通过耳机输入MIC输入,通过手机扬声器输出AUDIO输出

时间:2013-11-21 16:41:08

标签: java android audio galaxy samsung-mobile

有没有办法通过耳机路由麦克风输入并通过智能手机的扬声器同时使用 音频输出?

我现在一直在看着几个小时,我看到它在iOS上显然是不可能的,但Android的情况呢......

我正在使用三星Galaxy S4。

以下是我的代码的一部分,即使插入了耳机,也可以通过扬声器传送音频输出:

AudioManager speakerOutput = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
speakerOutput.setMode(AudioManager.MODE_IN_CALL);
speakerOutput.setSpeakerphoneOn(true);

但是当我试图用耳机的麦克风控制我的应用程序时,什么都没有。所以我尝试使用智能手机,这显然很有效。

似乎没有其他AudioManager.MODE仅路由音频输出并将麦克风输入留给耳机。那么我现在可以做什么而无需构建新内核,修改驱动程序,HAL,等等?

谢谢,C。

3 个答案:

答案 0 :(得分:0)

如果您使用AudioManager.STREAM_RING,则应将音频路由到扬声器和有线耳机,就像为来电播放铃声一样(删除setMode和{{1} }来电)。

答案 1 :(得分:0)

如果您未在Android上更改HAL或驱动程序,则无法从耳机麦克风环回到扬声器。如果你可以改变硬件,那么可能会有用。

答案 2 :(得分:0)

是的,有可能。我几天前成功做到了。有两种解决方案:

解决方案1:

假设您的心情正常且耳机已连接。我们只需要调用 setPreferredDevice 函数来设置您的首选音频输入/输出设备。我们的输入源已经来自耳机。因此,我们只需要将音频输出源路由到电话扬声器。这是我的Media Player示例代码:

@RequiresApi(Build.VERSION_CODES.P)
private fun playAudioFromPhoneSpeaker(context: Context, audioResId: Int) {
    val mMediaPlayer: MediaPlayer = MediaPlayer.create(context, audioResId)
    val mCurrentDevice: AudioDeviceInfo? = mMediaPlayer.preferredDevice
    val mDeviceSpeaker: AudioDeviceInfo? = getDeviceOutputSpeaker(context)
    mDeviceSpeaker?.let { speaker ->
        if (mCurrentDevice != speaker) {
            val result: Boolean? = mMediaPlayer.setPreferredDevice(mDeviceSpeaker)
            Log.i("PreferredDevice", "is set as speaker: $result")
        }
    }
    mMediaPlayer.start()
    mMediaPlayer.setOnCompletionListener { mediaPlayer ->
        mediaPlayer.release()
    }
}

@RequiresApi(Build.VERSION_CODES.M)
private fun getDeviceOutputSpeaker(context: Context): AudioDeviceInfo? {
    val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
    val mAudioDeviceOutputList = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)
    mAudioDeviceOutputList?.filterNotNull()?.forEach { speaker ->
        if (speaker.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER) {
            return speaker
        }
    }
    return null
}

此解决方案的积极之处在于,我们无需考虑输入源。我们仅更改音频输出源,并且对输入源没有任何影响。

问题是MediaPlayer的setPreferredDevice来自Android9。因此,仅Android 9支持此解决方案。

解决方案2:

在第二个解决方案中,我们通过音频管理器打开设备扬声器。因此,在打开设备扬声器后,音频输入和输出源将进入设备内部扬声器和设备麦克风。现在我们必须将麦克风路由到耳机。示例代码:

private val mAudioRecord: AudioRecord? = null
private fun RecordAudioFromHeadphone(context: Context) {
    //Step 1: Turn on Speaker
    val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
    audioManager.isSpeakerphoneOn = true

    //Step 2: Init AudioRecorder TODO for you

    //Step 3: Route mic to headset
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        setPreferredInputMic(getWiredHeadPhoneMic(this))
    }
}

@RequiresApi(Build.VERSION_CODES.M)
private fun setPreferredInputMic(mAudioDeviceInfo: AudioDeviceInfo?) {
    val result: Boolean? = mAudioRecord?.setPreferredDevice(mAudioDeviceInfo)
}

@RequiresApi(Build.VERSION_CODES.M)
private fun getWiredHeadPhoneMic(context: Context): AudioDeviceInfo? {
    val audioManager = context.getSystemService(Context.AUDIO_SERVICE) as AudioManager
    val mAudioDeviceOutputList = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)
    mAudioDeviceOutputList?.filterNotNull()?.forEach { device ->
        if (device.type == AudioDeviceInfo.TYPE_WIRED_HEADSET) {
            return device
        }
    }
    return null
}

Android 6支持该解决方案的正面评价。负面影响是它有点复杂,您必须维护语音输入源。

AudioRecorder,MediaRecorder,AudioTrack也支持这种解决方案。

谢谢