权限与业务逻辑
大约 3 分钟
Andorid 集成文档
权限与业务逻辑
权限声明
环信 CallKit 所需权限已在 Manifest.xml
文件中声明。若不需要某项功能,可根据实际情况修改。
<!-- 联网权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<!-- 悬浮窗权限 -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
<!-- android 13+ 通知相关权限 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.VIBRATE" />
<!-- 锁屏显示所需权限 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<!-- 前台服务权限,用于后台保持通话状态 -->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_CAMERA"
android:minSdkVersion="34" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE"
android:minSdkVersion="34" />
<uses-permission
android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK"
android:minSdkVersion="34" />
<!-- 标准 telecom ConnectionService 所需权限 -->
<uses-permission android:name="android.permission.MANAGE_OWN_CALLS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.USE_SIP" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL"/>
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS"/>
<!-- RTC 所需权限 -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH" />
<!-- 对于 Android 12.0 及以上且集成 v4.1.0 以下 SDK 的设备,还需要添加以下权限 -->
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<!-- 对于 Android 12.0 及以上设备,还需要添加以下权限 -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" />
<!-- 声明硬件特性为非必需,以支持没有电话功能的设备 -->
<uses-feature android:name="android.hardware.telephony" android:required="false" />
<uses-feature android:name="android.hardware.microphone" android:required="false" />
动态权限
动态权限也称为运行时权限。一些权限需要动态申请,申请逻辑位于 BaseCallActivity#initPermissions
函数。
例如,以下为动态权限:
- 录音:
RECORD_AUDIO
- 摄像头:
CAMERA
- Android 12+:
READ_PHONE_STATE
、BLUETOOTH_CONNECT
- Android 13+:
POST_NOTIFICATIONS
- 申请权限被拒:逻辑统一在
BaseCallActivity.onRequestPermissionsResult
中。 如果任一必要权限被拒,结束当前通话流程:- 主叫:发送取消信令
SignalingManager.cancelCall(...)
,取消通话。 - 被叫:发送拒绝信令
SignalingManager.refuseCall()
,拒绝接听。
- 主叫:发送取消信令
录音权限

摄像头权限

发送通知

拨打电话和通话管理

获取设备信息

获取附近设备信息

悬浮窗
当用户点击悬浮窗按钮或者在通话状态时 app 回到后台,会触发悬浮窗权限检查:
- 悬浮窗权限:
SYSTEM_ALERT_WINDOW
- 检查悬浮窗权限:
PermissionHelper.hasFloatWindowPermission(...)
- 引导开启悬浮窗权限:
requestFloatWindowPermission(...)
- 开启悬浮窗权限被拒:CallKit 在
SingleCallViewModel.handleRequestFloatWindowPermissionCancel()
会按当前CallState
执行取消/拒绝/挂断的兜底。 - 悬浮窗显示时,为保证通话正常进行(即摄像头、麦克风正常采集数据流),需要开启媒体类型前台服务。 前台服务权限为
FOREGROUND_SERVICE
,媒体类型为camera
microphone
和mediaPlayback
。
申请悬浮窗权限的界面展示如下:
需要悬浮窗权限

设置应用展示在其他应用上层

锁屏唤醒
锁屏唤醒权限:USE_FULL_SCREEN_INTENT
、WAKE_LOCK
、DISABLE_KEYGUARD
。
若 App 在后台运行,收到来电时,app 会被唤醒,显示来电通知。
最佳实践
为了确保流畅的用户通话体验,需在启动 app 后就提前申请以下权限:
1. 动态权限申请
ActivityCompat.requestPermissions(this,getRequiredPermissions(),Constant.PERMISSION_REQ_ID)
// 获取体验实时音视频互动所需的录音、摄像头等权限
private fun getRequiredPermissions(): Array<String> {
var basePermission = arrayOf(
Manifest.permission.RECORD_AUDIO, // 录音权限
Manifest.permission.CAMERA, // 摄像头权限
)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
basePermission += arrayOf(
Manifest.permission.READ_PHONE_STATE, // 读取电话状态权限
Manifest.permission.BLUETOOTH_CONNECT, // 蓝牙连接权限
)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU){
basePermission += arrayOf(
Manifest.permission.POST_NOTIFICATIONS //通知权限
)
}
return basePermission
}
2. 悬浮窗权限申请
PermissionHelper.showPermissionExplanationDialog(
this,
onConfirm = {
PermissionHelper.requestFloatWindowPermission(
this,
Constant.FLOAT_WINDOW_PERMISSION_REQUEST_CODE
)
},
onCancel = {
}
)