首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >PushSharp 4.0.10.0:基于HTTP/2的苹果推送通知服务(APN)

PushSharp 4.0.10.0:基于HTTP/2的苹果推送通知服务(APN)
EN

Stack Overflow用户
提问于 2021-01-13 13:33:07
回答 1查看 4.6K关注 0票数 1

我们使用PushSharp 4.0.10发送iOS推送通知:https://github.com/Redth/PushSharp

最近,我们收到了来自苹果开发者的电子邮件:

“如果您仍然发送带有遗留二进制协议的推送通知,则是时候更新基于HTTP/2的Apple push notifications (APN)提供程序API了。您将能够利用强大的功能,如使用JSON Web令牌的身份验证、改进的错误消息传递和每次通知反馈。为了给您额外的准备时间,升级到APNs提供者API的截止日期已经延长到2021年3月31日。我们建议尽快升级,因为APN在此日期之后将不再支持遗留的二进制协议。”

我的问题是: PushSharp 4.0.10在2021年3月31日后还能工作吗?

EN

Stack Overflow用户

发布于 2021-02-22 14:44:09

有关于这个问题的讨论,但是线程已经关闭了。但是在这个线程上仍然有一些建议,您可能想尝试一下。

苹果推送通知服务(APN)将于2020年11月起不再支持遗留的二进制协议 https://github.com/Redth/PushSharp/issues/923

**编辑-2021年3月25日

截止日期已经接近,@Ashita询问了一些代码片段,因此我希望下面的内容可以节省您的时间。

将以下类dotAPNSService添加到项目中。您可以根据您的需要定制此结构。此外,在实现自己的推送通知服务时,我也没有将最好的编码C#标准作为重点。您可以实现LINQ、任务异步等。我测试了这个dotAPNS库,它运行得非常好。对于Android,您仍然可以使用PushSharp

在实现dotAPNSService助手类之前,从帐户获取以下信息。ApnsJwtOptions值应该是:

BundleId -您的应用程序的包ID。不应该包括特定的主题(即com.myapp而不是com.myapp.voip)。

CertFilePath -从开发人员中心下载的.p8证书的路径。

KeyId -从开发人员帐户中获得的10字符密钥ID。

TeamId -用于开发公司应用程序的10个字符的团队ID。从开发人员帐户中获取此值。

代码语言:javascript
运行
复制
public class dotAPNSService : IDisposable
{
    public event EventHandler OnTokenExpiredHandler;
    private ApnsJwtOptions options = null;
    
    public dotAPNSService()
    {
        options = new ApnsJwtOptions()
        {
            BundleId = "com.xx.xxxx",
            CertFilePath = "../../certificate.p8",
            KeyId = "The_Key_Id",
            TeamId = "The_Team_Id"
        };
    }

    public void SendNotifications(String[] deviceTokens, String title, String body)
    {
        if (deviceTokens == null || deviceTokens.Length <= 0)
        {
            return;
        }

        if (String.IsNullOrEmpty(title))
        {
            return;
        }

        if (String.IsNullOrEmpty(body))
        {
            return;
        }

        // once you've gathered all the information needed and created an options instance, it's time to call
        var apns = ApnsClient.CreateUsingJwt(new HttpClient(), options);

        // start the process     
        foreach (String deviceToken in deviceTokens)
        {
            var push = new ApplePush(ApplePushType.Alert)
                .AddAlert(title, body)
                .AddToken(deviceToken);

            Send(apns, push, deviceToken);
        }
    }

    public void SendSilentNotifications(String[] deviceTokens)
    {
        try
        {
            if (deviceTokens == null || deviceTokens.Length <= 0)
            {
                return;
            }

            // once you've gathered all the information needed and created an options instance, it's time to call
            var apns = ApnsClient.CreateUsingJwt(new HttpClient(), options);

            // start the process               
            foreach (String deviceToken in deviceTokens)
            {
                var push = new ApplePush(ApplePushType.Background)
                    .AddContentAvailable()
                    .AddToken(deviceToken);

                Send(apns, push, deviceToken);
            }
        }
        finally
        {

        }
    }

    private void Send(ApnsClient apns, ApplePush push, String deviceToken)
    {
        try 
        {
            var response = apns.SendAsync(push);
            if (response.Result.Reason == ApnsResponseReason.Success)
            {
                // the notification has been sent!
            }
            else 
            {
                Boolean removeToken = false;
                switch (response.Result.Reason)
                {
                    case ApnsResponseReason.BadDeviceToken:
                        removeToken = true;
                        break;
                    case ApnsResponseReason.TooManyRequests:
                        break;
                }

                // remove the token from database?
                if (removeToken)
                    OnTokenExpired(new ExpiredTokenEventArgs(deviceToken));
            }
        }
        catch (TaskCanceledException)
        {
            // ERROR - HTTP request timed out, you can use the deviceToken to log the error
        }
        catch (HttpRequestException ex)
        {
            // ERROR - HTTP request failed, you can use the deviceToken to log the error
        }
    }

    protected virtual void OnTokenExpired(ExpiredTokenEventArgs args)
    {
        try
        {
            EventHandler handler = OnTokenExpiredHandler;
            if (handler != null)
            {                    
                ISynchronizeInvoke target = handler.Target as ISynchronizeInvoke;
                if (target != null && target.InvokeRequired)
                    target.Invoke(handler, new object[] { this, args });
                else
                    handler(this, args);
            }
        }
        catch (Exception ex)
        {
           
        }
    }
}

这些是dotAPNSService助手类的命名空间:

代码语言:javascript
运行
复制
using System;
using System.ComponentModel;
using System.Net.Http;
using System.Threading.Tasks;
using dotAPNS;

为了在项目中使用dotAPNSService助手,只需从数据库中提取令牌,然后将它们传递给它。例如,要发送无声通知:

代码语言:javascript
运行
复制
public void SendScheduledSilentNotifications()
{
    try
    {
        IList<User> users = _accountService.GetUsers(true);
        if (users != null && users.Count > 0)
        {
            List<String> deviceTokens = new List<String>();
            foreach (User user in users)
            {
                if (!String.IsNullOrEmpty(user.DeviceToken))
                    deviceTokens.Add(user.DeviceToken);
            }
    
            if (deviceTokens.Count > 0)
            {
                using (dotAPNSService service = new dotAPNSService())
                {
                    service.OnTokenExpiredHandler += new EventHandler(OnTokenExpired);
                    service.SendSilentNotifications(deviceTokens.ToArray());
                }
            }
        }
    }
    finally
    {
    
    }
}

要从数据库中删除过期令牌,可以使用以下命令:

代码语言:javascript
运行
复制
private void OnTokenExpired(object sender, EventArgs e)
{
    if (e == null)
        return;

    if (e.GetType() == typeof(ExpiredTokenEventArgs))
    {
        var args = (ExpiredTokenEventArgs)e;
        User user = _accountService.GetUserByDeviceToken(args.Token);
        if (user != null)
        {
            user.DeviceToken = String.Empty;
            Boolean success = !(_accountService.SaveUser(user) == null);
            if (success)
                // INFO - expired device token has been removed from database
            else
                // INFO - something went wrong
        }   
    }
}

您可以从这里下载源代码:https://github.com/alexalok/dotAPNS

API现在一次发送数千个无声通知,没有延迟,没有崩溃等。希望这个代码片段能帮助并节省您的时间!

票数 2
EN
查看全部 1 条回答
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/65703015

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档