启用麦克风后,一台设备无法通过耳机播放音频通话

One device doesn't play audio call through earpiece after enabling microphone

我正在编写 Messenger(具有 VoIP 功能),用户可以在其中分别打开 off/on 扬声器和微型 phone。我刚刚添加了一个功能,用户可以将 phone 带到他的耳朵,然后屏幕关闭,他可以通过耳机听到对话。这就是问题所在。在一台设备(带有自定义固件)上,当我同时打开扬声器和微型 phone 并将 phone 放在耳边时,我听不到任何声音。

我的部分代码:

打开扬声器:

private void headsetStart()
{
    if (mPlayMessages == null)
    {
        mHeadsetButton.setBackgroundResource(R.drawable.headset_on);

        audioManager.setMode(audioManager.MODE_IN_COMMUNICATION);
        audioManager.setSpeakerphoneOn(!nearProximity);

        // turn off screen on near proximity sensor
        mWakeLock = mPowerManager.newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, ":headsetStart");
        mWakeLock.acquire();
        mBeOnAirThread = new BeOnAirThread();
        mBeOnAirThread.start();

        if (partnerOnAir && !mIsStarted)
        {
            micStart();
        }
    }
}

private class BeOnAirThread extends Thread {

    // Sample rate must be one supported by Opus.
    static final int SAMPLE_RATE = 16000;

    // Number of samples per frame is not arbitrary,
    // it must match one of the predefined values, specified in the standard.
    static final int FRAME_SIZE = 160;

    // 1 or 2
    static final int NUM_CHANNELS = 1;

    @Override
    public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE);

        int minBufSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
                NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO,
                AudioFormat.ENCODING_PCM_16BIT);

        // init audio track
        AudioTrack track = new AudioTrack(AudioManager.STREAM_VOICE_CALL,
                SAMPLE_RATE,
                NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_OUT_MONO : AudioFormat.CHANNEL_OUT_STEREO,
                AudioFormat.ENCODING_PCM_16BIT,
                minBufSize,
                AudioTrack.MODE_STREAM);
.....................................

正在初始化微phone:

private class RecordThread extends Thread {
    // Sample rate must be one supported by Opus.
    static final int SAMPLE_RATE = 16000;

    // Number of samples per frame is not arbitrary,
    // it must match one of the predefined values, specified in the standard.
    static final int FRAME_SIZE = 160;

    // 1 or 2
    static final int NUM_CHANNELS = 1;

    byte[] textBuf;
    int iav;
    int off;

    @Override
    public void run() {
        Process.setThreadPriority(Process.THREAD_PRIORITY_MORE_FAVORABLE);

        int minBufSize = AudioRecord.getMinBufferSize(SAMPLE_RATE,
                NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO,
                AudioFormat.ENCODING_PCM_16BIT);

        // initialize audio recorder
        AudioRecord recorder = new AudioRecord(MediaRecorder.AudioSource.VOICE_COMMUNICATION,
                SAMPLE_RATE,
                NUM_CHANNELS == 1 ? AudioFormat.CHANNEL_IN_MONO : AudioFormat.CHANNEL_IN_STEREO,
                AudioFormat.ENCODING_PCM_16BIT,
                minBufSize);
..........................................

根据经验确定,如果在 "audioManager.setSpeakerphoneOn(!nearProximity)" 之前停止 RecordThread 并在它之后重新启动它,则耳机可以正常工作。 但是为我重新连接到服务器是不可取的。所以我也尝试在 "audioManager.setSpeakerphoneOn(!nearProximity)" 之前做 "recorder.stop(); recorder.release()" 并在它之后重建新的 AudioRecord,但它没有帮助。

有什么想法吗?

终于可以用了。

实验表明我确实不需要release和reconstruct AudioRecord

我所需要的只是 "audioManager.setSpeakerphoneOn(!nearProximity);" 和 "recorder.startRecording();"

之间的一些延迟(~1 秒)
@Override
public void onSensorChanged(SensorEvent event) {
    if (event.sensor.getType() == Sensor.TYPE_PROXIMITY) {
        boolean oldNear = nearProximity;
        if (event.values[0] >= -SENSOR_SENSITIVITY && event.values[0] <= SENSOR_SENSITIVITY) {
            nearProximity = true;
        } else {
            nearProximity = false;
        }

        if (mBeOnAirThread != null && oldNear != nearProximity)
        {
            if (nearProximity && mIsStarted)
                nearChanged = true;
            else
                audioManager.setSpeakerphoneOn(!nearProximity);
        }
    }
}

在记录循环中:

                if (nearChanged)
                {
                    recorder.stop();
                    audioManager.setSpeakerphoneOn(!nearProximity);

                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                    }

                    recorder.startRecording();
                    nearChanged = false;
                }