携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第29天,[点击查看活动详情](juejin.cn/post/712312… "juejin.cn/post/712312…
近日有朋友做即时通讯项目遇到了App被系统干掉后无法提醒的问题,刚开始最先想到推送,但推送只有一次,提示声也比较短,要像微信那样长时间响铃才行,结果找到了VoIP,这里做个集成笔记。
第一步:获取VoIP服务证书
和其他证书类似,不过VoIP证书不区分生产和测试环境,只有一个。
0获取VoIP证书.png
下载证书voip.cer
第二步:工程配置
打开Push Notifications开关 和 Background Modes开关
2打开推送开关.png
在Info.plist文件中增加如下键值对:
3Info.plist文件中添加VoIP.png
第三步:代码配置
在AppDelegate导入#import
在- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 中进行初始化设置。
PKPushRegistry * voipRegistry = [[PKPushRegistry alloc]initWithQueue:dispatch_get_main_queue()]; voipRegistry.delegate = self; voipRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
接收Token的方法
- (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{ NSString *str = [NSString stringWithFormat:@"%@",credentials.token]; NSString * tokenStr = [[[str stringByReplacingOccurrencesOfString:@"<" withString:@""] stringByReplacingOccurrencesOfString:@">" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""]; NSLog(@"TOKEN = %@",tokenStr); }
接收消息的方法
- (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type { NSDictionary *dic = [payload.dictionaryPayload objectForKey:@"aps"]; NSLog(@"******************* push Kit %@***********************",dic); }
第四步:导出证书
1、将之前生成的voip.cer SSL证书双击导入钥匙串 2、打开钥匙串访问,在证书中找到对应voip.cer生成的证书,右键导出并选择.p12格式,这里我们命名为voippush.p12,这里导出需要输入密码(随意输入,别忘记了)。 3、目前我们有两个文件,voip.cer SSL证书和voippush.p12私钥,新建文件夹命名为VoIP、并保存两个文件到VoIP文件夹。 4、把.cer的SSL证书转换为.pem文件,打开终端命令行cd到VoIP文件夹、执行以下命令 openssl x509 -in voip.cer -inform der -out VoiPCert.pem 5、把.p12私钥转换成.pem文件,执行以下命令(这里需要输入之前导出设置的密码) openssl pkcs12 -nocerts -out VoIPKey.pem -in voippush.p12 6、再把生成的两个.pem整合到一个.pem文件中 cat VoiPCert.pem VoIPKey.pem > ck.pem 最终生成的ck.pem文件一般就是服务器用来推送的。
第五步:修改服务端代码
文件名:pushMe.php
<?php // Put your device token here (without spaces):填写App启动时获取的token $deviceToken = '9e5ea4c9956e7551cbb2f3de963006609c9d9c21ec09e2b4e07b0b80fda03c20'; // 导出.p12密钥时填写的密码 $passphrase = '123456'; // Put your alert message here: 填写推送内容 $message = 'MICHOI_M_CLOUDTALK_'; //////////////////////////////////////////////////////////////////////////////// $ctx = stream_context_create(); stream_context_set_option($ctx, 'ssl', 'local_cert', 'ck.pem'); stream_context_set_option($ctx, 'ssl', 'passphrase', $passphrase); stream_context_set_option($ctx, 'ssl', 'verify_peer', false); // Open a connection to the APNS server 推送环境,分开发环境和生产环境 // 开发环境地址:gateway.sandbox.push.apple.com:2195 // 生产环境地址:gateway.push.apple.com:2195 $fp = stream_socket_client('ssl://gateway.sandbox.push.apple.com:2195', $err,$errstr, 60, STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx); if (!$fp) exit("Failed to connect: $err $errstr" . PHP_EOL); echo 'Connected to APNS' . PHP_EOL; // Create the payload body $body['aps'] = array( 'content-available' => '1', 'alert' => $message, 'sound' => 'voip_call.caf', 'badge' => 10, ); // Encode the payload as JSON $payload = json_encode($body); // Build the binary notification $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload; // Send it to the server $result = fwrite($fp, $msg, strlen($msg)); if (!$result) echo 'Message not delivered' . PHP_EOL; else echo 'Message successfully delivered' . PHP_EOL; // Close the connection to the server fclose($fp); ?>
第六步:测试推送
cd 到VoIP文件夹中,输入: php pushMe.php 即可大功告成!!
4VoIP文件夹内容.png
5终端显示.png
6iPhone显示.png