有时,Android 与 ScheduledExecutorService 一起使用的 SoundPool 会停止播放声音

Occasionally, Android SoundPool used with ScheduledExecutorService stops playing sounds

在我的 phone 和模拟器上,这似乎每 15 次就会发生 1 次。 SoundPool 将播放声音约 3 秒,然后停止。当我播放声音时,我反复收到这条消息,我理解这只是意味着不能使用低延迟模式。当声音停止时,不再生成这些警告。

    W/AudioTrack: AUDIO_OUTPUT_FLAG_FAST denied by client

如果我查看整个 phone 的 Android 监视器,我总是在声音停止时得到这个,否则不会。没有抛出异常。

    07-09 22:14:15.630 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7935
    07-09 22:14:15.630 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7928
    07-09 22:14:15.750 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7936
    07-09 22:14:15.750 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7937
    07-09 22:14:15.870 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7938
    07-09 22:14:16.130 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7939
    07-09 22:14:16.130 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7940
    07-09 22:14:16.250 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7941
    07-09 22:14:16.390 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7943
    07-09 22:14:16.390 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7944
    07-09 22:14:17.620 2601-2890/? I/AudioPolicyManager: stopOutput() output 2, stream 7, session 7942
    07-09 22:14:17.620 2601-2890/? I/AudioPolicyManager: getNewOutputDevice() selected device 0
    07-09 22:14:17.620 2601-2890/? I/AudioPolicyManager: setOutputDevice() output 2 device 0x0000 delayMs 40
    07-09 22:14:17.620 2601-2890/? I/AudioPolicyManager: setOutputDevice() prevDevice 0x0002
    07-09 22:14:17.620 2601-2890/? I/AudioPolicyManager: setOutputDevice() setting same device 0x0000 or null device for output 2

这就是我创建 SoundPool 的方式:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
        clips = new SoundPool.Builder()
                .setMaxStreams(22)
                .setAudioAttributes(new AudioAttributes.Builder()
                        .setUsage(AudioAttributes.USAGE_ALARM)
                        .setContentType(AudioAttributes.CONTENT_TYPE_UNKNOWN)
                        .setFlags(AudioAttributes.FLAG_AUDIBILITY_ENFORCED)
                        .build())
                .build();
    } else {
        clips = new SoundPool(22, AudioManager.STREAM_ALARM, 0);
    }

我的其余代码太大 post 但我正在按如下方式加载和播放剪辑:

ScheduledExecutorService trigger = Executors.newScheduledThreadPool(3);
int e1 = clips.load(this, noteFiles.getResourceId(0,0), 1);
int[] noteIDs = {e1};

playNote = new Runnable() {
        public void run() {
        clips.play(noteIDs[0], realTuneVol, realTuneVol, 1, 0, 1);
}
}

clips.setOnLoadCompleteListener(new SoundPool.OnLoadCompleteListener() {
        @Override
        public void onLoadComplete(SoundPool soundPool, int sampleId, int status) {
          if (savedInstanceState != null) {
               trigger.shutdown();
           } else {
               trigger.scheduleAtFixedRate(playNote, 0, 125, TimeUnit.MILLISECONDS);
                    }
                }
            }
        }
    });

我同时播放了很多剪辑,所以我知道这很可能是问题所在,但我没有注意到播放的剪辑数量与此错误之间有多大关联。然而,我所阅读和体验的是,如果我尝试播放太多剪辑,SoundPool 将开始跳过它们,但它不会一起停止。所以我想知道这个问题是否与我尝试播放的剪辑数量无关并且实际上与 ScheduledExecutorService 有关。当声音停止时,Runnable 似乎不再执行,因为我没有收到来自它的新日志消息。非常感谢任何帮助。

事实证明,ScheduledExecutorService 抑制了异常,正如这里提到的。 http://code.nomad-labs.com/2011/12/09/mother-fk-the-scheduledexecutorservice/

因此,通过将整个 Runnable 包装在一个 try catch 块中,我能够发现 ArrayIndexOutOfBoundsException 有时会由于程序的另一部分而发生,从而导致问题。

playNote = new Runnable() {
    public void run() {
    try{
    clips.play(noteIDs[0], realTuneVol, realTuneVol, 1, 0, 1);
    }
    catch (Throwable th){
        Log.v("ErrorInRunnable", th.toString());
    }
    }
}