iOS APNS 客户端实现流程与代码

前言

APNS 全称 Apple Push Notification Server ,是iOS设备的推送机制。

 由于iOS系统机制,iOS系统只允许四种类型的APP可以在后台保持一段时间,但是这个保持又受制于当前手机的内存。当前内存不足时,就不能保证APP的保护。四种类型的APP是:音乐播放,地图导航,VOiP电话,报刊下载。那么对于绝大多说的APP来说,APNS推送机制就成为了最好的选择,当然APNS也存在一定的问题,由于苹果服务器等相关原因,有的时候会存在无法即时收到推送消息的情况,甚至会出现丢失消息的情况。

推送通知分类

推送通知分为本地推送与远程推送

本地推送最大推送数量是64个,超过这个数量会被忽略

本地推送:不需要联网也可以推送,是开发人员在APP内设定特定的时间来提醒用户干什么

本地通知与远程通知都可以向不在前台运行的应用发送消息,这种消息既可能是即将发生的事件,也可能是服务器的新数据,不管是本地还是远程通知,他们在界面上的显示效果是相同的。

二者的区别是本地推送是由本应用负责调用,只能从当前设备上的iOS发出。而远程推送是由服务器来控制。

业务流程

第一阶段:应用程序把要发送的消息、目的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 内手机提示音的文件说明,代码说明请看我的下一篇文档,我会把我了解到的进行说明。 证书这一块,就是要单独申请一个推送证书,由于苹果的开发者网站变得比较快,这一块我也不是很熟悉。就不介绍了,给大家几个我觉得不错链接就好了。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享