Одно устройство не воспроизводит аудиовызов через наушник после включения микрофона - PullRequest
0 голосов
/ 09 апреля 2020

Я пишу мессенджер (с функцией VoIP), в котором пользователь может отдельно включать / выключать динамик и микрофон. Я только добавил функцию, с помощью которой пользователь может поднести телефон к уху, а затем экран выключается, и он может слышать разговор через динамик. Здесь проблема. На одном устройстве (с кастомной прошивкой) при одновременном включении динамика и подносе телефона к уху я ничего не слышу.

Части моего кода:

Включение динамика:

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);
.....................................

Инициализация микрофона:

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);
..........................................

Опытным путем установлено, что если остановить RecordThread перед «audioManager.setSpeakerphoneOn (! NearProximity)» и перезапустить его после него, то динамик заработает. Но переподключение к серверу для меня нежелательно. Поэтому я попытался также сделать "Recorder.stop (); Recorder.release ()" до "audioManager.setSpeakerphoneOn (! NearProximity)" и восстановить новый AudioRecord после него, но это не помогает.

Любые идеи

1 Ответ

0 голосов
/ 10 апреля 2020

Наконец, это работает.

Эксперименты показывают, что мне действительно не нужно выпускать и восстанавливать AudioRecord.

Все, что мне нужно, это некоторая задержка (~ 1 секунда) между "audioManager" .setSpeakerphoneOn (nearProximity!);» и "Recorder.startRecording ();"

@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);
        }
    }
}

В записи l oop:

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

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

                    recorder.startRecording();
                    nearChanged = false;
                }
...