CallSDK Android 接⼊⽂档

CallSDK Android 接入文档

1. 概述

CallSDK 是一款 Android 通话 SDK,提供通话初始化、拨号、通话控制(挂断 / 静音 / 扬声器 / DTMF)、外显号码配置等核心功能。

核心特性

  • 支持音频通话(SIP 协议)
  • 支持两种通话场景:主动外呼服务端发起通话
  • 外显号码组 / 号码配置
  • 通话状态监听(振铃 / 接听 / 挂断 / 失败)
  • 通话控制(静音、扬声器、DTMF 发送)

通话场景说明

场景 说明 触发方式
主动外呼 开发者调用 makeCall() 发起通话 开发者主动调用
服务端发起通话 服务端调度通话任务,SDK 自动接听 SIP SDK 自动处理,通过 OnServerCallListener 通知开发者

架构概览

┌──────────────────────────────────────────────────────────┐
│                       CallSDK                             │
│                                                          │
│  ① InitListener          → 初始化结果                     │
│  ② OnServerCallListener  → 服务端通话通知(开发者打开页面) │
│  ③ CallStateListener     → 通话状态变化(开发者更新 UI)   │
│  ④ MakeCallCallback      → 外呼发起结果                   │
│  ⑤ setOnKickedListener   → 被踢下线通知                   │
└──────────────────────────────────────────────────────────┘

2. 环境准备

2.1 权限声明

AndroidManifest.xml 中添加必要权限:

<!-- 网络权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />

<!-- 音频/通话权限 -->
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />

<!-- 蓝牙耳机相关 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- Android 12+ 需要 BLUETOOTH_CONNECT 权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />

注意RECORD_AUDIO 需要动态申请,没有权限拨打会失败。

2.2 依赖引入

  1. 版本更新日志 中最新的 callsdk-xxx.aar 拷贝至 app/libs 目录
  2. 在模块 build.gradle 中配置:
android {
    repositories {
        flatDir {
            dirs 'libs'
        }
    }
}

dependencies {
    implementation(name: 'callsdk-xxx', ext: 'aar')
    // 如果项目中没有引入 okhttp,需要加入
    implementation 'com.squareup.okhttp3:okhttp:4.9.3'
}

3. 快速集成

所有回调均在主线程触发,可直接更新 UI。

3.1 初始化 SDK

// 1. 配置 SDK 参数
val config = SDKConfig(
    username = account,
    password = password,       // 与 passwordPk 二选一
    passwordPk = passwordPk,   // 与 password 二选一
    baseUrl = Environment.DEBUG,
    logConfig = LogConfig(
        enableLog = true,
        logLevel = Log.INFO,
        logFilePath = null,         // null 使用默认路径:filesDir/logs
        fileLoggingEnabled = true,
        consoleLogEnabled = true
    )
)

// 2. 初始化 SDK(含登录)
CallSDK.init(
    context = applicationContext,
    config = config,
    object : InitListener {
        override fun onInitSuccess() {
            // 初始化成功(含登录成功),SDK 就绪
        }

        override fun onInitFailed(errorCode: Int, errorMsg: String?) {
            // 初始化失败,错误码详见「5.1 初始化错误」
        }
    }
)

// 3. 设置被踢下线监听(独立于 init,全局生效)
CallSDK.setOnKickedListener {
    // 账号被踢下线
}

3.2 监听服务端发起的通话

当服务端发起通话时,SDK 会自动接听 SIP,然后通过此监听器通知开发者。开发者应在回调中打开通话界面

// 建议在初始化成功后设置(如在主页面 onCreate 中)
CallSDK.setOnServerCallListener { callInfo ->
    // 收到服务端发起的通话,打开通话界面
    val intent = Intent(this, CallActivity::class.java)
    intent.putExtra("callId", callInfo.callId)
    intent.putExtra("direction", callInfo.direction.name)
    startActivity(intent)
}

3.3 监听通话状态

通话状态监听器用于在通话界面中更新 UI,适用于主动外呼和服务端发起的通话

class CallActivity : AppCompatActivity() {

    private val callStateListener = object : CallStateListener {
        override fun onCallAlerting(callInfo: CallInfo) {
            // 对方振铃中
        }

        override fun onCallAnswered(callInfo: CallInfo) {
            // 对方已接听,通话建立
        }

        override fun onCallReleased(callInfo: CallInfo) {
            // 通话已结束
        }

        override fun onCallFailed(callInfo: CallInfo, errorCode: Int, errorMsg: String) {
            // 通话失败,错误码详见「5.2 呼叫错误」
        }

        override fun onDtmfReceived(callInfo: CallInfo, dtmf: String) {
            // 收到 DTMF 信号
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // 注册通话状态监听器
        CallSDK.addCallStateListener(callStateListener)

       
    }

    override fun onDestroy() {
        super.onDestroy()
        // 移除通话状态监听器
        CallSDK.removeCallStateListener(callStateListener)
    }

}

3.4 拨打电话

CallSDK.makeCall(
    phoneNumber = "13800138000",
    callback = object : MakeCallCallback {
        override fun onSuccess(callInfo: CallInfo) {
            // 呼叫已成功发出
            // 后续通话状态通过 CallStateListener 接收
        }

        override fun onFailed(errorCode: Int, errorMsg: String) {
            // 呼叫发起失败(黑名单、风控、网络等原因)
            // 错误码详见「5.2 呼叫错误」
        }
    }
)

3.5 拨打电话携带自定义参数

自定义参数为 JSONObject 类型,大小限制 < 256 字节,超出会触发 onFailed

val userData = JSONObject().apply {
    put("orderId", "12345")
    put("source", "crm")
}

CallSDK.makeCall(
    phoneNumber = "13800138000",
    userData = userData,
    callback = object : MakeCallCallback {
        override fun onSuccess(callInfo: CallInfo) {
            // 呼叫已成功发出
        }

        override fun onFailed(errorCode: Int, errorMsg: String) {
            // 呼叫发起失败
        }
    }
)

3.6 挂断电话

CallSDK.hangupCall()

3.7 发送 DTMF

// 发送单个 DTMF 信号(如:*、#、0-9)
CallSDK.sendDTMF("1")

3.8 扬声器控制

// 打开/关闭扬声器
CallSDK.openLoudSpeaker(true)  // true: 打开,false: 关闭

// 获取扬声器状态
val isSpeakerOn = CallSDK.isLoudSpeakerOn()

3.9 静音控制

// 开启/关闭静音
CallSDK.openMute(true)  // true: 静音,false: 取消静音

// 获取静音状态
val isMute = CallSDK.isMuteOn()

3.10 查询外显号码组列表

CallSDK.queryNumberGroupList(
    page = 1,
    pageSize = 20,
    listener = object : NumberGroupListListener {
        override fun onSuccess(response: NumberGroupListResponse?) {
            // 查询成功
        }
        override fun onFailed(errorMsg: String?) {
            // 查询失败
        }
    }
)

3.11 查询外显号码列表

CallSDK.queryDisplayNumberList(
    listener = object : DisplayNumberListListener {
        override fun onSuccess(numbers: List<DisplayNumber>?) {
            // 查询成功
        }
        override fun onFailed(errorMsg: String?) {
            // 查询失败
        }
    }
)

3.12 设置座席外显号码组(通过号码组 ID)

CallSDK.updateAgentNumberGroupById(
    numberGroupId = "001",
    listener = object : AgentConfigListener {
        override fun onSuccess(config: AgentConfig?) {
            // 设置成功
        }
        override fun onFailed(errorMsg: String?) {
            // 设置失败
        }
    }
)

3.13 设置座席外显号码组(通过号码组名称)

CallSDK.updateAgentNumberGroupByName(
    numberGroupName = "group_name",
    listener = object : AgentConfigListener {
        override fun onSuccess(config: AgentConfig?) {
            // 设置成功
        }
        override fun onFailed(errorMsg: String?) {
            // 设置失败
        }
    }
)

3.14 设置座席自定义外显号码

CallSDK.updateAgentSelectNumber(
    selectNumber = "010-12345678",
    listener = object : AgentConfigListener {
        override fun onSuccess(config: AgentConfig?) {
            // 设置成功
        }
        override fun onFailed(errorMsg: String?) {
            // 设置失败
        }
    }
)

3.15 查询座席配置

CallSDK.getAgentConfig(
    listener = object : AgentConfigListener {
        override fun onSuccess(config: AgentConfig?) {
            // 查询成功
        }
        override fun onFailed(errorMsg: String?) {
            // 查询失败
        }
    }
)

3.16 获取登录信息

val loginInfo = CallSDK.getLoginInfo()

3.17 获取当前通话信息

val callInfo = CallSDK.getCurrentCallInfo()
// callInfo?.callId       — 通话 ID
// callInfo?.phoneNumber  — 电话号码
// callInfo?.direction    — 通话方向(APP / SERVER)
// callInfo?.state        — 当前状态(CALLING / ALERTING / ANSWERED / RELEASED / FAILED)
// callInfo?.startTime    — 通话开始时间戳

3.18 注销登录

CallSDK.logout()

3.19 销毁 SDK

销毁 SDK 实例,释放所有资源(通话、连接、监听器等)。

CallSDK.release()

4. 数据模型

4.1 CallInfo — 通话信息

字段 类型 说明
callId String? 通话 ID
phoneNumber String? 电话号码
direction CallDirection 通话方向
state CallState 当前通话状态
startTime Long 通话开始时间(毫秒时间戳)

4.2 CallDirection — 通话方向

说明
APP APP 端发起(开发者主动调用 makeCall()
SERVER 服务端发起,SDK 自动接听

4.3 CallState — 通话状态

说明
CALLING 呼叫发起中
ALERTING 对方振铃中
ANSWERED 通话中(对方已接听)
RELEASED 通话已结束
FAILED 通话失败

4.4 通话状态流转

主动外呼:
  CALLING → ALERTING → ANSWERED → RELEASED
                    └→ FAILED

服务端发起:
  CALLING → ALERTING → ANSWERED → RELEASED
                    └→ FAILED

5. 错误码

5.1 错误码分类

错误码范围 分类 说明
0 成功 操作成功
-1 ~ -99 初始化错误 SDK 初始化相关错误
-100 ~ -199 参数验证错误 输入参数验证失败
-200 ~ -299 登录流程错误 登录、认证、SIP 注册相关错误
-300 ~ -399 通话相关错误 呼叫、通话控制相关错误
-400 ~ -499 网络错误 网络连接、超时相关错误
-2000 ~ -2099 HTTP 请求错误 HTTP 接口调用错误
-2100 ~ -2199 WebSocket 错误 WebSocket 连接相关错误
-4000 ~ -4099 外显号码错误 外显号码配置相关错误
-9999 未知错误 未定义的错误

5.2 通用错误

错误码 常量名 原因
-9999 UNKNOWN_ERROR 未知错误(网络异常、解析失败等兜底错误)

5.3 初始化错误(-1 ~ -99)

错误码 常量名 原因
-1 SDK_INIT_FAILED SDK 初始化失败
-2 SDK_NOT_INITIALIZED SDK 未初始化
-3 PJSIP_CREATE_FAILED PJSIP 创建失败
-4 PJSIP_INIT_FAILED PJSIP 初始化失败
-5 TRANSPORT_CREATE_FAILED 传输层创建失败(UDP/TCP)
-6 PJSIP_START_FAILED PJSIP 启动失败

5.4 参数验证错误(-100 ~ -199)

错误码 常量名 原因
-100 INVALID_ACCOUNT 账号无效
-101 INVALID_PASSWORD 密码无效
-104 ACCOUNT_FORMAT_ERROR 账号格式错误
-105 ACCOUNT_EMPTY 账号为空
-106 PASSWORD_EMPTY 密码为空
-107 SERVER_URL_EMPTY 服务器 URL 为空
-108 TOKEN_EMPTY Token 为空

5.5 登录流程错误(-200 ~ -299)

通过 InitListener.onInitFailed(errorCode, errorMsg) 回调返回。

错误码 常量名 原因
-200 LOGIN_REQUEST_FAILED 登录请求失败
-201 LOGIN_AUTH_FAILED 登录认证失败
-202 LOGIN_FAILED_WRONG_CREDENTIALS 登录失败,账号或密码错误
-203 SOCKET_CONNECT_FAILED Socket 连接失败
-205 SIP_CONFIG_FAILED 获取 SIP 配置失败
-206 SIP_CONFIG_INCOMPLETE SIP 配置信息不完整
-207 SIP_REGISTER_FAILED SIP 注册失败(通用)
-209 SIP_REGISTER_REJECTED SIP 注册被拒绝 (403)
-210 LOGIN_FAILED_ACCOUNT_FROZEN 账号已被冻结,请联系管理员解冻
-211 AGENT_DISABLED 坐席已停用
-212 ACCOUNT_NOT_FOUND 账户未找到
-213 AGENT_NOT_FOUND 坐席未找到
-215 SIP_REGISTER_NOT_FOUND SIP 注册未找到 (404)
-216 SIP_REGISTER_SERVER_ERROR SIP 注册服务器错误 (5xx)
-217 GET_PUBLIC_KEY_FAILED 获取公钥失败

5.6 通话相关错误(-300 ~ -399)

通过 MakeCallCallback.onFailed(errorCode, errorMsg)CallStateListener.onCallFailed(callInfo, errorCode, errorMsg) 回调返回。

错误码 常量名 原因 触发阶段
-300 CALL_FAILED 呼叫失败(通用) 通话中(SIP 层)
-301 CALL_PERMISSION_DENIED 通话权限被拒绝 拨号前
-302 CALL_NOT_LOGGED_IN 未登录无法呼叫 拨号前
-303 CALL_NUMBER_EMPTY 呼叫号码为空 拨号前
-304 CALL_REJECTED 呼叫被拒绝 (403) 通话中(SIP 层)
-305 CALL_NUMBER_NOT_FOUND 号码不存在 (404) 通话中(SIP 层)
-306 CALL_USER_BUSY 用户忙线 (486) 通话中(SIP 层)
-307 CALL_REQUEST_TERMINATED 对方拒接或手机软件拦截 (487) 通话中(SIP 层)
-308 CALL_TIMEOUT 呼叫超时 (408) 通话中(SIP 层)
-309 CALL_TEMPORARILY_UNAVAILABLE 暂时不可用 (480) 通话中(SIP 层)
-310 CALL_FAILED_BLACKLIST 号码在黑名单中,无法拨打 拨号前(黑名单校验)
-311 CALL_FAILED_RISK_LIMIT 呼叫次数已达上限(风控拦截) 拨号前(风控查询)
-312 CALL_FAILED_USERDATA_TOO_LARGE userData 超过 255 字节限制 拨号前(参数校验)
-313 CALL_NOT_ACCEPTABLE 媒体协商失败 (488) 通话中(SIP 层)
-314 CALL_REGISTRATION_DROPPED SIP 注册掉线 (477) 通话中(SIP 层)
-315 CALL_NOT_EXIST 通话不存在 (481) 通话中(SIP 层)
-316 CALL_ADDRESS_INCOMPLETE 号码不完整 (484) 通话中(SIP 层)
-317 CALL_DECLINED 对方拒绝接听 (603) 通话中(SIP 层)
-318 CALL_BUSY_EVERYWHERE 全局忙线 (600) 通话中(SIP 层)
-319 CALL_SERVER_ERROR 服务器内部错误 (500) 通话中(SIP 层)
-320 CALL_BAD_GATEWAY 网关错误 (502) 通话中(SIP 层)
-321 CALL_SERVICE_UNAVAILABLE 服务不可用 (503) 通话中(SIP 层)
-322 CALL_SERVER_TIMEOUT 服务器超时 (504) 通话中(SIP 层)
-323 CALL_NETWORK_LOST 通话中网络中断 通话中(网络监听)

触发阶段说明:

  • 拨号前:在 makeCall() 调用后、SIP 拨号前触发,通过 MakeCallCallback.onFailed() 返回
  • 通话中:SIP 拨号后触发,通过 CallStateListener.onCallFailed() 返回

5.7 网络错误(-400 ~ -499)

错误码 常量名 原因
-401 NETWORK_TIMEOUT 网络超时

5.8 HTTP 请求错误(-2000 ~ -2099)

错误码 常量名 原因
-2001 HTTP_INVALID_URL 无效 URL
-2007 HTTP_ERROR HTTP 错误 (4xx, 5xx,通用)
-2008 HTTP_EMPTY_RESPONSE 空响应数据
-2009 HTTP_JSON_PARSE_FAILED JSON 解析失败

5.9 WebSocket 错误(-2100 ~ -2199)

错误码 常量名 原因
-2100 WS_INVALID_URL 无效的 WebSocket URL
-2101 WS_CONNECT_FAILED WebSocket 连接失败

5.10 外显号码错误(-4000 ~ -4099)

错误码 常量名 原因
-4001 DISPLAY_NUMBER_AGENT_ID_EMPTY 坐席 ID 为空
-4002 DISPLAY_NUMBER_CONFIG_FAILED 获取外显号码配置失败

5.13 错误处理建议

  1. 初始化错误:检查 SDK 是否正确集成,确保在调用其他方法前先初始化
  2. 参数验证错误:检查输入参数是否为空、格式是否正确
  3. 登录流程错误:检查账号密码、网络连接、服务器配置
  4. 通话相关错误:确保已登录且 SIP 连接成功,检查被叫号码格式
  5. 网络错误:检查网络连接状态,可能需要重试
  6. 未知错误:查看详细错误消息,联系技术支持

6. API 参考

6.1 初始化 & 生命周期

方法 说明
CallSDK.init(context, config, initListener) 初始化 SDK(含登录)
CallSDK.logout() 注销登录,释放通话和连接资源
CallSDK.release() 销毁 SDK 实例,释放所有资源(含监听器),调用后需重新 init()
CallSDK.getLoginInfo(): LoginInfo? 获取登录信息
CallSDK.getConfig(): SDKConfig 获取当前 SDK 配置

6.2 监听器

方法 说明
CallSDK.setOnServerCallListener(listener) 设置服务端通话监听器(全局唯一,传 null 移除)
CallSDK.setOnKickedListener(listener) 设置被踢下线监听器(全局唯一,传 null 移除)
CallSDK.addCallStateListener(listener) 添加通话状态监听器
CallSDK.removeCallStateListener(listener) 移除通话状态监听器

6.3 通话

方法 说明
CallSDK.makeCall(phoneNumber, callback) 发起通话
CallSDK.makeCall(phoneNumber, userData, callback) 发起通话(携带自定义参数)
CallSDK.hangupCall() 挂断当前通话
CallSDK.sendDTMF(dtmfNumber) 发送 DTMF 信号
CallSDK.getCurrentCallInfo(): CallInfo? 获取当前通话信息
CallSDK.getCurrentCallId(): String? 获取当前通话 ID

6.4 通话控制

方法 说明
CallSDK.openLoudSpeaker(open) 打开/关闭扬声器
CallSDK.isLoudSpeakerOn(): Boolean 获取扬声器状态
CallSDK.openMute(open) 开启/关闭静音
CallSDK.isMuteOn(): Boolean 获取静音状态

6.5 外显号码配置

方法 说明
CallSDK.queryNumberGroupList(page, pageSize, listener) 查询外显号码组列表
CallSDK.queryDisplayNumberList(listener) 查询外显号码列表
CallSDK.updateAgentNumberGroupById(id, listener) 设置座席外显号码组(通过 ID)
CallSDK.updateAgentNumberGroupByName(name, listener) 设置座席外显号码组(通过名称)
CallSDK.updateAgentSelectNumber(number, listener) 设置座席自定义外显号码
CallSDK.getAgentConfig(listener) 查询座席配置

6.6 监听器接口

InitListener — 初始化监听器

interface InitListener {
    fun onInitSuccess() {}
    fun onInitFailed(errorCode: Int, errorMsg: String?) {}
}

OnServerCallListener — 服务端通话监听器

fun interface OnServerCallListener {
    fun onServerCall(callInfo: CallInfo)
}

MakeCallCallback — 发起通话回调

interface MakeCallCallback {
    fun onSuccess(callInfo: CallInfo)
    fun onFailed(errorCode: Int, errorMsg: String)
}

CallStateListener — 通话状态监听器

interface CallStateListener {
    fun onCallAlerting(callInfo: CallInfo) {}
    fun onCallAnswered(callInfo: CallInfo) {}
    fun onCallReleased(callInfo: CallInfo) {}
    fun onCallFailed(callInfo: CallInfo, errorCode: Int, errorMsg: String) {}
    fun onDtmfReceived(callInfo: CallInfo, dtmf: String) {}
}

所有方法提供默认空实现,开发者只需 override 关心的回调。


7. 完整集成示例

7.1 最小集成(仅主动外呼)

// Application 或 LoginActivity 中
CallSDK.init(applicationContext, config, object : InitListener {
    override fun onInitSuccess() {
        
    }
})

// 通话页面中
class CallActivity : AppCompatActivity() {
    private val listener = object : CallStateListener {
        override fun onCallAlerting(callInfo: CallInfo) { /* 振铃中 */ }
        override fun onCallAnswered(callInfo: CallInfo) { /* 开始计时 */ }
        override fun onCallReleased(callInfo: CallInfo) { finish() }
        override fun onCallFailed(callInfo: CallInfo, errorCode: Int, errorMsg: String) {
            Toast.makeText(this@CallActivity, errorMsg, Toast.LENGTH_SHORT).show()
            finish()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        CallSDK.addCallStateListener(listener)
        CallSDK.makeCall("xxxxxxxxxx", object : MakeCallCallback {
            override fun onSuccess(callInfo: CallInfo) { /* 呼叫已发出 */ }
            override fun onFailed(errorCode: Int, errorMsg: String) { finish() }
        })
    }

    override fun onDestroy() {
        super.onDestroy()
        CallSDK.removeCallStateListener(listener)
    }
}

7.2 完整集成(主动外呼 + 服务端通话)

// ── 初始化后,设置全局监听 ──

// 服务端通话:收到通知后打开通话页面
CallSDK.setOnServerCallListener { callInfo ->
    val intent = Intent(context, CallActivity::class.java)
    intent.putExtra("callId", callInfo.callId)
    intent.putExtra("direction", CallDirection.SERVER.name)
    startActivity(intent)
}

// 被踢下线
CallSDK.setOnKickedListener {
    
}

// ── 通话页面(统一处理两种场景)──

class CallActivity : AppCompatActivity() {
    private lateinit var direction: CallDirection

    private val listener = object : CallStateListener {
        override fun onCallAlerting(callInfo: CallInfo) { /* 振铃中 */ }
        override fun onCallAnswered(callInfo: CallInfo) { /* 通话中 */ }
        override fun onCallReleased(callInfo: CallInfo) { finish() }
        override fun onCallFailed(callInfo: CallInfo, errorCode: Int, errorMsg: String) {
            Toast.makeText(this@CallActivity, errorMsg, Toast.LENGTH_SHORT).show()
            finish()
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        direction = CallDirection.valueOf(
            intent.getStringExtra("direction") ?: CallDirection.APP.name
        )

        // 注册监听
        CallSDK.addCallStateListener(listener)

        when (direction) {
            CallDirection.APP -> {
                // 主动外呼
                val phone = intent.getStringExtra("phoneNumber") ?: return
                CallSDK.makeCall(phone, object : MakeCallCallback {
                    override fun onSuccess(callInfo: CallInfo) { /* 呼叫已发出 */ }
                    override fun onFailed(errorCode: Int, errorMsg: String) { finish() }
                })
            }
            CallDirection.SERVER -> {
                
            }
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        CallSDK.removeCallStateListener(listener)
    }
}

8. Demo

Demo 集成了通话 SDK,包含自定义拨号盘页面和通话页面,UI 开发可参考 Demo。

8.1 前台服务

通话开始时会创建一个前台通知用来保活。

8.2 耳机

耳机的具体实现可参考 Demo:

  1. 需要增加蓝牙权限:
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />
<!-- Android 12+ -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
  1. HeadsetPlugReceiver — 具体实现可参考 Demo 中的 HeadsetPlugReceiver 类,实现了监听耳机插拔的逻辑。

9. 混淆配置

-keep class com.useasy.callsdk.** { *; }
-keep interface com.useasy.callsdk.** { *; }

10. 常见问题

10.1 初始化失败

  • 检查用户名 / 密码是否正确
  • 检查网络连接(需联网状态)
  • 检查环境地址是否可访问

10.2 通话无声音

  • 检查录音 / 扬声器权限是否授予
  • 检查设备音量是否正常

11. 注意事项

  1. 权限处理:Android 6.0+ 需动态申请录音权限,建议在拨号前检查并申请。
  2. 监听器生命周期addCallStateListenerremoveCallStateListener 必须成对调用,建议分别在 onCreateonDestroy 中调用。
  3. 服务端通话OnServerCallListener 应在初始化成功后尽早设置,避免错过通话通知。

12. 版本更新日志

版本号 更新时间 核心更新
1.3.2 2026-3-13 1. 通话中监听网络状态,3 秒未恢复网络则自动挂断
2. 网络未连接时不重连 Socket
3. 通话事件通知去重,修复连续两次 onCallAlerting 的 bug
4. 新增 release() 方法,支持完整销毁 SDK 实例
1.3.1 2026-3-11 1. 修复退出登录后重新登录再呼叫导致 crash 的问题
2. 精简 native .so 体积(去除strip 调试信息)
1.3.0 2026-2-28 1. 重构通话监听 API:统一 CallStateListener,支持 add/remove
2. 新增 OnServerCallListener 用于服务端通话通知
3. 新增 MakeCallCallback 分离外呼发起结果
4. 新增 getCurrentCallInfo() 支持页面状态同步
5. onKicked 独立为 setOnKickedListener
6. 新增 CallInfo 统一通话信息模型
7. 错误码对齐
8. 替换新的底层通话库
9. 优化日志
10. 修复通话bug
1.2.11 2026-1-16 1. 拨号前增加黑名单校验
2. 拨号前增加风控查询
1.2.10 2026-1-8 1. 优化通话回铃音杂音问题
1.2.9 2026-1-7 1. 修复通话震铃音问题
2. 设置外显号码组支持通过 id 和 name 设置
1.2.8 2026-1-6 1. onCallReleased 回调增加 hangupType 参数
2. 修复 onCallFailed 异常回调的问题
3. updateAgentNumberGroup 等接口去除 agent_id 参数
4. 增加日志
1.2.7 2025-12-31 1. 修复 crash
1.2.6 2025-12-28 1. SDKConfig 增加 passwordPk 参数
2. Demo 优化,动态申请蓝牙权限
1.2.5 2025-12-24 1. 兼容 okhttp 3.x 版本
2. LogConfig 支持 consoleLogEnabled 配置
1.2.4 2025-12-21 1. 外呼支持传递自定义参数
2. 初始化失败和外呼失败回调增加错误码和错误信息
3. 修复拨号信息残留 Bug
4. 修复通话声音小、有回音的问题
5. 优化日志
1.2.3 2025-12-19 1. 增加响铃中回调 onCallAlerting
2. 增加日志配置 LogConfig
3. 保留 init 参数中的 Context,去除其他方法的 Context 参数
4. 去除 setMute 方法
5. 优化 SDK,增加状态类型
1.2.2 2025-12-18 1. 支持蓝牙耳机/耳机通话
2. 优化 SDK 接口
3. SDK 回调统一回调在主线程
1.2.1 2025-12-16 1. 资源精简
2. 修复 Demo 计时基准错误问题
1.2.0 2025-12-15 1. 修复对端挂断电话无法收到回调的问题
2. 通话增加前台通知,启动前台 Service
3. 资源精简
1.0.0 2025-11-30 初始版本,支持音频通话、外显号码配置、通话控制

13. 从 1.2.x 迁移到 1.3.0

主要变更

旧 API 新 API 说明
CallSDK.makeCall(phone, CallStateListener) CallSDK.makeCall(phone, MakeCallCallback) + addCallStateListener() 外呼发起结果和通话状态分离
CallSDK.setServerCallListener(ServerCallStateListener) CallSDK.setOnServerCallListener(OnServerCallListener) 简化为单一回调
InitListener.onKicked() CallSDK.setOnKickedListener { } 独立为全局监听
CallStateListener 回调参数为 callId: String? 回调参数为 callInfo: CallInfo 统一通话信息模型
onCallReleased(hangupType, callId) onCallReleased(callInfo) hangupType 信息后续通过 CallInfo 扩展
onCallProceeding(callId) 已移除 内部状态,不再暴露
onConnected() / onDisconnected() 已移除 SIP 内部状态,不再暴露
onIncomingCall(callId) 已移除 SDK 自动接听,不再暴露

迁移步骤

  1. InitListener 中的 onKicked() 改为 CallSDK.setOnKickedListener { }
  2. makeCallCallStateListener 参数改为 MakeCallCallback
  3. 在通话页面 onCreate 中调用 CallSDK.addCallStateListener(listener)
  4. 在通话页面 onDestroy 中调用 CallSDK.removeCallStateListener(listener)
  5. 更新所有回调方法签名,参数从 callId: String? 改为 callInfo: CallInfo
AndroidCallSDK.zip
11.4 MB
压缩包中包含demo示例,demo 集成了通话 SDK,同时还有自定义的拨号盘页面以及通话页面,UI 开发可参考 Demo
2026-03-13