由于 Android 版本不同,共享音频输入行为也会有所不同,因此本答案旨在基于 docs 提供完整的解决方案。
Android 10 之前
在 Android 10 之前,输入音频流只能被一个应用程序捕获。如果某个应用程序已经在录制或监听音频,则您的应用程序可以创建 AudioRecord 对象,但是当您调用 AudioRecord.startRecording() 时将返回错误,并且录制将不会开始。
因此,您可以使用此函数来检查麦克风是否被其他应用程序使用,适用于 Android 10 之前的版本。
private fun isAnotherAppUsingMic(): Boolean {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) return false
createRecorder().apply {
try {
startRecording()
if (recordingState != AudioRecord.RECORDSTATE_RECORDING) {
return true
}
stop()
return false
} catch (e: IllegalStateException) {
return true
} finally {
release()
}
}
}
private fun createRecorder(): AudioRecord {
return AudioRecord(
MediaRecorder.AudioSource.MIC,
SAMPLE_RATE_HZ,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT,
2 * AudioRecord.getMinBufferSize(
SAMPLE_RATE_HZ,
AudioFormat.CHANNEL_IN_MONO,
AudioFormat.ENCODING_PCM_16BIT
)
)
}
const val SAMPLE_RATE_HZ = 44100
Android 10及以上版本
Android 10实施了一种优先级方案,可以在应用程序运行时在应用程序之间切换输入音频流。在大多数情况下,如果新的应用程序获取音频输入,则先前捕获的应用程序继续运行,但会接收静音。
因此,在Android 10及更高版本中,如果已经有其他应用程序(如语音或屏幕录制器)正在运行,并且您开始在您的应用程序中使用麦克风,则在大多数情况下,您的应用程序将具有优先权。但是,您需要检查语音/视频通话,因为它具有更高的优先级,麦克风将不可用于您的应用程序(它将接收静音)。您可以使用以下代码检查是否存在活动呼叫:
private fun isVoiceCallActive(): Boolean {
val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
return audioManager.mode in listOf(
AudioManager.MODE_IN_CALL,
AudioManager.MODE_IN_COMMUNICATION
)
}
总之,您可以合并上述两个函数,在您想要使用麦克风之前检查其是否可用。
fun isMicAvailable() = !isAnotherAppUsingMic() && !isVoiceCallActive()