PushSharp如何向APNS发送消息

Spiga

使用PushSharp给iOS应用推送消息

2013-12-14 11:21 by 囧月, 1435 阅读, 16 评论, 收藏, 编辑

PushSharp是一个C#编写的服务端类库,用于推送消息到各种客户端,支持iOS(iPhone/iPad)、Android、Windows Phone、Windows 8、Amazo、Blackberry等设备。

官方网站:https://github.com/Redth/PushSharp

当前最新稳定版本为2.0.4,支持通过NuGet获取(https://www.nuget.org/packages/PushSharp/)

 

主要特点

提供了易于使用的API,支持以下平台的消息推送:

100%的托管代码完全兼容Mono平台。

 

安装

PushSharp主要包含以下程序集:

  • PushSharp.Core:(必选)核心组件
  • PushSharp.Apple:APNS,用于iOS及OSX
  • PushSharp.Android:C2DM及GCM,用于Android设备
  • PushSharp.Windows:用于Windows 8
  • PushSharp.WindowsPhone:用于WP设备
  • PushSharp.Amazon.Adm:用于Amazon的设备
  • PushSharp.Blackberry:用于黑莓设备
  • PushSharp.Google.Chrome:用于Chrome

其中,PushSharp.Core为必须的组件,其他的可以根据自己需要来选择对应平台。

平常使用只需要用NuGet来获取程序集即可:

1
Install-Package PushSharp

这样会把主流平台的程序集(Apple/Android/Windows/WindowsPhone)都下载下来,可以根据自己需要删除用不到的平台组件。

假如需要使用Blackberry等NuGet包里没有的组件,则需要到官方网站(https://github.com/Redth/PushSharp)获取源码自行编译。

对于Apple平台,只需要PushSharp.Core和PushSharp.Apple组件即可。

 

证书配置

官方WIKI提供了详细的证书配置步骤:

 

Apple平台证书创建流程:

  • 创建AppID
  • 为AppID配置用于APP签名的证书:分别有开发环境(Development)和生产环境(Production)的证书
  • 编辑AppID启用消息推送
  • 为AppID创建用于消息推送(APNS)的证书(包括Development和Production)
  • 下载以上证书并安装到Key Chain(钥匙串)
  • 导出用于消息推送(APNS)的证书为.p12格式,并为它设置密码:用于在服务端推送消息

 

对于Apple平台需要特别说明:

  • Provisioning Protal现在已经变成了Certificates, Identifiers & Profiles,可以从Member Center点进去或者iOS Developer Center找到
  • 对于已经发布的APP要启用消息推送功能,需要在Identifiers – App IDs找到对应的ID创建好APNS证书之后,再重新生成用于APP签名的证书,否则用于注册消息推送的代码(RegisterForRemoteNotificationTypes)不会正常工作,即返回的deviceToken为null
  • 在使用Development证书调试应用程序时服务端需要使用Development APNS证书来推送消息,使用Production证书发布到AppStore后推送消息需要使用Production APNS证书来推送消息

 

客户端启用消息推送

启用消息推送都是在AppDelegate里注册来完成的。

对于使用objc语言编写的客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
- ( BOOL )application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
     if (application.enabledRemoteNotificationTypes == UIRemoteNotificationTypeNone)
     {
         [application registerForRemoteNotificationTypes:
          UIRemoteNotificationTypeAlert |
          UIRemoteNotificationTypeBadge |
          UIRemoteNotificationTypeSound];
     }
     application.applicationIconBadgeNumber = -1;
     // Override point for customization after application launch.
     return YES;
}
 
- ( void )application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
     NSString *pushToken = [[[[deviceToken description]
                              stringByReplacingOccurrencesOfString:@ "<" withString:@ "" ]
                             stringByReplacingOccurrencesOfString:@ ">" withString:@ "" ]
                            stringByReplacingOccurrencesOfString: @ " " withString: @ "" ];
     [[NSUserDefaults standardUserDefaults] setObject:pushToken forKey:@ "pushtoken" ]; // 保存起来
}

对于使用MonoTouch的客户端:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
     app.RegisterForRemoteNotificationTypes(
         UIRemoteNotificationType.Alert |
         UIRemoteNotificationType.Badge |
         UIRemoteNotificationType.Sound);
     app.ApplicationIconBadgeNumber = -1;
     // ...
     return true ;
}
 
public override void RegisteredForRemoteNotifications(UIApplication application, NSData deviceToken)
{
     // 成功接收到用于消息推送的token
     string tokenStr = token.Description;
     string pushToken = tokenStr.Replace( "<" , string .Empty).Replace( ">" , string .Empty).Replace( " " , string .Empty);
     NSUserDefaults.StandardUserDefaults.SetString(pushToken, "pushtoken" );
}
 
public override void FailedToRegisterForRemoteNotifications(UIApplication application, NSError error)
{
     // 消息推送注册失败
}
 
public override void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> completionHandler)
{
     // 接收到推送的消息
     // 在iOS7可能需要开启Background Modes的Remote Notifications
}

在接收到deviceToken的时候先存储在NSUserDefaults中,在用户登录的时候再取出来一起发送到服务端:

1
2
NSString *pushToken = [[NSUserDefaults standardUserDefaults] stringForKey: @"pushtoken" ]; //objc
string pushToken = NSUserDefaults.StandardUserDefaults.StringForKey( "pushtoken" ); //MonoTouch

服务端在用户登录成功之后,把接收到用户的用户名与pushToken关联起来,在推送消息的时候就可以针对指定用户来推送,具体的过程略。

而对于不需要用户登录的app,可以在接收到deviceToken的时候直接发送到服务端。

更多的客户端配置参考PushSharp源码的Client.SamplesPushSharp.Client目录。

 

服务端推送消息

1
2
3
4
5
6
7
8
9
var pusher = new PushBroker();
pusher.RegisterAppleService( new ApplePushChannelSettings(File.ReadAllBytes( "yourAppId.p12" ), "证书的密码" ));
pusher.QueueNotification(
                 new AppleNotification()
                     .ForDeviceToken(pushToken) // 从数据库等地方获取设备的pushToken
                     .WithAlert( "测试iOS消息推送 - 囧月" )
                     .WithBadge(1)
                     .WithSound( "default" )
             );

在RegisterAppleService方法中可以注册多个APNS证书,PushSharp可以自动检测是Development/Production,这时候需要为证书设置标识:

1
2
pusher.RegisterAppleService( new ApplePushChannelSettings(File.ReadAllBytes( "yourAppId.p12" ), "证书的密码" ), "证书标识如youAppId_development" );
pusher.RegisterAppleService( new ApplePushChannelSettings(File.ReadAllBytes( "yourAppId.p12" ), "证书的密码" ), "证书标识如youAppId_production" );

此外,可以注册各种事件来获得各种状态:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
pusher.OnDeviceSubscriptionChanged += pusher_OnDeviceSubscriptionChanged;
pusher.OnDeviceSubscriptionExpired += pusher_OnDeviceSubscriptionExpired;
pusher.OnNotificationSent += pusher_OnNotificationSent;
pusher.OnNotificationFailed += pusher_OnNotificationFailed;
pusher.OnNotificationRequeue += pusher_OnNotificationRequeue;
pusher.OnChannelCreated += pusher_OnChannelCreated;
pusher.OnChannelDestroyed += pusher_OnChannelDestroyed;
pusher.OnChannelException += pusher_OnChannelException;
pusher.OnServiceException += pusher_OnServiceException;
 
static void pusher_OnNotificationFailed( object sender, INotification notification, Exception error)
{
     var n = (AppleNotification)notification;
     //error.Message ...获取推送出错的信息
}
 
static void pusher_OnNotificationSent( object sender, INotification notification)
{
     //消息推送成功后
     var n = (AppleNotification)notification;
     //n.Payload.Alert.Body  获取推送的消息内容...
}
 
static void pusher_OnDeviceSubscriptionExpired( object sender, string expiredSubscriptionId, DateTime expirationDateUtc, INotification notification)
{
     // 从数据库删除过期的expiredSubscriptionId
}
 
static void pusher_OnDeviceSubscriptionChanged( object sender, string oldSubscriptionId, string newSubscriptionId, INotification notification)
{
     // 把数据库中的oldSubscriptionId更新为newSubscriptionId
}

更多请参考源码的PushSharp.Sample目录。

 

参考

官方网站:https://github.com/Redth/PushSharp 可以获取最新源码及各种例子

WIKI:https://github.com/Redth/PushSharp/wiki  详细说明了各平台证书配置的方法

Xamarin相关文档:http://docs.xamarin.com/guides/cross-platform/application_fundamentals/notifications/ios/remote_notifications_in_ios/ 

作者:囧月
出处:http://lwme.cnblogs.com/
本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

7
0
(请您对文章做出评价)
« 上一篇: 使用MonoTouch.Dialog简化iOS界面开发
Add your comment
  1. #1楼 walleyekneel   2013-12-14 15:44
    楼主有没有试过繁体发送是乱码
  2. #2楼[楼主] 囧月   2013-12-14 16:48
    @walleyekneel
    没有测试过繁体中文..
  3. #3楼 小鸡哥   2013-12-14 20:54
    这个牛叉
  4. #4楼 cry   2013-12-14 21:38
    mark
  5. #5楼 6572789   2013-12-15 13:44
    不错,收藏了
  6. #6楼 银河使者   2013-12-15 21:55
    这个在Mono上测试过吗,可以在Linux或Mac OS X上运行吗
  7. #7楼 deerchao   2013-12-15 22:58
    请教下,用这个方案的话,对Android设备在国内实际效果如何(会不会被伟大的墙干扰造成不稳定)?
  8. #8楼 sunlovesea   2013-12-16 08:32
    牛!!!!!是否支持PhoneGap这类打包的WebAPP呢?
  9. #9楼 llllboy   2013-12-16 08:59
    MARK
  10. #10楼 城岸   2013-12-16 09:05
    多线程下不知道什么原因会一起卡在那里(Win8下不会),无法解决,只好放弃它了,用回APNS-sharp.
  11. #11楼 上帝的病人   2013-12-16 09:10
    不太稳定, 有时候能收到通知,有时候不能
  12. #12楼[楼主] 囧月   2013-12-16 09:19
    @银河使者
    这个不用怀疑Mono的能力
    @deerchao
    Android用Google的服务在国内稳定性估计很差,国内有不少的厂商提供的替代方案像“百度云推送”之类的可靠性比较好
    @sunlovesea
    支持,这个只是服务端的库,客户端用什么框架没影响的,可以参考这个: http://devgirl.org/2013/07/17/tutorial-implement-push-notifications-in-your-phonegap-application/
    @城岸
    APNS-Sharp和PushSharp是同一个作者啊,而且APNS-Sharp早已经obsolete/deprecated了
  13. #13楼 城岸   2013-12-16 09:21
    嗯,我就是先使用APNS-Sharp,后想升级到PushSharp。
  14. #14楼[楼主] 囧月   2013-12-16 10:05
    @上帝的病人
    有在这些事件里记录日志了么?是Apple的服务器那边的问题还是什么问题?
    @城岸
    新的功能还退化了?..跟作者反馈一下看看
  15. #15楼 euler   2013-12-16 10:34
    Great API!
  16. #16楼 银河使者   2013-12-24 22:31
    @sunlovesea
    PhoneGap可以调用Android Java API
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值