Android ToneGenerator startTone() очень медленно при первом вызове
Я зову ToneGenerator.startTone()
неоднократно издавать короткие вспышки звука. Но при первом вызове он блокируется на длительный период времени. Так что первый взрыв слишком длинный. Вот пример:
Переменные-члены:
private ToneGenerator mDTMFPlayer
В конструкторе:
mDTMFPlayer = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, TONE_RELATIVE_VOLUME);
В Thread
начато OnClickListener.onClick()
:
long startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 1st: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 2nd: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG,"After 3rd: " + (System.currentTimeMillis() - startTime));
try { Thread.sleep(160); } catch (InterruptedException e) { }
mDTMFPlayer.stopTone();
Вот вывод, со временем выполнения startTone()
в миллисекундах:
11-16 18:07:35.885 16927-17977/com.my.project D/Ring: After 1st: 454
11-16 18:07:36.502 16927-17977/com.my.project D/Ring: After 2nd: 0
11-16 18:07:36.672 16927-17977/com.my.project D/Ring: After 3rd: 1
Первый звонок блокируется почти на полсекунды, что слишком долго для того, что мне нужно. Любые звонки после этого блокируют на некоторое время. Что странно, если я немного подожду и попробую снова, то снова медленно. Кажется, есть период, после которого блокировка возвращается.
Пожалуйста, порекомендуйте.
1 ответ
Я думаю что AudioManager.STREAM_VOICE_CALL
вызывает это. Поведение на моем устройстве похоже на ваше. После того, как я запустил приложение, у него есть длинный init для первого startTone()
вызов. Если я выйду и войду в приложение, это может быть быстро для всех 3 звонков. Но он покажет тот же самый "медленный, быстрый, быстрый" результат, если какой-либо системный звук воспроизводится до запуска приложения.
Так что я полагаю, что это как-то связано с переключением / блокировкой потока, потому что AudioManager.STREAM_NOTIFICATION
это займет всего 4-10 мсек на моем устройстве. Также можете прочитать дополнительную информацию здесь: В чем разница между типами потоков AudioManager на низком уровне?
Рассмотрим этот код:
for (int i = -1; i < 10; i++) {
System.out.println("AudioSystem stream " + i);
mDTMFPlayer = new ToneGenerator(i, TONE_RELATIVE_VOLUME);
long startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG, "After 1st: " + (System.currentTimeMillis() - startTime));
try {Thread.sleep(160);} catch (InterruptedException e) {}
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG, "After 2nd: " + (System.currentTimeMillis() - startTime));
try {Thread.sleep(160);} catch (InterruptedException e) {}
mDTMFPlayer.stopTone();
startTime = System.currentTimeMillis();
mDTMFPlayer.startTone(ToneGenerator.TONE_DTMF_0);
Log.d(TAG, "After 3rd: " + (System.currentTimeMillis() - startTime));
try {Thread.sleep(160);} catch (InterruptedException e) {}
mDTMFPlayer.stopTone();
mDTMFPlayer.release();
}
Выход:
I/System.out: AudioSystem stream -1 STREAM_DEFAULT
D/com.example.MainActivity: After 1st: 8
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 0 STREAM_VOICE_CALL
D/com.example.MainActivity: After 1st: 325
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 1 STREAM_SYSTEM
D/com.example.MainActivity: After 1st: 17
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 3
I/System.out: AudioSystem stream 2 STREAM_RING
D/com.example.MainActivity: After 1st: 28
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 3 STREAM_MUSIC
D/com.example.MainActivity: After 1st: 19
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 4 STREAM_ALARM
D/com.example.MainActivity: After 1st: 28
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 5 STREAM_NOTIFICATION
D/com.example.MainActivity: After 1st: 16
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 6 STREAM_BLUETOOTH_SCO
D/com.example.MainActivity: After 1st: 332
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 7 STREAM_SYSTEM_ENFORCED
D/com.example.MainActivity: After 1st: 324
D/com.example.MainActivity: After 2nd: 1
D/com.example.MainActivity: After 3rd: 1
I/System.out: AudioSystem stream 8 STREAM_DTMF
D/com.example.MainActivity: After 1st: 26
D/com.example.MainActivity: After 2nd: 2
D/com.example.MainActivity: After 3rd: 4
I/System.out: AudioSystem stream 9 STREAM_TTS
D/com.example.MainActivity: After 1st: 12
D/com.example.MainActivity: After 2nd: 4
D/com.example.MainActivity: After 3rd: 2
Кстати, если вы хотите исследовать связанный код на C, вы можете посмотреть на android_media_ToneGenerator.cpp, ToneGenerator.h, ToneGenerator.cpp AudioService.java