音视频通话
通话信令通过 im.calls,媒体、音频设备和系统来电由 im-call 提供,连接平台自建 LiveKit。先在平台配置媒体服务并为应用开启音视频,App 不能自行填写服务端媒体密钥。
安装和权限
引入 im-call,配置概述中的 JitPack 仓库。初始化时提供 DRCallOptions:
import com.deeprespond.im.*
import com.deeprespond.im.call.*
val options = DRClientOptions(
appKey = "org#app",
apiUrl = "https://api.example.com",
call = DRCallOptions(incomingCallActivity = IncomingCallActivity::class.java),
)IncomingCallActivity 是 App 自己的 Activity,必须在清单声明。Library 清单提供通话服务、通知、音频、摄像头等权限声明,运行时授权由 App 完成。音频需 RECORD_AUDIO,视频另需 CAMERA;通知和蓝牙权限按系统版本申请。Android 14 起全屏通知的可用性和 Google Play 声明由 App 负责。
<activity
android:name=".IncomingCallActivity"
android:exported="false"
android:showWhenLocked="true"
android:turnScreenOn="true" />DRCallOptions 还提供 useTelecom(默认 true)、autoBusy(默认 true)、ringtone。需要离线来电时同时配置推送。calls.supported 可检查媒体能力是否接入,不能把有信令接口当作已经配置完媒体。
发起、接听与结束
import com.deeprespond.im.*
val call = im.calls.start(CallMedia.AUDIO, CallTarget.User("bob"))
// 拿到句柄后,按业务界面管理当前通话。
println(call.callId)群通话使用 CallTarget.Group(groupId, usernames?),media 可选 VIDEO。incoming 是待处理来电 StateFlow,current 是当前通话。监听 CallIncoming 或 incoming 后展示来电页,取得对应 CallHandle:
call.join() // 用户接听。
call.setMicrophoneEnabled(false)
call.setCameraEnabled(false)
call.hangup() // 本设备退出通话。join 接听或加入,reject 拒接(DECLINED / BUSY),hangup 本人离开,end 结束整个通话(需要权限)。invite 批量邀请并返回逐项结果,resume 恢复媒体连接。不要把 hangup 与 end 混用。
状态与历史
call.snapshot 包含服务端通话及本地媒体状态,call.tracks 提供音视频轨道,call.data 接收媒体数据消息。sendData(ByteArray) 发送临时媒体数据,不代替可靠聊天消息。
get(callId) 获取句柄,history(cursor?, limit?) 分页查记录;groupCall(groupId) 获取群当前通话,groupCallBanner 返回界面横幅信息。观察 CallChanged、GroupCallChanged 更新界面。
视频和音频设备
import com.deeprespond.im.call.*
val view = DRCallVideoView(context)
view.scaleType = DRCallVideoView.ScaleType.FIT
view.mirror = false
val track = call.tracks.value.local
view.bind(call, track)
// 轨道变化时重新 bind;页面不显示时 unbind。
view.unbind()DRCallVideoView 需要实际加入视图树,bind 的轨道可为 null。tracks 的本地 / 远端轨道变化时重新绑定,不要缓存旧轨道。
import com.deeprespond.im.call.*
call.switchCamera()
call.setSpeakerphoneOn(true)
val devices = call.audioEndpoints.value
val selected = devices.available.firstOrNull()
if (selected != null) call.setAudioEndpoint(selected)audioEndpoints 是 StateFlow,包含 available 和 current,类型包括耳机、听筒、扬声器、蓝牙和流媒体设备。权限或设备状态可能导致切换失败。
系统来电和后台
DRCallUI.of(im) 返回控制器,未配置时为 null。canUseFullScreenIntent / openFullScreenIntentSettings 检查与打开全屏通知设置;callChannelEnabled 检查来电渠道。intentCall(intent) 解析来电入口,actions 收集通知或 Telecom 的操作。
Core-Telecom 和前台服务用于系统通话集成及保持媒体。App 应处理权限、锁屏来电页和生命周期,后台通话、进程被杀后唤醒与各品牌省电策略仍需真机验证。完整接口见CallHandle。
独立频道
本页的呼叫、振铃和接听属于原通话。无需 IM 群的会议 / 语音房使用独立 RTC 频道,不自动使用来电 UI 或通知;媒体占用与原通话共享,计费口径分别定义。
