Java 通过耳机发送麦克风输入,通过手机扬声器发送音频输出

Java 通过耳机发送麦克风输入,通过手机扬声器发送音频输出,java,android,audio,galaxy,samsung-mobile,Java,Android,Audio,Galaxy,Samsung Mobile,有没有办法通过耳机发送麦克风输入,同时通过智能手机扬声器使用音频输出 我已经观察了几个小时了,我发现在iOS上这显然是不可能的,但安卓呢 我用的是三星Galaxy S4 以下是我的代码的一部分,用于在插入耳机的情况下通过扬声器发送音频输出: AudioManager speakerOutput = (AudioManager) getSystemService(Context.AUDIO_SERVICE); speakerOutput.setMode(AudioManager.MODE_IN_C

有没有办法通过耳机发送麦克风输入,同时通过智能手机扬声器使用音频输出

我已经观察了几个小时了,我发现在iOS上这显然是不可能的,但安卓呢

我用的是三星Galaxy S4

以下是我的代码的一部分,用于在插入耳机的情况下通过扬声器发送音频输出:

AudioManager speakerOutput = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
speakerOutput.setMode(AudioManager.MODE_IN_CALL);
speakerOutput.setSpeakerphoneOn(true);
但当我试图通过耳机的麦克风控制我的应用程序时,什么都没有。所以我尝试了智能手机的一个,它显然是工作的

与其他AudioManager.MODEs不同,它仅路由音频输出,将麦克风输入保留到耳机。那么,我现在可以做什么而不必构建新内核、修改驱动程序、HAL等等


谢谢,C.

如果您使用AudioManager.STREAM\u RING,音频应该同时传送到扬声器和有线耳机,就像在来电时播放铃声一样。取消通话时的设置模式和设置扬声器。

如果您不在安卓系统上更改HAL或驱动程序,则无法从耳机麦克风循环到扬声器。如果你能改变硬件,这是可能的。

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

解决方案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是否来自Android 9。因此,该解决方案仅受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也支持这种解决方案


谢谢

不工作:需要添加设置扬声器才能听到声音,它会将麦克风重新连接到手机。谢谢