# 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