苹果原生远程推送

一、通过证书助手,苹果官网生成了3个文件
1、PushChat.certSigningRequest
2、PushChatKey.p12
3、aps_developer_identity.cer

二、在AppDelegate中的didFinishLaunchingWithOptions方法中加入下面代码,通过registerForRemoteNotificationTypes方法,告诉应用程序,能接受push来的通知:

// iOS8.0 以上在AppDelegate.m 中,并且遵循协议UNUserNotificationCenterDelegate
#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import 
#endif

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [self replyPushNotificationAuthorization:application];
    return YES;
}


- (void)replyPushNotificationAuthorization:(UIApplication *)application{
    if (IOS10_OR_LATER) {
        //iOS 10 later
        UNUserNotificationCenter *center = [UNUserNotificationCenter currentNotificationCenter];
        //必须写代理,不然无法监听通知的接收与点击事件
        center.delegate = self;
        [center requestAuthorizationWithOptions:(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert) completionHandler:^(BOOL granted, NSError * _Nullable error) {
            if (!error && granted) {
                //用户点击允许
                NSLog(@"注册成功");
            } else {
                //用户点击不允许
                NSLog(@"注册失败");
            }
        }];
 
        // 可以通过 getNotificationSettingsWithCompletionHandler 获取权限设置
        //之前注册推送服务,用户点击了同意还是不同意,以及用户之后又做了怎样的更改我们都无从得知,现在 apple 开放了这个 API,我们可以直接获取到用户的设定信息了。注意UNNotificationSettings是只读对象哦,不能直接修改!
        [center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings * _Nonnull settings) {
            NSLog(@"========%@",settings);
//打印结果 ========        
        }];
    } else if (IOS8_OR_LATER) {
        //iOS 8 - iOS 10系统
        UIUserNotificationSettings *settings = [UIUserNotificationSettings settingsForTypes:UIUserNotificationTypeAlert | UIUserNotificationTypeBadge | UIUserNotificationTypeSound categories:nil];
        [application registerUserNotificationSettings:settings];
    } else {
        //iOS 8.0系统以下
        [application registerForRemoteNotificationTypes:UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeSound];
    }
 
    //注册远端消息通知获取device token
    [application registerForRemoteNotifications];
}

三、注册结果回调

#pragma mark - 获取device Token
//获取DeviceToken成功
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken{
 
    //解析NSData获取字符串
    //我看网上这部分直接使用下面方法转换为string,你会得到一个nil(别怪我不告诉你哦)
    //错误写法
    //NSString *string = [[NSString alloc] initWithData:deviceToken encoding:NSUTF8StringEncoding];
 
 
    //正确写法
    NSString *deviceString = [[deviceToken description] stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"<>"]];
    deviceString = [deviceString stringByReplacingOccurrencesOfString:@" " withString:@""];
 	// 然后将获得的deviceString传给服务器
    NSLog(@"deviceToken===========%@",deviceString);
}
 
//获取DeviceToken失败
- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error{
    NSLog(@"[DeviceToken Error]:%@\n",error.description);
}

四、收到推送后回调方法

// 处理远程消息
// 调用时机:App处于前台收到推送;在iOS7后,开启了 Remote Notification,App处于后台收到推送。
// 方法二是在iOS 7之后新增的方法,可以说是 方法一 的升级版本,如果app最低支持iOS 7的话可以不用添加 方法一了。
//- (void)application:(UIApplication *)application //didReceiveRemoteNotification:(NSDictionary *)userInfo
//{
//    NSLog(@"userinfo:%@",userInfo);
//    NSLog(@"收到推送消息:%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);
//}

// 其中completionHandler这个block可以填写的参数UIBackgroundFetchResult是一个枚举值。主要是用来在后台状态下进行一些操作的,比如请求数据,操作完成之后,必须通知系统获取完成,可供选择的结果有
- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
    NSLog(@"userinfo:%@",userInfo);
    NSLog(@"收到推送消息:%@",[[userInfo objectForKey:@"aps"] objectForKey:@"alert"]);
    
    completionHandler(UIBackgroundFetchResultNewData);
//    typedef NS_ENUM(NSUInteger, UIBackgroundFetchResult) {
//        UIBackgroundFetchResultNewData,
//        UIBackgroundFetchResultNoData,
//        UIBackgroundFetchResultFailed
//    }
}


// iOS10.0之后,新增两个方法。原来的方法还是需要实现的,各自的调用时机不一样。
// App处于前台接收到通知
- (void)userNotificationCenter:(UNUserNotificationCenter *)center willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler {
    if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
        NSLog(@"iOS10 收到远程通知");
    }else {
        // 判断为本地通知
        NSLog(@"iOS10 收到本地通知");
    }
    
    // 在前台默认不显示推送,如果要显示,就要设置以下内容
    // 微信设置里-新消息通知-微信打开时-声音or振动  就是该原理
    // 需要执行这个方法,选择是否提醒用户,有Badge、Sound、Alert三种类型可以设置
    completionHandler(UNNotificationPresentationOptionBadge|
                      UNNotificationPresentationOptionSound|
                      UNNotificationPresentationOptionAlert);
}

// 点击通知后会调用
- (void)userNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler:(void (^)())completionHandler {
    completionHandler(UIBackgroundFetchResultNewData);
    NSDictionary *userInfo = response.notification.request.content.userInfo;
    //程序关闭状态点击推送消息打开 可以在App启动方法的launchOptions获知
    if (self.isLaunchedByNotification) {
        //TODO
    } else{
        //前台运行
        if ([UIApplication sharedApplication].applicationState == UIApplicationStateActive) {
            //TODO
        }  else{  //后台挂起时
            //TODO
        }
        //收到推送消息手机震动,播放音效
        AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
        AudioServicesPlaySystemSound(1007);
    }
    //设置应用程序角标数为1
    [UIApplication sharedApplication].applicationIconBadgeNumber = 1;
    
    // 此处必须要执行下行代码,不然会报错
    completionHandler();
}

五、除了deviceToken之外,服
务器还需要一个与APNS连接的证书。这个证书可以通过我们前面生成的两个文件中得到。

使用OpenSSL生成服务器和APNS通信的证书文件。

1、将aps_developer_identity.cer转换成 aps_developer_identity.pem格式。

openssl x509 -in aps_developer_identity.cer -inform DER -out aps_developer_identity.pem -outform PEM

2、将p12格式的私钥转换成pem,需要设置4次密码,这里密码都设置为:abc123。

openssl pkcs12 -nocerts -out PushChat_Noenc.pem -in PushChat.p12

3、用certificate和the key 创建PKCS#12格式的文件。

openssl pkcs12 -export -in aps_developer_identity.pem -inkey PushChat_Noenc.pem -certfile PushChat.certSigningRequest -name “aps_developer_identity” -out aps_developer_identity.p12

这样我们就得到了在服务器中使用的证书文件:aps_developer_identity.p12。

整个推送流程如下:苹果原生远程推送_第1张图片
参考链接:https://www.jianshu.com/p/3fc46a8764ed

你可能感兴趣的:(iOS)