Android 13通话时开启扬声器的Kotlin代码失效,求修复方案
Android 13 通话中开启扬声器的适配修改方案
你的代码在Android 13中失效主要是因为系统对音频权限、通话状态监听方式以及音频通道时机的限制变严格了,以下是具体修改步骤和代码:
1. 权限适配
首先在AndroidManifest.xml中声明必要权限:
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" /> <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <!-- 若应用需在后台操作,需添加前台服务权限 --> <uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE" />
其中READ_PHONE_STATE是危险权限,需要在代码中动态申请,确保用户授权后再执行后续逻辑。
2. 替换通话状态监听方式
Android 12(API 31)起弃用了旧的TelephonyManager.listen()方法,Android 13需使用registerPhoneStateListener来监听通话状态:
val telephonyManager = applicationContext.getSystemService(Context.TELEPHONY_SERVICE) as TelephonyManager val phoneStateListener = object : PhoneStateListener(Looper.getMainLooper()) { override fun onCallStateChanged(state: Int, phoneNumber: String?) { super.onCallStateChanged(state, phoneNumber) when (state) { TelephonyManager.CALL_STATE_OFFHOOK -> { Timber.d("onPhoneState: CALL_STATE_OFFHOOK") // 延迟1秒执行,确保通话音频通道完全建立 Handler(Looper.getMainLooper()).postDelayed({ turnOnSpeaker() }, 1000) } } } } // 注册监听 telephonyManager.registerPhoneStateListener( applicationContext, PhoneStateListener.LISTEN_CALL_STATE, phoneStateListener )
3. 修正扬声器开启逻辑
Android 13要求修改音频状态前需先获取音频焦点,同时要避免直接在Activity未前台时调用相关方法,改用ApplicationContext获取服务:
private fun turnOnSpeaker() { val audioManager = applicationContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager // 构建音频焦点请求 val audioFocusRequest = AudioFocusRequest.Builder(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT) .setAudioAttributes( AudioAttributes.Builder() .setUsage(AudioAttributes.USAGE_VOICE_COMMUNICATION) .setContentType(AudioAttributes.CONTENT_TYPE_SPEECH) .build() ) .build() // 请求音频焦点 val focusResult = audioManager.requestAudioFocus(audioFocusRequest) if (focusResult == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) { try { // 设置音频模式为通话模式 audioManager.mode = AudioManager.MODE_IN_CALL // 开启扬声器 audioManager.isSpeakerphoneOn = true } catch (e: SecurityException) { Timber.e(e, "开启扬声器失败:权限不足") } } else { Timber.d("获取音频焦点失败,无法开启扬声器") } }
关键注意点
- 时机问题:
CALL_STATE_OFFHOOK触发时通话音频通道可能尚未完全初始化,延迟执行可避免设置失效 - 前台要求:Android 13限制后台应用修改音频设置,若需在后台操作,需将应用转为前台服务
- 权限检查:每次执行扬声器开启逻辑前,最好再次检查
MODIFY_AUDIO_SETTINGS权限是否已授权
内容的提问来源于stack exchange,提问作者Eli
相关产品推荐
相关产品推荐

