• iOS Callkit与Pushkit 的使用手册总结,折腾了我5天烦死了。


    首先要说一下,callkit和pushkit的用途。我一开始误会了这个两货的用法导致浪费了很多时间。 callkit是可以让app调出打电话的页面,走打电话的流程,接听,挂掉。大概就是下图这样子。同时让这个通话能出现在通讯录里,所以这个功能一般用于app里的语音聊天,如果配合pushkit就可以实现在锁屏的情况下调出这个页面。

    这里我就来简单介绍一下如何集成CallKit与PushKit

    要集成,首先就要导入framework,图中的三个framework都要导入,第一个framework是从通讯录中直接拨打App电话所需要的。

    Pushkit

    首先从这个开始弄吧。

    去苹果账号里申请voip的证书,这个证书和普通的推送证书一样,不懂的直接百度一下吧。或者参考这个www.jianshu.com/p/c85a58ab4…

    然后在appdelegate里,导入

    1. #import <PushKit/PushKit.h>
    2. 复制代码

    然后,在didFinishLaunchingWithOptions里,初始化,并实现代理PKPushRegistryDelegate

    1. PKPushRegistry .*pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
    2. pushRegistry.delegate = self;
    3. pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
    4. 复制代码

    然后,实现代理方法。如果能收到token代表,配置成功,token配置成功后就可以让后台给你发推送了。

    - (void)pushRegistry:(PKPushRegistry *)registry didUpdatePushCredentials:(PKPushCredentials *)credentials forType:(NSString *)type{     NSLog(@"%@",credentials.token);     //应用启动获取token,并上传服务器     token = [[[[credentials.token description] stringByReplacingOccurrencesOfString:@"<"withString:@""] stringByReplacingOccurrencesOfString:@">" withString:@""] stringByReplacingOccurrencesOfString:@" " withString:@""]; }

    这个是接受推送的方法

    - (void)pushRegistry:(PKPushRegistry *)registry didReceiveIncomingPushWithPayload:(PKPushPayload *)payload forType:(NSString *)type

    至于你想测试推送,由于我个人是兼职java开发,看这个里测试的,blog.csdn.net/m0_37954663…

    Callkit

    关于这个我觉得比起我干讲,还是先附上demo 感谢这个大大的demo,看完大体上就知道怎么用 github.com/itomorrow/C…

    不过个人觉得还是有点复杂,简化了一下,大佬们都很喜欢搞一个CallKitManager来管理,但我并不需求这么复杂,能实现基础功能就完事了。 gitee.com/klkxxy/call…

    创建一个文件实现Callkit的代理CXProviderDelegate

    #import **@interface** ProviderDelegate : NSObject

    里面实现的代理方法,无非就是,接电话,挂电话,打电弧,静音这种功能。

    1. #import "ProviderDelegate.h"
    2. #import <AVFoundation/AVFAudio.h>
    3. @interface ProviderDelegate ()
    4. @property (nonatomic ,strong) CXProvider *provider;
    5. @end
    6. @implementation** ProviderDelegate
    7. static ProviderDelegate *shared = **nil**;
    8. + (instancetype)shared{
    9.     @synchronized(self) {
    10.         if (shared == nil) {
    11.             shared = [[ProviderDelegate alloc]init];
    12.         }
    13.         return shared;
    14.     } 
    15. }
    16. +(void)configureAudioSession{
    17.     NSLog(@"Callkit& Configuring audio session");
    18.     AVAudioSession *session = [AVAudioSession sharedInstance];
    19.     [session setCategory:AVAudioSessionCategoryPlayAndRecord error:**nil**];
    20.     [session setMode:AVAudioSessionModeVoiceChat error:**nil**];
    21. }
    22. //通过设置CXProviderConfiguration来支持视频通话、电话号码处理,并将通话群组的数字限制为 1 个,其实光看属性名大家也能看得懂吧。
    23. - (CXProviderConfiguration *)config{
    24.     **static** CXProviderConfiguration* configInternal = **nil**;
    25.     **static** dispatch_once_t onceToken;
    26.     dispatch_once(&onceToken, ^{
    27.         configInternal = [[CXProviderConfiguration alloc] initWithLocalizedName:@"我的"];
    28.         configInternal.supportsVideo = **NO**;
    29.         configInternal.maximumCallsPerCallGroup = 1;
    30.         configInternal.maximumCallGroups = 1;
    31.         configInternal.supportedHandleTypes = [NSSet setWithObject:@(CXHandleTypePhoneNumber)];
    32.         UIImage* iconMaskImage = [UIImage imageNamed:@"IconMask"];
    33.         configInternal.iconTemplateImageData = UIImagePNGRepresentation(iconMaskImage);
    34.         configInternal.ringtoneSound = @"voip_call.caf";
    35.     });
    36.     **return** configInternal;
    37. }
    38. - (**instancetype**)init{
    39.     **if** (**self**) {
    40.         //用一个 CXProviderConfiguration 初始化 CXProvider,前者在后面会定义成一个静态属性。CXProviderConfiguration 用于定义通话的行为和能力。
    41.         **self**.provider = [[CXProvider alloc]initWithConfiguration:**self**.config];
    42.         //为了能够响应来自于 CXProvider 的事件,你需要设置它的委托。
    43.         [**self**.provider setDelegate:**self** queue:**nil**];
    44.     }
    45.     **return** **self**;
    46. }
    47. //这个方法牛逼了,它是用来更新系统电话属性的。。
    48. -(CXCallUpdate *)callUpdate:(NSString *)handle andHasVideo:(BOOL)hasVideo{
    49.     CXCallUpdate *update = [[CXCallUpdate alloc]init];
    50.     update.localizedCallerName = @"aaaaaaaa";
    51.     update.supportsGrouping = **NO**;
    52.     update.supportsHolding = **NO**;
    53.     update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:handle];
    54.     update.hasVideo = hasVideo;
    55.     **return** update;
    56. }
    57. - (**void**)providerDidReset:(**nonnull** CXProvider *)provider {
    58. }
    59. - (**void**)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action{
    60.     //向系统通讯录更新通话记录
    61.     CXCallUpdate *update = [**self** callUpdate:action.handle.value andHasVideo:action.isVideo];
    62.     [provider reportCallWithUUID:action.callUUID updated:update];
    63.     [action fulfill];
    64. }
    65. - (**void**)provider:(CXProvider *)provider didActivateAudioSession:(AVAudioSession *)audioSession{
    66.     //一定要记得播放铃声呐。。
    67. }
    68. //打电话方法
    69. -(**void**)reportIncomingCall:(NSUUID *)uuid andHandle:(NSString *)handle andHasvideo:(**BOOL**)hasVideo andCompletion:(completion2)completion{
    70.     CXCallUpdate *update = [**self** callUpdate:handle andHasVideo:hasVideo];
    71.     [**self**.provider reportNewIncomingCallWithUUID:uuid update:update completion:^(NSError * **_Nullable** error) {
    72.         **if** (!error) {
    73.         }
    74.         
    75.         completion(error);
    76.     }];
    77. }
    78.  
    79. //接电话(按钮的返回)
    80. - (**void**)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action{
    81.     [ProviderDelegate configureAudioSession];
    82.     [action fulfill];
    83. }
    84. //挂电话的按钮,点击事件
    85. - (**void**)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action{
    86.     //在这里添加自己App挂断电话的逻辑
    87.     [action fulfill];
    88. }
    89. - (**void**)provider:(CXProvider *)provider performSetHeldCallAction:(CXSetHeldCallAction *)action{
    90.     [action fulfill];
    91. }
    92. @end
    93. 复制代码

    感觉看完上面大概就懂了吧。如果实在不懂,下载上面的demo体验一下。

    参考文档

    www.pianshen.com/article/110… www.jianshu.com/p/c85a58ab4…

    demo

    github.com/itomorrow/C…

    gitee.com/klkxxy/call…


    作者:庞然大虎
    链接:https://juejin.cn/post/7137601079348297741/
    来源:稀土掘金
    著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    这个是我的掘金账号,哈哈。 

  • 相关阅读:
    【数字IC验证快速入门】11、Verilog TestBench(VTB)入门
    java的集合进阶学习
    Python x-www-form-urlencoded post
    软考高级系统架构设计师系列之:详细快速掌握软考高级架构设计师考试全部知识点和典型例题上篇
    Hadoop中SecondaryNameNode工作机制
    Shopee店铺ID是什么?Shopee店铺id怎么看?——站斧浏览器
    【数据结构】广义表与二叉树之间的转换
    聊聊多包管理,杂谈,monorepo
    大数据培训课程之RDD传递一个属性
    java基础10题
  • 原文地址:https://blog.csdn.net/klkxxy/article/details/126609249