# VoipServiceDemo **Repository Path**: itgsa/voipservicedemo ## Basic Information - **Project Name**: VoipServiceDemo - **Description**: VoIPServiceKit 调用示例代码 - **Primary Language**: Android - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 2 - **Forks**: 2 - **Created**: 2026-01-28 - **Last Updated**: 2026-05-12 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # VoIP Service Kit ## 目录 - [1. 概述](#1-概述) - [2. 功能介绍](#2-功能介绍) - [3. 使用限制](#3-使用限制) - [4. 开发准备](#4-开发准备) - [4.1 接入推送服务](#41-接入推送服务) - [4.1.1 vivo 推送](#411-vivo-推送) - [4.1.2 OPPO 推送](#412-oppo-推送) - [4.1.3 小米推送](#413-小米推送) - [4.1.4 荣耀推送](#414-荣耀推送) - [4.2 集成VoIP Service Kit SDK](#42-集成voip-service-kit-sdk) - [4.3 系统版本要求](#43-系统版本要求) - [4.4 SDK简介](#44-sdk简介) - [4.5 SDK集成方式](#45-sdk集成方式) - [5. 功能使用指南](#5-功能使用指南) - [5.1 去电场景](#51-去电场景) - [5.2 来电场景](#52-来电场景) - [6. API 参考](#6-api-参考) - [6.1 枚举定义](#61-枚举定义) - [6.2 数据模型](#62-数据模型) - [6.3 API 接口](#63-api-接口) --- ## 1. 概述 VoIP Service Kit 为 VoIP应用提供一站式的通话管理解决方案,集成后可快速获得来电管理、通话控制、音频切换等核心通信能力,助力开发者打造流畅、稳定且用户体验卓越的通信服务。 ### VoIPServiceDemo 项目 VoIPServiceDemo 是一个基于 Android 平台的通话服务示例项目,提供完整的 VoIP 通话解决方案。支持语音/视频通话、来电管理、通知、多音频设备切换等功能,让通话体验更加智能便捷。 --- ## 核心功能 - 📞 **语音通话**:高质量语音通话支持 - 📹 **视频通话**:完整的视频通话功能 - 🔔 **来电管理**:来电界面、按钮接听/挂断 - 🏝️ **系统通知**:系统级通知功能,支持快速接听或挂断 - 🔊 **音频切换**:扬声器/耳机/蓝牙设备切换 --- ## 2. 功能介绍 ### 2.1 去电场景 应用主动发起 VoIP 通话邀请时,在通知栏中可以看到VoIP通话通知,用户可以在通知栏通知上完成挂断、切换音频等操作,若应用退到后台,会在状态栏上展示。 ### 2.2 来电场景 应用接收 VoIP 通话邀请时,应用需将通话相关信息上报至 VoIP Service Kit,由系统为用户展示来电横幅通知;用户可直接在该横幅上完成接听、拒接、挂断通话等操作。 --- ## 3. 使用限制 | 限制类型 | 说明 | | ------------ | ------------------------------------------------------- | | 设备限制 | 只支持手机端 | | 地域支持限制 | VoIP Service Kit 提供的能力当前只支持中国大陆销售的设备 | ### 3.1 系统版本支持 | 品牌 | 系统版本要求 | | ---- | ----------------------- | | vivo | OriginOS 6.0 及以上版本 | | 小米 | HyperOS 3.1及以上版本 | | OPPO | ColorOS16.0 及以上版本 | | 荣耀 | MagicOS 10.0及以上版本 | --- ## 4. 开发准备 ### 4.1 接入推送服务 由于 VoIP Service Kit 需要依赖各厂商推送服务,不同品牌的设备需要接入对应的推送 SDK。以下是各厂商推送服务的接入说明: #### 4.1.1 vivo 推送 需要提前接入 **vivo 推送 SDK 4.1.3.0 及以上版本**,请参考: - [vivo 推送接入文档](https://dev.vivo.com.cn/documentCenter/doc/362) - [客户端 SDK 集成指南](https://dev.vivo.com.cn/documentCenter/doc/361) #### 4.1.2 OPPO 推送 需要提前接入 OPPO 推送服务,请参考: - [OPPO 推送接入文档](https://open.oppomobile.com/documentation/page/info?id=10195) #### 4.1.3 小米推送 需要提前接入小米推送服务,请参考: - [小米推送接入文档](https://dev.mi.com/xiaomihyperos/documentation/detail?pId=1559) - [客户端 SDK 集成指南](https://dev.mi.com/xiaomihyperos/documentation/detail?pId=1544) #### 4.1.4 荣耀推送 需要提前接入荣耀推送服务,请参考: - [荣耀推送接入文档](https://developer.hihonor.com/cn/) ### 4.2 集成VoIP Service Kit SDK 点击此处下载 [VoIP Service Kit SDK](https://nexus.itgsa.com/repository/voipServiceKit/gsai/sdk/callService/1.0.0.2/callService-1.0.0.2.aar) > **注意**: 下载链接将跳出Gitee, 若公司网络下载压缩包解压异常,建议切换其他网络下载。 ### 4.3 系统版本要求 | 品牌 | 系统版本要求 | | ---- | ----------------------- | | vivo | OriginOS 6.0 及以上版本 | | 小米 | HyperOS 3.1及以上版本 | | OPPO | ColorOS16.0 及以上版本 | | 荣耀 | MagicOS 10.0及以上版本 | ### 4.4 SDK简介 | 项目 | 说明 | | -------- | ---------------------------------------------------------- | | SDK 名称 | VoIP 通话 SDK | | 提供主体 | 玩咖 | | 版本号 | 1.0.0.2 | | 功能说明 | 提供标准化的 VoIP 来电通话组件,实现通话样式和交互上的统一 | ### 4.5 SDK集成方式 #### 4.5.1 方式一:通过 Maven 仓库集成 **步骤 1**:打开 Android Studio 项目级 `build.gradle` 文件 **步骤 2**:在 `buildscript > repositories` 和 `allprojects > repositories` 中配置 VoIP Service Kit SDK 的 Maven 仓库地址: ```groovy buildscript { repositories { google() jcenter() // 配置 Maven 仓库地址 maven { allowInsecureProtocol = true url = 'http://nexus.itgsa.com:5566/repository/voipServiceKit/' } } } allprojects { repositories { google() jcenter() // 配置 Maven 仓库地址 maven { allowInsecureProtocol = true url = 'http://nexus.itgsa.com:5566/repository/voipServiceKit/' } } } ``` **步骤 3**:添加编译依赖,打开应用级的 `build.gradle` 文件,在 `dependencies` 中添加如下依赖: ```groovy dependencies { // 配置编译依赖 implementation 'gsai.sdk:callService:1.0.0.2' } ``` **步骤 4**:点击工具栏中的 Gradle 同步图标完成 `build.gradle` 文件的同步。 --- #### 4.5.2 方式二:通过本地 AAR 包集成 1. 将下载到的 `callService.aar` 拷贝到工程的 `libs` 文件夹中,点击此处下载 [VoIP Service Kit SDK](https://nexus.itgsa.com/repository/voipServiceKit/gsai/sdk/callService/1.0.0.2/callService-1.0.0.2.aar) 2. 在 app 目录下的 `build.gradle` 中添加 AAR 依赖: ```groovy dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation files('libs/callService-1.x.x.x.aar') } ``` --- ## 5. 功能使用指南 ### 5.1 去电场景 #### 5.1.1 接口说明 | 接口名 | 描述 | | -------------------------------------------------------------------------------- | ----------------------------------------- | | `on(Application context)` | 判断当前手机环境是否支持 VoIP Service Kit | | `register(CallKitCallBack callback)` | 注册 VoIP 通话回调事件 | | `off()` | 取消注册 VoIP 通话回调事件 | | `reportOutgoingCall(VoipCall voipCall)` | 上报去电消息 | | `reportCallAudioRouteEvent(String callId, int currentRoute, int supportRoute)` | 上报通话中的音频事件 | | `updateCallState(String callId, int callState)` | 上报应用内通话状态变化 | | `updateCallType(String callId, int calltype)` | 上报应用内通话类型变化 | | `reportCallError(String callId, int errorCode, String errorMessage)` | 上报通话失败 | #### 5.1.2 开发步骤 **步骤 1:注册 VoIP 通话回调事件** ```java // 检查设备是否支持 VoIP Service Kit int workable = CallKitManager.getInstance().on(this); // 注册回调 CallKitCallBack mCallKitCallBack = new CallKitCallBack() { @Override public void answerCall(String callId) { CallKitLog.i(TAG, "answerCall callId " + callId); } @Override public void answerCallWithType(String callId, int callType) { CallKitLog.i(TAG, "answerCallWithType callId " + callId + ", type " + callType); } @Override public void rejectCall(String callId) { CallKitLog.i(TAG, "rejectCall callId " + callId); } @Override public void changeCallType(String callId, int callType) { CallKitLog.i(TAG, "changeCallType callId " + callId + ", type " + callType); } @Override public void disconnectCall(String callId) { CallKitLog.i(TAG, "disconnectCall callId " + callId); } @Override public void mute(String callId, boolean mute) { CallKitLog.i(TAG, "mute callId " + callId + ", mute " + mute); } @Override public void changeAudioRoute(String callId, int route) { CallKitLog.i(TAG, "changeAudioRoute callId " + callId + ", route " + route); } @Override public void onCallKitEvent(int event, Bundle extras) { CallKitLog.i(TAG, "onCallKitEvent: " + event + " , extras " + extras); } }; if (workable == CallKitConstants.ERROR_NONE) { CallKitManager.getInstance().register(mCallKitCallBack); } ``` **返回结果**: - `ERROR_NONE`:支持 - `ERROR_FEATURE_UNSUPPORTED`:不支持 --- **步骤 2:上报去电事件** 应用内部建立通话连接之后,需要向VoIP Service Kit上报去电,并携带通话信息,详见接口文档VoipCall。 ```java VoipCall call = new VoipCall(); call.setCallId("123456789"); call.setUserName("Mark"); call.setPackageName(getPackageName()); call.setActivityName(this.getClass().getName()); call.setVoipCallType(CallKitConstants.VOIP_CALL_TYPE_VOICE); call.setVoipCallState(CallKitConstants.VOIP_CALL_STATE_DIALING); call.setDirection(CallKitConstants.DIRECTION_OUTGOING); // 上报去电事件 CallKitManager.getInstance().reportOutgoingCall(call); ``` --- **步骤 3:上报通话状态** 当对端用户接听后,向 VoIP Service Kit 上报通话状态: ```java CallKitManager.getInstance().updateCallState(callId, CallKitConstants.VOIP_CALL_STATE_ACTIVE); ``` --- **步骤 4:上报通话中的音频事件** 在通话过程中,用户可以根据实际需要选择不同的音频通路,包括手机听筒、免提扬声器、蓝牙设备和有线耳机等。当通话的音频通路被切换,VoIP 应用会接收到切换通话音频通路回调 `changeAudioRoute`,应用在完成通话音频通路切换后,需通过调用接口上报当前通知的音频通路。 ```java String callId = "123456789"; int currentRoute = CallKitConstants.ROUTE_SPEAKER; int supportRoute = CallKitConstants.ROUTE_EARPIECE | CallKitConstants.ROUTE_BLUETOOTH | CallKitConstants.ROUTE_SPEAKER; CallKitManager.getInstance().reportCallAudioRouteEvent(callId, currentRoute, supportRoute); ``` --- **步骤 5:上报应用内通话类型变化** 通话类型分视频通话和语音通话两种,对于视频来电语音接听、通话中视频降语音或者语音升视频,需要应用调用接口上报通话类型变化。 ```java String callId = "123456789"; CallKitManager.getInstance().updateCallType(callId, CallKitConstants.VOIP_CALL_TYPE_VOICE); ``` --- **步骤 6:上报通话结束** 用户在通知上点击挂断按钮,应用会收到挂断电话回调 `disconnectCall`,在应用内处理完成挂断后,需立即通过调用接口上报通话结束状态。 > **注意**:为了确保功能完整(如系统状态同步、资源释放等),通话结束后,开发者需要确保调用此接口上报通话结束状态。 ```java CallKitManager.getInstance().updateCallState(callId, CallKitConstants.VOIP_CALL_STATE_DISCONNECTED); ``` --- **步骤 7:取消注册** 通话结束后取消订阅: ```java CallKitManager.getInstance().off(); ``` > **注意**:取消订阅后,下次使用需重新注册回调事件。 --- **步骤 8:上报通话异常** 当通话出现异常时,应用需通过接口上报通话失败的原因: ```java CallKitManager.getInstance().reportCallError(callId, errorCode, errorMessage); ``` --- ### 5.2 来电场景 #### 5.2.1 接口说明 | 接口名 | 描述 | | -------------------------------------------------------------------------------- | ----------------------------------------- | | `on(Application context)` | 判断当前设备系统是否支持 VoIP Service Kit | | `register(CallKitCallBack callback)` | 注册 VoIP 通话回调事件 | | `off()` | 取消注册 VoIP 通话回调事件 | | `reportIncomingCall(VoipCall voipCall)` | 上报来电消息 | | `reportCallAudioRouteEvent(String callId, int currentRoute, int supportRoute)` | 上报通话中的音频事件 | | `updateCallState(String callId, int callState)` | 上报应用内通话状态变化 | | `updateCallType(String callId, int calltype)` | 上报应用内通话类型变化 | | `reportCallError(String callId, int errorCode, String errorMessage)` | 上报通话失败 | #### 5.2.2 开发步骤 **步骤 1:感知 VoIP 来电** 通过 厂商 推送 SDK 的回调接口感知 VoIP 来电: ```java public interface VOIPMessageCallback { void onCallMessage(CallMessage callMessage); } public class CallMessage { private String mMessage; // VoIP 通话消息内容 private String mMsgId; // push 的消息 id } ``` 继承 `OpenClientPushMessageReceiver` 类并重写 `onCallMessage` 方法: ```java public class VOIPMessageReceiver extends OpenClientPushMessageReceiver { @Override public void onCallMessage(CallMessage callMessage) { super.onCallMessage(callMessage); } } ``` > **注意**:对于 OS 不支持 VoIP Service Kit 的系统版本,需同时实现 `onTransmissionMessage` 回调。 **判断设备是否支持 VoIP Service Kit 功能:** ```java boolean isSupportVoipServiceKit = PushClient.getInstance(this) .isPushSupport(SUPPORT_VOIP_SERVICE_KIT_FLAG); // SUPPORT_VOIP_SERVICE_KIT_FLAG = 1 << 19 ``` --- **步骤 2:注册 VoIP 通话回调事件** ```java int workable = CallKitManager.getInstance().on(this); CallKitCallBack mCallKitCallBack = new CallKitCallBack() { @Override public void answerCall(String callId) { CallKitLog.i(TAG, "answerCall callId " + callId); } @Override public void answerCallWithType(String callId, int callType) { CallKitLog.i(TAG, "answerCallWithType callId " + callId + ", type " + callType); } @Override public void rejectCall(String callId) { CallKitLog.i(TAG, "rejectCall callId " + callId); } @Override public void changeCallType(String callId, int callType) { CallKitLog.i(TAG, "changeCallType callId " + callId + ", type " + callType); } @Override public void disconnectCall(String callId) { CallKitLog.i(TAG, "disconnectCall callId " + callId); } @Override public void mute(String callId, boolean mute) { CallKitLog.i(TAG, "mute callId " + callId + ", mute " + mute); } @Override public void changeAudioRoute(String callId, int route) { CallKitLog.i(TAG, "changeAudioRoute callId " + callId + ", route " + route); } @Override public void onCallKitEvent(int event, Bundle extras) { CallKitLog.i(TAG, "onCallKitEvent: " + event + " , extras " + extras); } }; if (workable == CallKitConstants.ERROR_NONE) { CallKitManager.getInstance().register(mCallKitCallBack); } ``` --- **步骤 3:上报来电事件** 应用内部完成通话连接建立后,需向 VoIP Service Kit 上报来电并携带通话信息,具体详见 VoipCall; ```java VoipCall call = new VoipCall(); call.setCallId("123456789"); call.setMsgId("msg78680bjbp680"); call.setUserName("Mark"); call.setPackageName(getPackageName()); call.setActivityName(this.getClass().getName()); call.setVoipCallType(CallKitConstants.VOIP_CALL_TYPE_VOICE); call.setVoipCallState(CallKitConstants.VOIP_CALL_STATE_RINGING); call.setDirection(CallKitConstants.DIRECTION_INCOMING); // 上报来电事件 CallKitManager.getInstance().reportIncomingCall(call); ``` > 若此时应用处于后台,系统将展示来电横幅通知。 --- **步骤 4:上报通话状态** - **接听**: ```java CallKitManager.getInstance().updateCallState(callId, CallKitConstants.VOIP_CALL_STATE_ACTIVE); ``` > **注意**:通话接听时,可能会因为网络等原因,从用户点击接听到通话真正被接通的过程时间可能会比较长(比如,1s左右),通知的样式会一直停留在来电状态,用户可能认为点击接听无响应,体验不好,建议在接听的过程中再上报一次通话状态VOIP_CALL_STATE_ANSWERED,系统会在界面上给用户以反馈。 - **拒接**: 拒接成功后上报 `VOIP_CALL_STATE_DISCONNECTED`,系统会取消通话横幅通知。 --- **步骤 5:上报通话中的音频事件** 在通话过程中,用户可以根据实际需要选择不同的音频通路,包括手机听筒、免提扬声器、蓝牙设备和有线耳机等。当通话的音频通路被切换,应用在完成通话音频通路切换后,需通过调用接口上报当前通知的音频通路。 > 详细开发步骤与去电场景相同,请参考 [5.1.2 步骤 5](#513-开发步骤)。 --- **步骤 6:上报应用内通话类型变化** 通话类型分视频通话和语音通话两种,对于视频来电语音接听、通话中视频降语音或者语音升视频,需要应用调用接口上报通话类型变化。 > 详细开发步骤与去电场景相同,请参考 [5.1.2 步骤 6](#513-开发步骤)。 --- **步骤 7:上报通话结束** 用户在通知上点击挂断按钮,应用会收到挂断电话回调,在应用内处理完成挂断后,需立即通过调用接口上报通话结束状态。 > **注意**:为了确保功能完整(如系统状态同步、资源释放等),通话结束后,开发者需要确保调用此接口上报通话结束状态。详细开发步骤与去电场景相同,请参考 [5.1.2 步骤 7](#513-开发步骤)。 --- **步骤 8:取消注册** 通话结束后取消订阅。 > 详细开发步骤与去电场景相同,请参考 [5.1.2 步骤 8](#513-开发步骤)。 --- **步骤 9:上报通话异常** 当通话出现异常时,应用需通过接口上报通话失败的原因。 > 详细开发步骤与去电场景相同,请参考 [5.1.2 步骤 9](#513-开发步骤)。 --- ## 6. API 参考 ### 6.1 枚举定义 #### 6.1.1 通话类型 (VoipCallType) | 枚举名称 | 值 | 说明 | | ------------------------ | -- | -------- | | `VOIP_CALL_TYPE_VOICE` | 0 | 语音通话 | | `VOIP_CALL_TYPE_VIDEO` | 1 | 视频通话 | #### 6.1.2 通话状态 (VoipCallState) | 枚举名称 | 值 | 说明 | | --------------------------------- | -- | ------------ | | `VOIP_CALL_STATE_IDLE` | 0 | 空闲 | | `VOIP_CALL_STATE_CONNECTING` | 1 | 建立通话连接 | | `VOIP_CALL_STATE_DIALING` | 3 | 拨号中 | | `VOIP_CALL_STATE_RINGING` | 4 | 来电响铃 | | `VOIP_CALL_STATE_ACTIVE` | 5 | 通话中 | | `VOIP_CALL_STATE_HOLDING` | 6 | 通话保持 | | `VOIP_CALL_STATE_DISCONNECTED` | 7 | 通话结束 | | `VOIP_CALL_STATE_ABORTED` | 8 | 通话中断 | | `VOIP_CALL_STATE_DISCONNECTING` | 9 | 通话结束中 | | `VOIP_CALL_STATE_PULLING` | 10 | 通话切回 | | `VOIP_CALL_STATE_ANSWERED` | 11 | 接听中 | #### 6.1.3 通话音频通路 | 枚举名称 | 值 | 说明 | | --------------------------- | -- | ---------- | | `ROUTE_EARPIECE` | 1 | 听筒 | | `ROUTE_BLUETOOTH` | 2 | 蓝牙 | | `ROUTE_WIRED_HEADSET` | 4 | 耳机 | | `ROUTE_SPEAKER` | 8 | 免提 | | `ROUTE_STREAMING` | 16 | 外接设备 | | `ROUTE_WIRED_OR_EARPIECE` | 5 | 耳机或听筒 | | `ROUTE_ALL` | 31 | 所有通路 | #### 6.1.4 错误码 | 枚举名称 | 值 | 说明 | | ------------------------------ | ---- | ------------------------ | | `ERROR_NONE` | 0 | 无错误 | | `CELLULAR_CALL_EXISTS` | 1 | 当前已存在蜂窝通话 | | `VOIP_CALL_EXISTS` | 2 | 当前已存在其他应用内通话 | | `INVALID_CALL` | 3 | 通话无效 | | `USER_ANSWER_CELLULAR_FIRST` | 4 | 用户选择接听蜂窝 | | `ERROR_GET_USER_INFO` | 1001 | 获取用户信息失败 | | `ERROR_NO_AUDIO_PERMISSION` | 1002 | 没有麦克风权限 | | `ERROR_NO_CAMERA_PERMISSION` | 1003 | 没有相机权限 | | `ERROR_RTC_INIT` | 1004 | RTC 初始化失败 | --- ### 6.2 数据模型 #### 6.2.1 VoipCall 对象 | 参数 | 类型 | 只读 | 可选 | 说明 | | ----------------------------- | ------------- | ---- | ---- | ----------------------------------- | | `callId` | String | 否 | 否 | 应用内通话唯一 ID | | `voipCallType` | VoipCallType | 否 | 否 | 应用内通话类型 | | `userName` | String | 否 | 否 | 用户昵称 | | `userProfile` | byte[] | 否 | 是 | 头像 | | `packageName` | String | 否 | 否 | 接听后需加载的应用名 | | `activityName` | String | 否 | 否 | 接听后需加载的应用界面名 | | `voipCallState` | VoipCallState | 否 | 否 | 应用内通话状态 | | `showBannerForIncomingCall` | boolean | 否 | 是 | 是否显示横幅通知,默认 true | | `isConferenceCall` | boolean | 否 | 是 | 是否为会议通话,默认 false | | `isVoiceAnswerSupported` | boolean | 否 | 是 | 视频来电是否支持语音接听,默认 true | > **注意**:`activityName` 对应的界面需要设置 `android:exported="true"` --- ### 6.3 API 接口 #### 6.3.1 on ```java int on(Application context) ``` **功能描述**:订阅 VoIP Call UI 事件,判断当前手机环境是否支持 VoIP Service Kit **参数**: - `context`:Application - 应用上下文 **返回值**: - `ERROR_NONE`:支持 VoIP Service Kit - `ERROR_FEATURE_UNSUPPORTED`:系统不支持 VoIP Service Kit --- #### 6.3.2 register ```java int register(CallKitCallBack callback) ``` **功能描述**:注册 VoIP 通话回调事件 **参数**: - `callback`:CallKitCallBack - 回调函数,返回通话事件详细信息 **返回值**: - `ERROR_NONE`:注册成功 - 其他错误码:注册失败 **CallKitCallBack 回调函数详情** `CallKitCallBack` 是 VoIP 通话事件的核心回调接口,当用户对通话通知进行操作时,会触发相应的回调方法。该接口包含以下回调函数: | 回调函数 | 参数 | 说明 | | -------- | ---- | ---- | | `answerCall` | `String callId` | 用户点击通知栏接听按钮时触发,返回通话唯一标识 | | `answerCallWithType` | `String callId, int callType` | 用户以特定通话类型接听时触发(如视频来电语音接听),返回通话标识和通话类型 | | `rejectCall` | `String callId` | 用户点击通知栏拒接按钮时触发,返回通话唯一标识 | | `changeCallType` | `String callId, int callType` | 用户切换通话类型时触发(如语音转视频),返回通话标识和目标通话类型 | | `disconnectCall` | `String callId` | 用户点击通知栏挂断按钮时触发,返回通话唯一标识 | | `mute` | `String callId, boolean mute` | 用户点击静音/取消静音按钮时触发,返回通话标识和静音状态 | | `changeAudioRoute` | `String callId, int route` | 用户切换音频通路时触发(如切换扬声器/听筒),返回通话标识和目标音频通路 | | `onCallKitEvent` | `int event, Bundle extras` | 其他 通话 事件通知,`event` 为事件类型,`extras` 包含扩展信息 | **使用示例**: ```java CallKitCallBack mCallKitCallBack = new CallKitCallBack() { @Override public void answerCall(String callId) { // 处理接听事件 CallKitLog.i(TAG, "answerCall callId " + callId); } @Override public void answerCallWithType(String callId, int callType) { // 处理带类型的接听事件 CallKitLog.i(TAG, "answerCallWithType callId " + callId + ", type " + callType); } @Override public void rejectCall(String callId) { // 处理拒接事件 CallKitLog.i(TAG, "rejectCall callId " + callId); } @Override public void changeCallType(String callId, int callType) { // 处理通话类型切换事件 CallKitLog.i(TAG, "changeCallType callId " + callId + ", type " + callType); } @Override public void disconnectCall(String callId) { // 处理挂断事件 CallKitLog.i(TAG, "disconnectCall callId " + callId); } @Override public void mute(String callId, boolean mute) { // 处理静音事件 CallKitLog.i(TAG, "mute callId " + callId + ", mute " + mute); } @Override public void changeAudioRoute(String callId, int route) { // 处理音频通路切换事件 CallKitLog.i(TAG, "changeAudioRoute callId " + callId + ", route " + route); } @Override public void onCallKitEvent(int event, Bundle extras) { // 处理其他 通话 事件 CallKitLog.i(TAG, "onCallKitEvent: " + event + " , extras " + extras); } }; ``` --- #### 6.3.3 off ```java int off() ``` **功能描述**:取消注册 **注意**:取消注册后,下次使用需重新调用 `register` 接口 --- #### 6.3.4 reportIncomingCall ```java void reportIncomingCall(VoipCall voipCall) void reportIncomingCall(VoipCall voipCall, ServerCallBack callBack) ``` **功能描述**:上报通知系统有来电消息 **参数**: - `voipCall`:VoipCall - 通话详细信息 - `callBack`:ServerCallBack - 服务状态监听回调,voip 应用可以监听 CallServer 的状态 **注意**:如果来电建立失败,需调用 `reportCallError` **ServerCallBack 回调函数详情** `ServerCallBack` 是 CallServer 服务状态监听回调接口,用于监听 VoIP 通话服务的连接状态。该接口包含以下回调函数: | 回调函数 | 说明 | | -------- | ---- | | `onServerConnecting` | CallServer 服务正在连接中,此时通话服务尚未就绪 | | `onServerReady` | CallServer 服务已就绪,可以正常进行通话管理 | | `onServerFail` | CallServer 服务连接失败,无法进行通话管理 | **使用示例**: ```java ServerCallBack serverCallBack = new ServerCallBack() { @Override public void onServerConnecting() { // 服务正在连接 CallKitLog.i(TAG, "CallServer is connecting..."); } @Override public void onServerReady() { // 服务已就绪 CallKitLog.i(TAG, "CallServer is ready"); } @Override public void onServerFail() { // 服务连接失败 CallKitLog.e(TAG, "CallServer connection failed"); } }; // 上报来电时传入回调 CallKitManager.getInstance().reportIncomingCall(call, serverCallBack); ``` --- #### 6.3.5 reportOutgoingCall ```java void reportOutgoingCall(VoipCall voipCall) void reportOutgoingCall(VoipCall voipCall, ServerCallBack callBack) ``` **功能描述**:应用上报去电消息 **参数**: - `voipCall`:VoipCall - 通话详细信息 - `callBack`:ServerCallBack - 服务状态监听回调,voip 应用可以监听 CallServer 的状态 **ServerCallBack 回调函数详情** `ServerCallBack` 是 CallServer 服务状态监听回调接口,用于监听 VoIP 通话服务的连接状态。该接口包含以下回调函数: | 回调函数 | 说明 | | -------- | ---- | | `onServerConnecting` | CallServer 服务正在连接中,此时通话服务尚未就绪 | | `onServerReady` | CallServer 服务已就绪,可以正常进行通话管理 | | `onServerFail` | CallServer 服务连接失败,无法进行通话管理 | **使用示例**: ```java ServerCallBack serverCallBack = new ServerCallBack() { @Override public void onServerConnecting() { // 服务正在连接 CallKitLog.i(TAG, "CallServer is connecting..."); } @Override public void onServerReady() { // 服务已就绪 CallKitLog.i(TAG, "CallServer is ready"); } @Override public void onServerFail() { // 服务连接失败 CallKitLog.e(TAG, "CallServer connection failed"); } }; // 上报去电时传入回调 CallKitManager.getInstance().reportOutgoingCall(call, serverCallBack); ``` --- #### 6.3.6 reportCallAudioRouteEvent ```java void reportCallAudioRouteEvent(String callId, int currentRoute, int supportRoute) ``` **功能描述**:上报通话中的音频通路变化事件 **参数**: - `callId`:String - 通话唯一标识 - `currentRoute`:int - 当前音频通路 - `supportRoute`:int - 当前支持的音频通路 --- #### 6.3.7 updateCallState ```java void updateCallState(String callId, int callState) ``` **功能描述**:通知系统通话状态变化 > **注意**:为了确保功能完整(如系统状态同步、资源释放等),通话结束后,开发者需要确保调用此接口上报通话结束状态。 **参数**: - `callId`:String - 通话唯一标识 - `callState`:int - 通话状态 --- #### 6.3.8 updateCallType ```java void updateCallType(String callId, int callType) ``` **功能描述**:通知系统通话类型变化(如视频降语音、语音升视频) **参数**: - `callId`:String - 通话唯一标识 - `callType`:int - 通话类型 --- #### 6.3.9 reportCallError ```java void reportCallError(String callId, int errorCode, String errorMessage) ``` **功能描述**:通知通话失败原因 **参数**: - `callId`:String - 通话唯一标识 - `errorCode`:int - 错误码 - `errorMessage`:String - 错误描述 --- ## 软件架构 ### 技术栈 | 项目 | 说明 | | -------- | -------------------------------------------- | | 开发语言 | Java | | 构建系统 | Gradle 7.2.0 | | 目标SDK | Android 34 (API Level 34) | | 最小SDK | Android 34 (API Level 34) | | 架构模式 | 基于 Android 原生架构 | | UI框架 | Android 原生 UI + 自定义 View | | 通信机制 | AIDL (Android Interface Definition Language) | --- ## 安装教程 ### 环境要求 | 环境项 | 要求 | | -------------- | --------------------------- | | 操作系统 | Windows 10/11, macOS, Linux | | Android Studio | 2021.1.1 或更高版本 | | JDK | JDK 8 或更高版本 | | Android SDK | API Level 34 | | Gradle | 7.2.0 或更高版本 | ### 构建 AAR 包 **步骤 1:克隆项目** ```bash git clone https://gitee.com/itgsa/callservicedemo.git cd android_packages_apps_CallService ``` **步骤 2:打开项目** - 启动 Android Studio - 选择 "Open an existing Android Studio project" - 选择项目根目录 **步骤 3:同步项目** - Android Studio 会自动提示同步 Gradle 文件 - 点击 "Sync Now" 等待同步完成 **步骤 4:构建 AAR 包** ```bash # 构建 Debug 版本 AAR ./gradlew assembleDebug # 构建 Release 版本 AAR ./gradlew assembleRelease ``` **步骤 5:获取 AAR 文件** - AAR 文件位置:`app/build/outputs/aar/app-debug.aar` 或 `app/build/outputs/aar/app-release.aar` ### 集成到目标应用 **步骤 1:添加 AAR 依赖** 将生成的 AAR 文件复制到目标应用的 `libs/` 目录,在目标应用的 `build.gradle` 中添加: ```groovy dependencies { implementation files('libs/app-release.aar') } ``` **步骤 2:配置权限** 在目标应用的 `AndroidManifest.xml` 中添加必要权限: ```xml ``` **步骤 3:初始化服务** 在目标应用启动时初始化 CallService: ```java // 在 Application 或 Activity 中初始化 CallServiceManager.getInstance().init(context); ``` ### 权限配置 由于该应用需要系统级权限,请在安装前确保: 1. 开发者选项已启用 2. USB 调试已开启 3. 未知来源应用安装已允许 --- ## 使用说明 ### 通话功能 - 来电时自动显示来电界面 - 支持按钮接听/挂断 - 通话过程中可切换音频设备 ### 音频控制 - 支持扬声器、耳机、蓝牙设备切换 ### 悬浮窗控制 - 通话时可显示悬浮窗 - 支持快速挂断等操作 --- ## 参与贡献 1. Fork 本仓库 2. 新建 Feat_xxx 分支 3. 提交代码 4. 新建 Pull Request