Как определить исходящее кольцо звонков в Android с помощью класса Visualizer?

В настоящее время мне нужно зафиксировать момент, когда начинается исходящий звонок. Согласно Abeer Ahmad в "Как определить состояние звонка исходящего вызова в android" , решение чтобы определить изменение частоты испускаемого звука (от 0 до значения, соответствующего кольцу), используя класс Visualizer. Однако во время совершения вызова не регистрируется значение частоты, отличное от 0 (тишина). Это не соответствует тому, что происходит, когда мобильный телефон излучает другой звук, такой как воспроизведение звуковой дорожки, где обнаружены значения частоты. Может ли кто-нибудь помочь мне или дать мне альтернативное решение?

Вот мой код:

mVisualizer = new Visualizer(0);
mVisualizer.setCaptureSize(Visualizer.getCaptureSizeRange()[1]);
Visualizer.OnDataCaptureListener listener = new Visualizer.OnDataCaptureListener(){
                    @Override
                    public void onWaveFormDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) { }
                    @Override
                    public void onFftDataCapture(Visualizer visualizer, byte[] bytes, int samplingRate) {
                        for (int i=0;i<bytes.length;i++) {
                            if (bytes[i] != 0) {
                              Log.i("INFO","FREQUENCY:"+bytes[i]);
                                break;
                            }
                        }
                    }
                };
mVisualizer.setDataCaptureListener(listener, Visualizer.getMaxCaptureRate() / 2, true, true);

Я использую Android Jellybean (API 17).

Ответ 1

Вызов new Visualizer(0); прослушивает Stream 0, смешанный выход.

Проблема заключается в том, что звук вызова не всегда присутствует в смешанном выпуске, как указано на этой ошибке Google, поэтому вам нужно найти правильный Поток себя. Однако я не нашел простой способ сделать это.

Для MediaPlayer использовался непубличный метод snoop, который можно было использовать, но он был удален из последних версий. Длинный выстрел, который вы могли бы попробовать, это создать звуковую дорожку в одном потоке и прослушивать этот идентификатор сеанса:

AudioTrack track = new AudioTrack(AudioManager.STREAM_VOICE_CALL, aSampleRate, 
        AudioFormat.CHANNEL_CONFIGURATION_MONO, AudioFormat.ENCODING_PCM_16BIT, 
        aBuffersize, AudioTrack.MODE_STREAM);

Вы также можете попробовать позвонить audioManager.setStreamSolo(AudioManager.STREAM_VOICE_CALL, true);, прежде чем запускать визуализатор. Теоретически, поскольку STREAM_VOICE_CALL станет единственным сеансом, позволяющим производить аудио, он должен влиять на результаты визуализатора.

Примечание. Если вы посмотрите на generateAudioSessionId в Источники AudioManager, вы увидите, что он использует класс Native AudioSystem, Я бы предложил использовать NDK для доступа к этому классу и найти текущий идентификатор аудио сессии