VoIP实现即时通话通知
2018-07-07 本文已影响38人
Nick_iOS
近日有朋友做即时通讯项目遇到了App被系统干掉后无法提醒的问题,刚开始最先想到推送,但推送只有一次,提示声也比较短,要像微信那样长时间响铃才行,结果找到了VoIP,这里做个集成笔记。
第一步:获取VoIP服务证书
和其他证书类似,不过VoIP证书不区分生产和测试环境,只有一个。 0获取VoIP证书.png下载证书voip.cer
第二步:工程配置
打开Push Notifications开关 和 Background Modes开关
1打开BackgroundModes.png
2打开推送开关.png
在Info.plist文件中增加如下键值对:
3Info.plist文件中添加VoIP.png
第三步:代码配置
在AppDelegate导入#import <PushKit/PushKit.h>
在- (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
参考文档:
https://www.jianshu.com/p/22ffe3816090
https://www.jianshu.com/p/f9bef7e7a4ab
https://oopsr.github.io/2016/06/20/voip/