首先要说一下,callkit和pushkit的用途。我一开始误会了这个两货的用法导致浪费了很多时间。 callkit是可以让app调出打电话的页面,走打电话的流程,接听,挂掉。大概就是下图这样子。同时让这个通话能出现在通讯录里,所以这个功能一般用于app里的语音聊天,如果配合pushkit就可以实现在锁屏的情况下调出这个页面。
这里我就来简单介绍一下如何集成CallKit与PushKit
要集成,首先就要导入framework,图中的三个framework都要导入,第一个framework是从通讯录中直接拨打App电话所需要的。
Pushkit
首先从这个开始弄吧。
去苹果账号里申请voip的证书,这个证书和普通的推送证书一样,不懂的直接百度一下吧。或者参考这个www.jianshu.com/p/c85a58ab4…
然后在appdelegate里,导入
- #import <PushKit/PushKit.h>
- 复制代码
然后,在didFinishLaunchingWithOptions里,初始化,并实现代理PKPushRegistryDelegate
- PKPushRegistry .*pushRegistry = [[PKPushRegistry alloc] initWithQueue:dispatch_get_main_queue()];
- pushRegistry.delegate = self;
- pushRegistry.desiredPushTypes = [NSSet setWithObject:PKPushTypeVoIP];
- 复制代码
然后,实现代理方法。如果能收到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
里面实现的代理方法,无非就是,接电话,挂电话,打电弧,静音这种功能。
- #import "ProviderDelegate.h"
- #import <AVFoundation/AVFAudio.h>
- @interface ProviderDelegate ()
- @property (nonatomic ,strong) CXProvider *provider;
- @end
-
- @implementation** ProviderDelegate
- static ProviderDelegate *shared = **nil**;
- + (instancetype)shared{
- @synchronized(self) {
- if (shared == nil) {
- shared = [[ProviderDelegate alloc]init];
- }
- return shared;
- }
- }
-
- +(void)configureAudioSession{
- NSLog(@"Callkit& Configuring audio session");
- AVAudioSession *session = [AVAudioSession sharedInstance];
- [session setCategory:AVAudioSessionCategoryPlayAndRecord error:**nil**];
- [session setMode:AVAudioSessionModeVoiceChat error:**nil**];
-
- }
-
- //通过设置CXProviderConfiguration来支持视频通话、电话号码处理,并将通话群组的数字限制为 1 个,其实光看属性名大家也能看得懂吧。
- - (CXProviderConfiguration *)config{
- **static** CXProviderConfiguration* configInternal = **nil**;
- **static** dispatch_once_t onceToken;
- dispatch_once(&onceToken, ^{
- configInternal = [[CXProviderConfiguration alloc] initWithLocalizedName:@"我的"];
- configInternal.supportsVideo = **NO**;
- configInternal.maximumCallsPerCallGroup = 1;
- configInternal.maximumCallGroups = 1;
- configInternal.supportedHandleTypes = [NSSet setWithObject:@(CXHandleTypePhoneNumber)];
- UIImage* iconMaskImage = [UIImage imageNamed:@"IconMask"];
- configInternal.iconTemplateImageData = UIImagePNGRepresentation(iconMaskImage);
- configInternal.ringtoneSound = @"voip_call.caf";
-
- });
- **return** configInternal;
- }
-
- - (**instancetype**)init{
- **if** (**self**) {
- //用一个 CXProviderConfiguration 初始化 CXProvider,前者在后面会定义成一个静态属性。CXProviderConfiguration 用于定义通话的行为和能力。
- **self**.provider = [[CXProvider alloc]initWithConfiguration:**self**.config];
- //为了能够响应来自于 CXProvider 的事件,你需要设置它的委托。
- [**self**.provider setDelegate:**self** queue:**nil**];
- }
- **return** **self**;
- }
-
-
- //这个方法牛逼了,它是用来更新系统电话属性的。。
- -(CXCallUpdate *)callUpdate:(NSString *)handle andHasVideo:(BOOL)hasVideo{
- CXCallUpdate *update = [[CXCallUpdate alloc]init];
- update.localizedCallerName = @"aaaaaaaa";
- update.supportsGrouping = **NO**;
- update.supportsHolding = **NO**;
- update.remoteHandle = [[CXHandle alloc] initWithType:CXHandleTypePhoneNumber value:handle];
- update.hasVideo = hasVideo;
- **return** update;
- }
-
-
- - (**void**)providerDidReset:(**nonnull** CXProvider *)provider {
-
-
- }
-
-
- - (**void**)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action{
- //向系统通讯录更新通话记录
- CXCallUpdate *update = [**self** callUpdate:action.handle.value andHasVideo:action.isVideo];
- [provider reportCallWithUUID:action.callUUID updated:update];
- [action fulfill];
- }
-
-
- - (**void**)provider:(CXProvider *)provider didActivateAudioSession:(AVAudioSession *)audioSession{
- //一定要记得播放铃声呐。。
-
- }
-
-
- //打电话方法
-
- -(**void**)reportIncomingCall:(NSUUID *)uuid andHandle:(NSString *)handle andHasvideo:(**BOOL**)hasVideo andCompletion:(completion2)completion{
-
- CXCallUpdate *update = [**self** callUpdate:handle andHasVideo:hasVideo];
- [**self**.provider reportNewIncomingCallWithUUID:uuid update:update completion:^(NSError * **_Nullable** error) {
- **if** (!error) {
-
- }
-
-
-
- completion(error);
-
- }];
-
- }
-
-
-
- //接电话(按钮的返回)
-
- - (**void**)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action{
- [ProviderDelegate configureAudioSession];
- [action fulfill];
-
- }
-
-
- //挂电话的按钮,点击事件
- - (**void**)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action{
- //在这里添加自己App挂断电话的逻辑
-
- [action fulfill];
-
- }
-
- - (**void**)provider:(CXProvider *)provider performSetHeldCallAction:(CXSetHeldCallAction *)action{
- [action fulfill];
-
- }
-
- @end
- 复制代码
感觉看完上面大概就懂了吧。如果实在不懂,下载上面的demo体验一下。
参考文档
www.pianshen.com/article/110… www.jianshu.com/p/c85a58ab4…
demo
作者:庞然大虎
链接:https://juejin.cn/post/7137601079348297741/
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。
这个是我的掘金账号,哈哈。