菊风云平台
菊风云平台一对一视频通话快速开始

快速开始

参考接入教程,快速了解开发流程

1. 前提条件

支持 iOS 8.0 或以上版本的 iOS 真机设备。

有效的菊风云开发者账号 免费注册

2. 准备工作

开始之前,请先做好如下准备工作。

2.1 SDK 下载

点击 iOS SDK 进行下载。如果已经下载了 SDK,请直接进行 SDK 配置。

注解

从 2.1 版本开始提供动态库和静态库。开发者可以根据需要下载对应的库。

2.2 AppKey 获取

AppKey 是应用在 菊风云平台 中的唯一标识。需要在 SDK 初始化的时候使用,AppKey 获取请参考 创建应用 。

2.3 SDK 配置

您可以在工程中使用静态库或者动态库,此处介绍使用静态库的配置方法。如果想使用动态库,请参考动态库的配置说明文档 iOS 导入动态库 。

如果您已经集成了多家音视频引擎,则推荐使用动态库。

打开下载的 JC SDK 静态库,目录如下:

/style/images/document/instructions/ioslib.png

注解

从 2.1 版本开始,下载的 SDK 中包含 JCCloudWrapper.framework,该库是为IM(消息)服务的,如果需要集成 IM 消息,则需要在工程中添加 JCCloudWrapper.framework;如果不需要集成 IM 消息,则无需集成该库。

只有完成 SDK 的配置之后,您才可以集成 JC SDK 提供的功能,请按以下操作完成静态库的配置:

导入静态库

有两种方式导入静态库

方法一:使用 CocoaPods 自动导入

注解

该方法仅适用于 2.0 及以上版本的静态库集成。

SDK 支持使用 CocoaPods 导入 SDK。 需要安装 CocoaPods 环境,请参照 CocoaPods 官网 安装。

CocoaPods 环境安装好后,请执行以下操作:

  1. 打开 Terminal,cd 至项目根目录
  2. 执行 pod init,项目文件夹下会生成一个 Podfile 文本文件
  3. 执行 open -e Podfile
  4. 添加导入配置 pod 'JuphoonCloudSDK_iOS', '2.1'

修改后内容如下所示,注意将 Your App 替换为你的 Target 名称。

platform :ios, '9.0'
#use_frameworks!
target 'Your App' do
pod 'JuphoonCloudSDK_iOS', '2.1'
end

2.0 为当前发布的最新版本,关于指定具体版本请参考 pod 使用规范 。

  1. 执行 pod install,成功安装后,Terminal 中会显示 Pod installation complete!,此时项目文件夹下会生成一个 xcworkspace 文件。

注解

如果需要更新本地库版本,在执行 pod install 之前执行 pod update 命令。

  1. 双击打开 .xcworkspace 文件即可。

方法二:手动导入

拷贝文件

将 sdk 文件夹拷贝到您工程所在的目录下。

工程设置

1. 导入 SDK

打开 Xcode,进入 TARGETS > Project Name > Build Phases > Link Binary with Libraries 菜单,点击 '+' 符号,导入 sdk 文件夹下的 JCSDKOC.framework、lib 文件夹下的两个 .a 文件,如下图:

/style/images/document/instructions/inputlib.png

2. 导入 SDK 依赖的库

继续点击 '+' 符号,导入下图红框中的库:

/style/images/document/instructions/inputotherlib.png

3. 设置路径

点击 'Build Settings',找到 Framework Search Paths 、Header Search Paths(头文件路径) 和 Library Search Paths(库文件路径)。并设置 Framework Search Paths、Header Search Paths 和 Library Search Paths,如下图:

/style/images/document/instructions/pathset.png

注解

在完成第1步导入 JCSDKOC.framework 和两个.a文件后,Xcode 会自动生成该路径,如果 Xcode 没有自动生成路径,用户要根据 JCSDKOC.framework 、include 和 lib 库文件所在目录,手动设置路径。

4. 设置 Enable Bitcode 为 NO

点击 'Build Settings',找到 Enable Bitcode 设置为 NO,如下图:

/style/images/document/instructions/iOS_integration_DynamicBitcode.png

5. 设置 Other Linker Flags 的参数为 -ObjC

点击 'Build Settings',找到 Other Linker Flags 并添加参数 -ObjC,如下图:

/style/images/document/instructions/iOS_integration_ObjC.png

6.设置预处理宏定义

点击 'Build Settings',找到 Preprocessor Macros,在右侧输入 ZPLATFORM=ZPLATFORM_IOS,如下图:

/style/images/document/instructions/static_import_ios.png

如果设置了 APNs 推送,则还需要在 Preprocessor Macros 下的 Debug 中输入 DEBUG,如下图:

/style/images/document/instructions/pushdebug.png

注解

DEBUG 宏定义的目的是为了区分推送环境是 release 还是 debug,环境不对会导致推送失败。

7. 设置 Documentation Comments 为 NO

点击 'Build Settings',找到 Documentation Comments 并设置为 NO,如下图:

/style/images/document/instructions/static_import_ios1.png

8. 设置后台运行模式

点击 'Capabilities',找到 Background Modes,勾选红框内的 Audio, AirPlay, and Picture in Picture ,如下图:

/style/images/document/instructions/iOS_integration_DynamicBackgroundModes.png

权限设置

9. 设置麦克风和摄像头权限

点击 'Info',然后添加麦克风和摄像头的权限,如下图:

/style/images/document/instructions/iOS_integration_DynamicPermissions.png
Key Type Value
Privacy - Microphone Usage Description String 使用麦克风的目的,如语音通话。
Privacy - Camera Usage Description String 使用摄像头的目的,如视频通话。

10. 编译运行

以上步骤进行完后,编译工程,如果提示 succeeded,恭喜您已经成功配置 SDK,可以进行 SDK 初始化了。

SDK 不支持模拟器运行,请使用真机。

2.4 SDK 初始化

在使用 SDK 之前,需要进行 SDK 的初始化。

首先在需要使用 JC SDK 的地方 #import <JCSDKOC/JCSDKOC.h>

然后在实现初始化的文件中实现 JCClientCallback 回调,用于接收 JCClient 相关通知。

JCClientCreateParam 对象有以下属性

/// sdk信息存储目录
@property (nonatomic, copy) NSString* __nonnull sdkInfoDir;

/// sdk日志目录
@property (nonatomic, copy) NSString* __nonnull sdkLogDir;

/// sdk日志等级 JCLogLevel
@property (nonatomic) JCLogLevel sdkLogLevel;

调用下面的接口初始化 SDK

/**
 * @brief 创建 JCClient 实例
 * @param appKey 用户从 Juphoon Cloud 平台上申请的 AppKey 字符串
 * @param callback 回调接口,用于接收 JCClient 相关通知
 * @param createParam 创建参数,nil 则按默认值创建
 * @return JCClient 对象
 */
+(JCClient* __nullable)create:(NSString* __nonnull)appKey callback:(id<JCClientCallback> __nonnull)callback creatParam:(JCClientCreateParam* __nullable)createParam;
			
appKey 为准备工作中“获取 AppKey”步骤中取得的 AppKey。如果还未获取 AppKey,请参考 创建应用 来获取。

示例代码

// 初始化,因为这些模块实例将被频繁使用,建议声明在单例中
JCClientCreateParam *param = [[JCClientCreateParam alloc] init];
param.sdkLogLevel = JCLogLevelInfo;
param.sdkInfoDir = @"SDK 信息存放路径";
param.sdkLogDir = @"日志存放路径";
JCClient *client = [JCClient create:@"your appkey" callback:self creatParam:param];
			

SDK 初始化之后,即可进行登录的集成。

3. 登录

登录涉及 JCClient 类及其回调 JCClientCallback 类,其主要作用是负责登录、登出管理及帐号信息存储。

登录之前,可以通过配置关键字进行登录的相关配置,如是否使用代理服务器登录以及服务器地址的设置,具体如下。

3.1 登录环境设置

服务器地址设置,包括国际环境服务器地址和国内环境服务器地址

JCClientLoginParam* loginParam = [[JCClientLoginParam alloc] init];
//默认国内环境 http:cn.router.justalkcloud.com:8080
loginParam.serverAddress = @"服务器地址";
//如果使用代理服务器登录
loginParam.httpsProxy = @"代理服务器地址";
			
国际环境 服务器地址为 http:intl.router.justalkcloud.com:8080 。
国内环境 服务器地址为 http:cn.router.justalkcloud.com:8080 。

开发者可以使用自定义服务器地址。

还可以通过 displayName 属性设置昵称,例如

client.displayName = @"小张";
			

3.2 发起登录

/**
 * @brief 登陆 Juphoon Cloud 平台,只有登陆成功后才能进行平台上的各种业务
 * 服务器分为鉴权模式和非鉴权模式
 *
 *     - 鉴权模式: 服务器会检查用户名和密码
 *
 *     - 免鉴权模式: 只要用户保证用户标识唯一即可, 服务器不校验
 *
 * 登陆结果通过 JCClientCallback 通知
 *
 * @param userId 用户名
 * @param password 密码,免鉴权模式密码可以随意输入,但不能为空
 * @param loginParam 登录参数,nil则按照默认值登录
 * @return 返回 true 表示正常执行调用流程,false 表示调用异常,异常错误通过 JCClientCallback 通知
 * @warning 目前只支持免鉴权模式,免鉴权模式下当账号不存在时会自动去创建该账号
 * @warning 用户名为英文数字和'+' '-' '_' '.',长度不要超过64字符,'-' '_' '.'不能作为第一个字符
 */
-(bool)login:(NSString* __nonnull)userId password:(NSString* __nonnull)password loginParam:(JCClientLoginParam* __nullable)loginParam;
			
用户名大小写不敏感,用户名为英文、数字和’+’ ‘-‘ ‘_’ ‘.’,长度不要超过64字符,’-‘ ‘_’ ‘.’不能作为第一个字符。

示例代码

JCClientLoginParam* loginParam = [[JCClientLoginParam alloc] init];
//默认国内环境 http:cn.router.justalkcloud.com:8080
loginParam.serverAddress = @"服务器地址";
[client login:@"账号" password:@"123" loginParam:loginParam];
			

登录成功之后,首先会触发登录状态改变(onClientStateChange)回调

/**
 *  @brief 登录状态变化通知
 *  @param state    当前状态值
 *  @param oldState 之前状态值
 */
-(void)onClientStateChange:(JCClientState)state oldState:(JCClientState)oldState;
			

JCClientState 有

// 未初始化
JCClientStateNotInit,
// 未登录
JCClientStateIdle,
// 登录中
JCClientStateLogining,
// 登录成功
JCClientStateLogined,
// 登出中
JCClientStateLogouting,
			

示例代码

-(void)onClientStateChange:(JCClientState)state oldState:(JCClientState)oldState
{
    if (state == JCClientStateIdle) { // 未登录
       ...
    } else if (state == JCClientStateLogining) { // 登录中
       ...
    } else if (state == JCClientStateLogined) {  // 登录成功
       ...
    } else if (state == JCClientStateLogouting) {  // 登出中
       ...
    }
}
			

之后通过 onLogin 回调上报登录结果

/**
 *  @brief 登陆结果回调
 *  @param result true 表示登陆成功,false 表示登陆失败
 *  @param reason 当 result 为 false 时该值有效
 *  @see JCClientReason
 */
-(void)onLogin:(bool)result reason:(JCClientReason)reason;
			

其中,JCClientReason 有

/// 正常
JCClientReasonNone,
/// sdk 未初始化
JCClientReasonSDKNotInit,
/// 无效的参数
JCClientReasonInvalidParam,
/// 函数调用失败
JCClientReasonCallFunctionError,
/// 当前状态无法再次登录
JCClientReasonStateCannotLogin,
/// 超时
JCClientReasonTimeOut,
/// 网络异常
JCClientReasonNetWork,
/// appkey 错误
JCClientReasonAppKey,
/// 账号密码错误
JCClientReasonAuth,
/// 无该用户
JCClientReasonNoUser,
/// 被强制登出
JCClientReasonServerLogout,
/// 其他错误
JCClientReasonOther,

登录成功之后,SDK 会自动保持与服务器的连接状态,直到用户主动调用登出接口,或者因为帐号在其他设备登录导致该设备登出。

3.3 登出

登出调用下面的方法,登出后不能进行平台上的各种业务操作

/**
 *  登出 菊风云平台,登出后不能进行平台上的各种业务
 *  @return 返回 true 表示正常执行调用流程,false 表示调用异常,异常错误通过 JCClientCallback 通知
 */
-(bool)logout;

登出同样会触发登录状态改变(onClientStateChange)回调

之后将通过 onlogout 回调上报登出结果

/**
 *  @brief 登出回调
 *  @param reason 登出原因
 *  @see JCClientReason
 */
-(void)onLogout:(JCClientReason)reason;

集成登录后,即可进行相关业务的集成。

4. 业务集成

一对一视频通话涉及以下类

名称 描述
JCCall 一对一通话类,包含一对一语音和视频通话功能
JCCallItem 通话对象类,此类主要记录通话的一些状态,UI 可以根据其中的状态进行显示逻辑
JCCallCallback 通话模块回调代理
JCMediaDevice 设备模块,主要用于视频、音频设备的管理
JCMediaDeviceVideoCanvas 视频对象,主要用于 UI 层视频显示、渲染的控制
JCMediaDeviceCallback 设备模块回调代理

更多接口的详细信息请参考 API 说明文档 。


接口调用逻辑和相关状态

说明:蓝色与黄色字表示接口,红色字表示通话状态。

通话方向(呼入或呼出)及通话状态(振铃、连接中、通话中等)可通过 JCCallItem 对象中的 direction 和 state 获得。

开始集成通话功能前,请先实现 JCMediaDeviceCallback, JCCallCallback 回调,用于接收 JCMediaDevice 和 JCCall 的相关通知。

之后进行模块的初始化

创建 JCMediaDevice 实例

/**
 *  @brief 创建 JCMediaDevice 对象
 *  @param client JCClient 对象
 *  @param callback JCMediaDeviceCallback 回调接口,用于接收 JCMediaDevice 相关通知
 *  @return 返回 JCMediaDevice 对象
 */
+(JCMediaDevice* __nullable)create:(JCClient* __nonnull)client callback:(id<JCMediaDeviceCallback> __nonnull)callback;
			

创建 JCCall 实例

/**
 *  @brief                  创建 JCCall 实例
 *  @param client           JCClient 实例
 *  @param mediaDevice      JCMediaDevice 实例
 *  @param callback         JCCallCallback 回调接口,用于接收 JCCall 相关回调事件
 *  @return                 返回 JCCall 实例
 */
+(JCCall* __nullable)create:(JCClient* __nonnull)client mediaDevice:(JCMediaDevice* __nonnull)mediaDevice callback:(id<JCCallCallback> __nonnull)callback;
			

示例代码

                        
// 初始化各模块,因为这些模块实例将被频繁使用,建议声明在单例中
JCMediaDevice *mediaDevice = [JCMediaDevice create:client callback:self];
JCCall *call = [JCCall create:client mediaDevice:mediaDevice callback:self];
                    

开始集成

媒体参数配置

一对一视频通话支持智能硬件设备集成,需要在发起通话前设置媒体参数

// 根据模式生成配置参数
JCCallMediaConfig *mediaConfig = [JCCallMediaConfig generateByMode:JCCallMediaConfigModeIntelligentHardware];
// 设置媒体参数
JCManager.shared.call.mediaConfig = mediaConfig;
                    

菊风提供三种配置模式供开发者选择,并开放相关属性供开发者进行灵活的自定义配置,具体方法请查看 媒体参数设置 。

4.1 拨打通话

主叫调用下面的接口发起视频通话,此时 video 传入值为 true

/**
 *  @brief                  一对一呼叫
 *  @param userId           用户标识
 *  @param video            是否为视频呼叫
 *  @param extraParam       透传参数,被叫方可获取透传参数
 *  @return                 返回 true 表示正常执行调用流程,false 表示调用异常
 */
-(bool)call:(NSString* __nonnull)userId video:(bool)video extraParam:(NSString * __nullable)extraParam;
			
调用此接口会自动打开音频设备。
extraParam 为自定义透传字符串,被叫可通过 JCCallItem 对象中的 extraParam 属性获得。

通话发起后,主叫和被叫均会收到新增通话的回调,通话状态变为 JCCallStatePending

/**
 *  @brief 新增通话回调
 *  @param item JCCallItem 对象
 */
-(void)onCallItemAdd:(JCCallItem* __nonnull)item;
			

示例代码

-(void)onCallItemAdd:(JCCallItem* __nonnull)item {
    // 收到新增通话回调
}
			
如果主叫想取消通话,可以直接转到第4步,调用第4步中的挂断通话的接口。这种情况下调用挂断后,通话状态变为 JCCallStateCancel。

4.1.1 创建本地视频画面

通话发起后,即可调用 JCMediaDevice 类中的 startCameraVideo 方法打开本地视频预览,调用此方法会打开摄像头

/**
 *  @brief 获得预览视频对象,通过此对象能获得视图用于UI显示
 *  @param type 渲染模式,@ref JCMediaDeviceRender
 *  @return JCMediaDeviceVideoCanvas 对象
 */
-(JCMediaDeviceVideoCanvas* __nullable)startCameraVideo:(int)type;

其中,type(渲染模式)可以参考 JCMediaDeviceRender 的枚举值,具体如下

/// 视频图像按比例填充整个渲染区域(裁剪掉超出渲染区域的部分区域)
JCMediaDeviceRenderFullScreen = 0,
/// 视频图像的内容完全呈现到渲染区域(可能会出现黑边,类似放电影的荧幕)
JCMediaDeviceRenderFullContent,
/// 自动
JCMediaDeviceRenderFullAuto,
调用该方法后,在挂断通话或者关闭摄像头时需要对应调用 stopVideo 方法停止视频。

该方法采集分辨率默认值为 640*360,帧率为 30。默认打开的是前置摄像头。

如果想自定义摄像头采集参数,如采集的高度、宽度和帧速率,请参考 视频采集和渲染。

示例代码

// 发起视频呼叫
[call call:@"peer number" video:true extraParam:@"自定义透传字符串"];
// 本地视频渲染
JCMediaDeviceVideoCanvas *localCanvas = [mediaDevice startCameraVideo:JCMediaDeviceRenderFullContent];
localCanvas.videoView.frame = CGRectMake(20, 20, 90, 160);
[self.view addSubview:localCanvas.videoView];
			

4.2 应答通话

被叫收到 onCallItemAdd 回调事件,并通过 JCCallItem 中的 video 属性以及 direction 属性值 JCCallDirectionIn 判断是视频呼入还是语音呼入,此时可以调用以下接口选择视频应答或者语音应答

/**
 *  @brief                  接听
 *  @param item             JCCallItem 对象
 *  @param video            针对视频呼入可以选择以视频接听还是音频接听
 *  @return                 返回 true 表示正常执行调用流程,false 表示调用异常
 */
-(bool)answer:(JCCallItem* __nonnull)item video:(bool)video;

如果被叫应答通话成功,双方都会收到 onCallItemUpdate 的回调。

示例代码

-(void)onCallItemAdd:(JCCallItem*)item {
// 如果是视频呼入且在振铃中
    if(item && item.state == JCCallStatePending) {
        if (item.direction == JCCallDirectionIn && item.video) {
            // 应答通话
            [call answer:item video:true];
        }
    }
}

通话应答后,通话状态变为 JCCallStateConnecting。

如果要拒绝通话,可以直接转到第4步,调用第4步中的挂断通话的接口。这种情况下调用挂断后,通话状态变为 JCCallStateCanceled。

4.3 通话建立

被叫接听通话后,双方将建立连接,此时,主叫和被叫都将会收到通话更新的回调(onCallItemUpdate)。连接成功之后,可以进行远端视频的渲染。

4.3.1 创建远端视频画面

远端视频画面的获取通过调用 JCMediaDevice 类中的 startVideo 方法实现

/**
 *  @brief 获得预览视频对象,通过此对象能获得视图用于UI显示
 *  @param videoSource 渲染标识串,比如 JCMediaChannelParticipant JCCallItem 中的 renderId,当videoSource 为 videoFileId 时,内部会调用 startVideoFile
 *  @param type        渲染模式,@ref JCMediaDeviceRender
 *  @return JCMediaDeviceVideoCanvas 对象
 */
-(JCMediaDeviceVideoCanvas* __nullable)startVideo:(NSString* __nonnull)videoSource renderType:(int)type;

其中,type(渲染模式)可以参考 JCMediaDeviceRender 的枚举值,具体如下

/// 视频图像按比例填充整个渲染区域(裁剪掉超出渲染区域的部分区域)
JCMediaDeviceRenderFullScreen = 0,
/// 视频图像的内容完全呈现到渲染区域(可能会出现黑边,类似放电影的荧幕)
JCMediaDeviceRenderFullContent,
/// 自动
JCMediaDeviceRenderFullAuto,
调用该方法后,在挂断通话或者关闭摄像头时需要对应调用 stopVideo 方法停止视频。

现在您可以进行一对一视频通话了。

示例代码

-(void)onCallItemUpdate:(JCCallItem*)item {
    // 如果对端在上传视频流(uploadVideoStreamOther)
    if (item.state == JCCallStateTalking && remoteCanvas == nil && item.uploadVideoStreamOther) {
        // 获取远端视频画面,renderId来源JCCallItem对象
        JCMediaDeviceVideoCanvas *remoteCanvas = [mediaDevice startVideo:item.renderId renderType:JCMediaDeviceRenderFullContent];
        remoteCanvas.videoView.frame = self.view.frame;
        [self.view addSubview:remoteCanvas.videoView];
    }
}

4.4 挂断通话

主叫或者被叫均可以调用下面的方法挂断通话

/**
 * @brief 获得当前活跃通话
 *
 * @return 当前活跃通话,没有则返回nil
 */
-(JCCallItem* __nullable)getActiveCallItem;
			

当前活跃通话对象获取后,调用下面的方法挂断通话

/**
 *  @brief                  挂断
 *  @param item             JCCallItem 对象
 *  @param reason           挂断原因
 *  @param description      挂断描述
 *  @return                 返回 true 表示正常执行调用流程,false 表示调用异常
 *  @see JCCallReason
 */
-(bool)term:(JCCallItem* __nonnull)item reason:(JCCallReason)reason description:(NSString* __nullable)description;
			

示例代码

// 挂断通话
JCCallItem *item = [call getActiveCallItem];
[call term:item reason:JCCallReasonNone description:@"主叫挂断"];
			

4.4.1 销毁本地和远端视频画面

通话挂断后,还需要调用 stopVideo 接口移除视频画面

/**
 *  @brief 停止视频
 *  @param canvas JCMediaDeviceVideoCanvas 对象,由 startVideo 获得
 */
-(void)stopVideo:(JCMediaDeviceVideoCanvas* __nonnull)canvas;

通话挂断后,UI 会收到移除通话的回调,通话状态变为 JCCallStateOk

/**
 *  @brief 移除通话
 *  @param item JCCallItem 对象
 *  @param reason 通话结束原因
 *  @param description 通话结束原因的描述,只有被动挂断的时候,才会收到这个值,其他情况下则返回空字符串
 *  @see JCCallReason
 */
-(void)onCallItemRemove:(JCCallItem* __nonnull)item reason:(JCCallReason)reason description:(NSString * __nullable)description;
			

其中,reason 有以下几种

名称 描述
JCCallReasonNone 无异常
JCCallReasonNotLogin 未登录
JCCallReasonCallFunctionError 函数调用错误
JCCallReasonTimeOut 超时
JCCallReasonNetWork 网络错误
JCCallReasonCallOverLimit 超出通话上限
JCCallReasonTermBySelf 自己挂断
JCCallReasonAnswerFail 应答失败
JCCallReasonBusy 忙
JCCallReasonDecline 拒接
JCCallReasonUserOffline 用户不在线
JCCallReasonNotFound 无此用户
JCCallReasonRejectVideoWhenHasCall 已有通话拒绝视频来电
JCCallReasonRejectCallWhenHasVideoCall 已有视频通话拒绝来电
JCCallReasonOther 其他错误

示例代码

-(void)onCallItemRemove:(JCCallItem* __nonnull)item reason:(JCCallReason)reason description:(NSString * __nullable)description { //移除通话回调
    // 界面处理
    if (_localCanvas) { // 本端视频销毁
        [mediaDevice stopVideo:_localCanvas];
        [_localCanvas.videoView removeFromSuperview];
        _localCanvas = nil;
    }
    if (_remoteCanvas) { // 远端视频销毁
        [mediaDevice stopVideo:_remoteCanvas];
        [_remoteCanvas.videoView removeFromSuperview];
        _remoteCanvas = nil;
    }
}
			

通话挂断的其他情况

如果拨打通话时,对方未在线,或者主叫呼叫后立即挂断,则对方再次上线时会收到未接来电的回调

/**
 * @brief上报服务器拉取的未接来电
 * @param item JCCallItem 对象
 */
-(void)onMissedCallItem:(JCCallItem * __nonnull)item;
			

此时通话状态变为 JCCallStateMissed。