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/

上一篇下一篇

猜你喜欢

热点阅读