iOS APNS 客户端实现流程与代码(附详细说明)
前言
APNS 全称 Apple Push Notification Server ,是iOS设备的推送机制。
由于iOS系统机制,iOS系统只允许四种类型的APP可以在后台保持一段时间,但是这个保持又受制于当前手机的内存。当前内存不足时,就不能保证APP的保护。四种类型的APP是:音乐播放,地图导航,VOiP电话,报刊下载。那么对于绝大多说的APP来说,APNS推送机制就成为了最好的选择,当然APNS也存在一定的问题,由于苹果服务器等相关原因,有的时候会存在无法即时收到推送消息的情况,甚至会出现丢失消息的情况。
业务流程
第一阶段:应用程序把要发送的消息、目的iPhone的标识打包,发给APNS。
第二阶段:APNS在自身的已注册Push服务的iPhone列表中,查找有相应标识的iPhone,并把消息发送到iPhone。
第三阶段:iPhone把发来的消息传递给相应的应用程序,并且按照设定弹出Push通知。
1、应用程序注册消息推送。
2、iOS从APNS Server获取device token,应用程序接收device token。
3、应用程序将device token发送给PUSH服务端程序。
4、服务端程序向APNS服务发送消息。
5、APNS服务将消息发送给iPhone应用程序。
实现代码
注册APNS通知
+ (void)registerNotificationToAppleServer:(NSDictionary *)launchOptions {
//注册通知
if ([UIDevice currentDevice].systemVersion.doubleValue<8.0) {
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeBadge)];
}
else {
[[UIApplication sharedApplication] registerForRemoteNotifications];
[[UIApplication sharedApplication] registerUserNotificationSettings:[UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeBadge|UIUserNotificationTypeSound|UIUserNotificationTypeAlert categories:nil]];
}
}
APNS 相关代理方法
该方法是获取DeviceToken的协议方法,当APP启动后,才会调用该方法。DeviceToken 是设备令牌,只有当前设备的系统重装,才会发生改变,是标示设备的唯一标识符,苹果服务器即通过该标识符进行确认推送的APP。
#pragma mark - APNS Delegate
- (void)application:(UIApplication *)app didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
NSString *deviceTokenString2 = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""]
stringByReplacingOccurrencesOfString:@">" withString:@""]
stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"Token 字符串:%@", deviceTokenString2);
self.deviceToken = deviceTokenString2;
//这里应将device token发送到服务器端
}
DeviceToken 转换为 NSString 的两种方法:(一般向服务器上传DeviceToken时,都是需要进行相关处理)
// 将deviceToken转换成字符串
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
{
// 方式1
NSMutableString *deviceTokenString1 = [NSMutableString string];
const char *bytes = deviceToken.bytes;
int iCount = deviceToken.length;
for (int i = 0; i < iCount; i++) {
[deviceTokenString1 appendFormat:@"%02x", bytes[i]&0x000000FF];
}
NSLog(@"方式1:%@", deviceTokenString1);
// 方式2
NSString *deviceTokenString2 = [[[[deviceToken description] stringByReplacingOccurrencesOfString:@"<"withString:@""]
stringByReplacingOccurrencesOfString:@">" withString:@""]
stringByReplacingOccurrencesOfString:@" " withString:@""];
NSLog(@"方式2:%@", deviceTokenString2);
}
该方法是注册APNS或者获取DeviceToken失败时调用的方法,在该地方进行相关处理。
- (void)application:(UIApplication *)app didFailToRegisterForRemoteNotificationsWithError:(NSError *)error {
NSString *error_str = [NSString stringWithFormat: @"%@", error];
NSLog(@"Failed to get token, error:%@", error_str);
}
收到APNS推送的消息,该方法只有当APP处在前端时,收到APNS推送消息时才会调用该方法,若是APNS处在后台状态,无论是挂起状态,还是已经被释放,再或者是刚推出在后台时,程序还活跃状态时,都不会调用该方法,而是直接推送出通知的。
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo
{
NSLog(@"APNS 收到 信息 %@", userInfo);
for (id key in userInfo) {
NSLog(@"key: %@, value: %@", key, [userInfo objectForKey:key]);
}
/* eg.
key: aps, value: {
alert = "\U8fd9\U662f\U4e00\U6761\U6d4b\U8bd5\U4fe1\U606f";
badge = 1;
sound = default;
}
*/
// NSInteger badge = [UIApplication sharedApplication].applicationIconBadgeNumber;
// [UIApplication sharedApplication].applicationIconBadgeNumber = badge;
}
对于DeviceToken的上传,都是需要根据业务逻辑进行操作的,但是基本的上传操作,我想大家都应该没有什么问题,我是使用AFNetWorking将相关信息POST到服务器,并且我是将DeviceToken转换为NSString上传的,当然也可以直接上传二进制字节流。
对于服务器向Apple Server传送消息的时候,badge 该字段是APP图标个数,传递过来是几就会显示几,由于有些时候APP挂起时,无法对该字段进行处理,所以需要与服务器沟通。不要让该字段数字错误。
sound 字段是提示音,设置为 default 时就会与当前手机系统的设置保持一致。
对 iPhone 内手机提示音的文件说明,代码说明请看我的下一篇文档,我会把我了解到的进行说明。
证书这一块,就是要单独申请一个推送证书,由于苹果的开发者网站变得比较快,这一块我也不是很熟悉。就不介绍了,给大家几个我觉得不错链接就好了。