CallKit 是一个iOS10新框架,用于改善 VoIP 的体验,允许 App 和原生的 Phone UI 紧密集成,你的 App 将能够:
CallKit 通话流程如下图:
- (instancetype)init; //在私有串行队列创建.
- (instancetype)initWithQueue:(dispatch_queue_t)queue; //指定队列里创建.默认主线程 //指定使用
@property (nonatomic, readonly, strong) CXCallObserver *callObserver; //电话信息观察者
{
CXCallObserver类 :随时捕获电话信息的更新
一个方法:- (void)setDelegate:(nullable id
一个代理:- (void)callObserver:(CXCallObserver *)callObserver callChanged:(CXCall *)call;
一个属性:@property (nonatomic, readonly, copy) NSArray
CXCall类 :电话信息类
UUID //唯一通过这个ID可以定位到特定时刻的特定号码的来电信息
outgoing // (bool)是否是自己拨打的
onHold //电话是否挂起
hasConnected //电话是否接通
hasEnded //电话是否结束
}
//以下三个方法:将CXTransaction传递给系统,如果error为空,将调起CXProvider类的-provider:executeTransaction: 代理方法
- (void)requestTransaction:(CXTransaction *)transaction completion:(void (^)(NSError *_Nullable error))completion;
- (void)requestTransactionWithActions:(NSArray
- (void)requestTransactionWithAction:(CXAction *)action completion:(void (^)(NSError *_Nullable error))completion API_AVAILABLE(ios(11.0));
CXTransaction类 :用户的任何操作(CXAction)被包装成CXTransaction,然后丢给CXCallController通知系统
@property (nonatomic, readonly, copy) NSUUID *UUID; //获取唯一标识
@property (nonatomic, readonly, assign, getter=isComplete) BOOL complete; //所有的CXAction是否已经完成
@property (nonatomic, readonly, copy) NSArray<__kindof CXAction *> *actions; //获取CXAction列表
- (instancetype)initWithActions:(NSArray
- (instancetype)initWithAction:(CXAction *)action;
- (void)addAction:(CXAction *)action; //添加CXTransaction
CXAction类:电话操作载体类
@property (nonatomic, readonly, copy) NSUUID *UUID; // 唯一标示
@property (nonatomic, readonly, assign, getter=isComplete) BOOL complete; // 不论失败成功 是否完成
@property (nonatomic, readonly, strong) NSDate *timeoutDate; // action未完成的超时时间
- (instancetype)init; //指定初始化方法
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder; // 指定初始化方法
- (void)fulfill; // action已经完成(在当前时间)
- (void)fail;
CXCallAction类 :CXAction的子类,以下类的父类
- (instancetype)initWithCallUUID:(NSUUID *)callUUID handle:(CXHandle *)handle;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
- (instancetype)initWithCallUUID:(NSUUID *)callUUID; // 不可用
@property (nonatomic, copy, nullable) NSString *contactIdentifier; // 呼叫接收方的标识符
@property (nonatomic, getter=isVideo) BOOL video; // 是否是视频电话
- (void)fulfillWithDateStarted:(NSDate *)dateStarted; // 指明电话的开始时间
@property (nonatomic, copy) CXHandle *handle;
{
CXHandle类
@property (nonatomic, readonly) CXHandleType type;
@property (nonatomic, readonly, copy) NSString *value;
- (instancetype)initWithType:(CXHandleType)type value:(NSString *)value NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
- (BOOL)isEqualToHandle:(CXHandle *)handle
}
- (void)fulfillWithDateConnected:(NSDate *)dateConnected; // 指明一个时间表明电话已经接通
- (instancetype)initWithCallUUID:(NSUUID *)callUUID onHold:(BOOL)onHold; // 指定
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder; // 指定
- (instancetype)initWithCallUUID:(NSUUID *)callUUID; // 不可用
@property (nonatomic, getter=isOnHold) BOOL onHold; //是否被hold
- (instancetype)initWithCallUUID:(NSUUID *)callUUID muted:(BOOL)muted;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
- (instancetype)initWithCallUUID:(NSUUID *)callUUID; // 不可用
@property (nonatomic, getter=isMuted) BOOL muted;
- (instancetype)initWithCallUUID:(NSUUID *)callUUID callUUIDToGroupWith:(nullable NSUUID *)callUUIDToGroupWith;
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder;
- (instancetype)initWithCallUUID:(NSUUID *)callUUID; // 不可用
@property (nonatomic, copy, nullable) NSUUID *callUUIDToGroupWith;
- (void)fulfillWithDateEnded:(NSDate *)dateEnded; // 指明一个end时间表完成
CXProvider类
//初始化一个CXProvider,应该定义成单利
- (instancetype)initWithConfiguration:(CXProviderConfiguration *)configuration; //指定使用
{
CXProviderConfiguration类
@property (nonatomic, readonly, copy) NSString *localizedName; //获取系统来电页面显示的app名称和系统通讯记录的信息
@property (nonatomic, strong, nullable) NSString *ringtoneSound; //来电铃声(在app的bundel中的)
@property (nonatomic, copy, nullable) NSData *iconTemplateImageData; //锁屏接听时系统界面右下角app图标,要40x40大小
@property (nonatomic) NSUInteger maximumCallGroups; //最大通话组,默认2
@property (nonatomic) NSUInteger maximumCallsPerCallGroup; //每个通话组的最大呼叫次数,默认 5
@property (nonatomic) BOOL includesCallsInRecents API_AVAILABLE(ios(11.0)); //每个通话结束是否显示在系统最近通话列表,默认YES
@property (nonatomic) BOOL supportsVideo; //是否支持视频,默认NO
@property (nonatomic, copy) NSSet
- (instancetype)initWithLocalizedName:(NSString *)localizedName; //指定使用
}
//设置代理,queue一般直接指定为nil,即在main线程执行callback
- (void)setDelegate:(nullable id
重要流程:
1、来了VoIP电话后,让系统按照它的配置弹出一个系统来电界面。UUID:每次随机生成,其方法是:
- (void)reportNewIncomingCallWithUUID:(NSUUID *)UUID update:(CXCallUpdate *)update completion:(void (^)(NSError *_Nullable error))completion;
{
CXCallUpdate类
@property (nonatomic, copy, nullable) CXHandle *remoteHandle; //通话对方的Handel信息
@property (nonatomic, copy, nullable) NSString *localizedCallerName; //对方的名字,可以设置为app注册的昵称
@property (nonatomic) BOOL supportsHolding; //通话过程中再来电,是否支持保留并接听
@property (nonatomic) BOOL supportsGrouping; //通话是否可以加入一个群组
@property (nonatomic) BOOL supportsUngrouping; //通话当被加入群组时,是否可退出
@property (nonatomic) BOOL supportsDTMF; //是否支持键盘拨号
@property (nonatomic) BOOL hasVideo; //本次通话是否有视频
}
2、报告系统一个通话更新。动态更改provider的配置信息CXCallUpdate,比如拨打方,开始没有配置通话的界面,就可以在通话开始时更新这些配置信息
- (void)reportCallWithUUID:(NSUUID *)UUID updated:(CXCallUpdate *)update;
3、外拨电话时
//通话连接时
- (void)reportOutgoingCallWithUUID:(NSUUID *)UUID startedConnectingAtDate:(nullable NSDate *)dateStartedConnecting;
//通话连接上
- (void)reportOutgoingCallWithUUID:(NSUUID *)UUID connectedAtDate:(nullable NSDate *)dateConnected;
4、报告系统通话结束的时间和原因
- (void)reportCallWithUUID:(NSUUID *)UUID endedAtDate:(nullable NSDate *)dateEnded reason:(CXCallEndedReason)endedReason;
@property (nonatomic, readwrite, copy) CXProviderConfiguration *configuration; //配置
- (void)invalidate; //让provider停止(所有存在的通话都被标记为失败结束)
@property (nonatomic, readonly, copy) NSArray
- (NSArray<__kindof CXCallAction *> *)pendingCallActionsOfClass:(Class)callActionClass withCallUUID:(NSUUID *)callUUID;
--------- 代理 ---------
//必须通过清除所有内部呼叫状态(断开通信信道、释放网络资源等)来响应此回调
- (void)providerDidReset:(CXProvider *)provider;
@optional
//provider创建好以后触发
- (void)providerDidBegin:(CXProvider *)provider;
//是否执行一个transaction
- (BOOL)provider:(CXProvider *)provider executeTransaction:(CXTransaction *)transaction;
// 如果 provider:executeTransaction:error: 返回 NO, 下面的方法按逻辑执行
//拨打方成功发起一个通话后触发
- (void)provider:(CXProvider *)provider performStartCallAction:(CXStartCallAction *)action;
//接听方成功接听一个电话时触发
- (void)provider:(CXProvider *)provider performAnswerCallAction:(CXAnswerCallAction *)action;
//接听方拒接电话或者双方结束通话时触发
- (void)provider:(CXProvider *)provider performEndCallAction:(CXEndCallAction *)action;
//当点击系统通话界面的 暂停 按钮时,会触发
- (void)provider:(CXProvider *)provider performSetHeldCallAction:(CXSetHeldCallAction *)action;
//当点击系统通话界面的 静音 按钮时,会触发
- (void)provider:(CXProvider *)provider performSetMutedCallAction:(CXSetMutedCallAction *)action;
//当点击系统通话界面的 添加通话 按钮时,会触发
- (void)provider:(CXProvider *)provider performSetGroupCallAction:(CXSetGroupCallAction *)action;
//
- (void)provider:(CXProvider *)provider performPlayDTMFCallAction:(CXPlayDTMFCallAction *)action;
//通话响应超时,强制通话结束
- (void)provider:(CXProvider *)provider timedOutPerformingAction:(CXAction *)action;
//audio session activation state改变时发起
- (void)provider:(CXProvider *)provider didActivateAudioSession:(AVAudioSession *)audioSession;
- (void)provider:(CXProvider *)provider didDeactivateAudioSession:(AVAudioSession *)audioSession;
CXCallDirectoryManager类
//获取app extension的授权
identifier:app extension的bundleID
enabledStatus:授权状态:未授权-授权-不知道
- (void)getEnabledStatusForExtensionWithIdentifier:(NSString *)identifier completionHandler:(void (^)(CXCallDirectoryEnabledStatus enabledStatus, NSError *_Nullable error))completion;
//需要实时更新
- (void)reloadExtensionWithIdentifier:(NSString *)identifier completionHandler:(nullable void (^)(NSError *_Nullable error))completion;
CXCallDirectory类
一个属性:CXCallDirectoryPhoneNumber //可以标识一个电话号码数组
CXCallDirectoryExtensionContext类
两个功能:
1>将号码添加(移除)到黑名单
2>给一个号码添加(移除)一个标识。例如腾讯手机管家中的“腾讯手机管家:骚扰电话”
一个代理:添加黑名单或号码标识出错时发起
- (void)requestFailedForExtensionContext:(CXCallDirectoryExtensionContext *)extensionContext withError:(NSError *)error
CXCallDirectoryProvider类
一个方法:- (void)beginRequestWithExtensionContext:(CXCallDirectoryExtensionContext *)context;
它基于NSExtensionRequestHandling协议,由Extention实现
CXError类 :错误信息类
参考文章:
https://www.jianshu.com/p/305bd923c1ae
https://www.cnblogs.com/viviwu/p/5942483.html
https://blog.csdn.net/kmyhy/article/details/74388913
https://blog.csdn.net/zhaochen_009/article/details/53410288?locationNum=12&fps=1
-- NORMAL --
-- NORMAL --