如何检查麦克风是否被任何后台应用程序使用

5

我已经搜索了几天,但始终没有找到合适的解决方案。

我正在尝试检查后台是否有任何应用程序正在使用麦克风,以便我的应用程序可以使用它,否则我只想显示消息“麦克风正在被另一个应用程序使用”。

我尝试检查后台中所有应用程序及其权限,但这并不能解决我的问题,因为有一个名为wearable.app的包请求权限,但它不影响音频,或者它没有使用它。

我尝试了在此处或Google上能够找到的其他解决方案,但似乎都不是正确的方法。

我只想检查麦克风是否未被使用,以便我的应用程序可以使用它。

如果有任何建议,我将不胜感激。

6个回答

17

我搜索了更多,找到了解决方法,现在我将其添加在这里,以便需要的人更容易找到。

private boolean validateMicAvailability(){
    Boolean available = true;
    AudioRecord recorder =
            new AudioRecord(MediaRecorder.AudioSource.MIC, 44100,
                    AudioFormat.CHANNEL_IN_MONO,
                    AudioFormat.ENCODING_DEFAULT, 44100);
    try{
        if(recorder.getRecordingState() != AudioRecord.RECORDSTATE_STOPPED ){
            available = false;

        }

        recorder.startRecording();
        if(recorder.getRecordingState() != AudioRecord.RECORDSTATE_RECORDING){
            recorder.stop();
            available = false;

        }
        recorder.stop();
    } finally{
        recorder.release();
        recorder = null;
    }

    return available;
}

很好的解决方法,但我想知道是否也可以使用OpenSLES检测到。目前我的OpenSLES音频回调在麦克风不可用的情况下根本没有被触发。 - user2479595

2
你可以采用另一种方式。
在你的应用程序中获取麦克风。
获取已安装应用程序的列表,这些应用程序拥有RECORD权限。
然后检查是否有一个这些应用程序正在前台运行,如果有一个释放麦克风,以便其他应用程序可以使用它(例如当电话呼叫发生时)。
这是一种有点“不太正常”的做法,但我认为这是你要寻找的方法。
干杯!

是的,但这仍然不能解决我的问题。 假设在我之前启动了一个应用程序,该应用程序在后台记录音频。用户启动我的应用程序,除非他们实现了广播接收器来释放麦克风(我认为很少这样做),否则我无法从该应用程序中获取麦克风。因此,当我的应用程序尝试初始化麦克风时,它将被卡住或崩溃,因为它无法使用麦克风,因为其他应用程序已经使用它来记录音频。 - Borce Ivanovski
但是并没有这样的应用程序。如果一个应用程序使用硬件资源,比如麦克风,并且不释放给其他应用程序使用,那么手机甚至无法打电话。所以,除非你想让麦克风24/7开启,否则你只需检查你想要捕获的时间是否有其他应用程序在使用它。如果有,你可以推迟音频捕获的时间,直到它可用为止。 - Konstantinos Michael
但这就是问题所在,我正在尝试在我的应用程序中获取麦克风,但它没有从其他应用程序中释放,因此我的应用程序被卡住或崩溃了。我相信这与系统进程完全不同,它们始终可以从后台运行的任何应用程序中获取资源。因此,除非我漏掉了什么,否则您所说的“在您的应用程序中获取麦克风”是行不通的。我想做的与Shazam相同,当应用程序打开且后台有另一个应用程序正在使用麦克风并且未释放时,它会显示“麦克风正在使用”的消息。我正在尝试做相同的事情。 - Borce Ivanovski
我完成了一个项目,它可以从麦克风捕获的声音中进行一些信号处理。这是我创建的服务。我使用了一个叫做TarsosDSP的库来实现这个功能。如果你足够勇敢,可以深入研究。代码有点乱,但在其他应用程序中没有任何问题。干杯! - Konstantinos Michael
@KonstantinosMichael 只是要纠正一件事:如果麦克风正在被其他应用程序使用,电话可能会发生。此外,有一个 AudioSource.HOTWORD 用于助手应用程序,您可以在某个应用程序中录制麦克风,并且助手应用程序仍然可以使用该音频源监听麦克风(除了通话之外,它使用另一个绕过常规 MIC 的源,这是通常使用的源,因此应用程序必须逐一共享它)。 - Edw590

1

AudioManager.AudioRecordingCallback()

        am.registerAudioRecordingCallback(new AudioManager.AudioRecordingCallback() {
        @Override
        public void onRecordingConfigChanged(List<AudioRecordingConfiguration> configs) {
            super.onRecordingConfigChanged(configs);
            try {
                isMicOn = configs.get(0) != null;
            }catch (Exception e)
            {
                isMicOn = false;
            }
            if (isMicOn) {
                //microphone is on
            } else {
                // microphone is off
            }
            Toast.makeText(context, isMicOn ? "Mic on" : "Mic off", Toast.LENGTH_SHORT).show();

        }
    }, null);

欢迎来到Stack Overflow!虽然您的答案可能解决了这个问题,但如果您能解释一下它是如何解决的以及为什么能解决,那将会更有帮助。同时请注意,如果您提供高质量的答案,未来的访问者也会受益,并可能给您点赞。我鼓励您编辑您的答案并添加解释,说明它是如何解决这个问题的。 - NeNaD

1
这就是如何完成的。
AudioManager am = (AudioManager)context.getSystemService(Context.AUDIO_SERVICE);

if(am.getMode()==AudioManager.MODE_IN_COMMUNICATION){
   //Mic is in use
}

MODE_NORMAL -> You good to go. Mic not in use
MODE_RINGTONE -> Incoming call. The phone is ringing
MODE_IN_CALL -> A phone call is in progress
MODE_IN_COMMUNICATION -> The Mic is being used by another application

1

由于 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()

0

我知道这听起来可能有点繁琐或者是冗长的方式...但是你考虑过记录logcat吗?记录内核和应用程序的日志。重现问题,然后比较两个日志,看看当内核使用麦克风时哪个程序被占用。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接