准备工作
如果需要在APP中使用远程推送消息服务,需要通过apple member center内开通推送服务,创建与APP相关联的APP ID、开发与发布证书,APNs服务的开发与发布证书等,在开发调试之前,参考下面图中相关步骤完成准备工作。
证书生成方法及账号配置可参考下面的苹果官方文档链接。
苹果相关指导文档:
Configuring Push Notifications
Local Notifications and Remote Notifications Programming Guide
概览
详细介绍
1.Register
在APP启动进入到Application launch接口时,调用注册API并且指定你感兴趣的推送通知类型,,iOS系统向APNs请求一个device token并且返回给APP。iOS 8.0之后注册接口稍有变化
-(void)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)options {
float sysVer = [[[UIDevice currentDevice] systemVersion] floatValue];
if (sysVer >= 8.0) {
if ([application respondsToSelector:@selector(registerUserNotificationSettings:)]) {
UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|
UIUserNotificationTypeAlert categories:nil];
[application registerUserNotificationSettings:settings];
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert;
[application registerForRemoteNotificationTypes:myTypes];
}
} else {
UIRemoteNotificationType myTypes = UIRemoteNotificationTypeBadge |UIRemoteNotificationTypeAlert;
[application registerForRemoteNotificationTypes:myTypes];
}
}
2.Send token
添加注册推送通知后,需要在AppDelegate.m中重写register notification相关回调方法,以获取APNs返回给此设备的Token,并将token通过APP自己的传输方式发送到APP所属Server上
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)token{
//Update token to your server
NSString* dt = [[token description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
NSLog(@"RegisterForRemoteNotifications success UDID = %@", dt);
}
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
//Check your provisioning profile for entitlements
//Push not supported in the simulator
NSLog(@"didFailToRegisterForRemoteNotifications");
}
需要注意的是在iOS8.0之后,需要先实现下面的方法及调用内容,上面的两个方法才会被调用
// This callback will be made upon calling -[UIApplication registerUserNotificationSettings:]. The settings the user has granted to the application will be passed in as the second argument.
- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings
{
[application registerForRemoteNotifications];
}
Device Token并不等同于UDID标识,它不是永久不变的,当iOS设备系统内容重置等情况下可能会发生变化,因此苹果官方建议在每次APP Launch时都要调用注册并检查一下token,如果发生变化应及时通知Server更新
3.Push notification to APNs(Server‘s Job)
Your Server需要一个有效证书才能和APNs连接(这个证书含有目标APP的Bundle identifier信息,前面已经介绍)。与APNs连接后,Your Server向APNs发送的通知带有设备token(由目标APP连接Your Server后发来的token),APNs以此找到目标设备,然后看目标设备里的目标程序有接受推送的证书,APNs以此验证通过后,发送通知给目标设备。
通知(Notification)Binary结构
其中APS dic保留Sound、Badge、Alert Keys,支持自定义,最大长度256bytes
装载信息(Payload Message)JSON结构
其中APS dic保留Sound、Badge、Alert Keys,支持自定义,最大长度256bytes
载荷信息(Payload Message)Alert自定义
Server与APNs通信相关开源代码
C#开源 APNS-Sharp
java开源 javapns
OC开源 APNS-Pusher
4.Receive notification and dilivery
当Server成功发送一个通知到APNs并且验证通过后,APNs根据指定的Token发送通知到目标设备,此时目标设备有以下几种状态:
如果应用程序 isn't running,
iOS会处理这个消息,比如弹出一个框、在应用程序的icon上显示红色数字等。
如果用户此时通过点击弹框进入程序,iOS会启动程序调用application:didFinishLaunchingWithOptions,并且launchOptions包含远程消息的payload.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions {
NSDictionary* payload = [launchOptions objectForKey:UIApplicationLaunchOptionsRemoteNotificationKey];
if (payload){
NSLog(@"startup from remote notification: %@",[payload description]);
....
}
}
如果用户直接点击app icon进入程序,iOS会启动程序并同样调用application:didFinishLaunchingWithOptions,但是launchOptions不包含远程消息的payload。
如果应用程序is running in the foreground
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)payload{
NSLog(@"foreground remote notification: %@",[payload description]);
...
}
如果应用程序is running in the background
同样弹框,然后如果通过弹框进入程序,就会调用application:didReceiveRemoteNotification.
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)payload{
NSLog(@"background remote notification: %@",[payload description]);
...
}