【问题标题】:Android ToneGenerator startTone() very slow on the first callAndroid ToneGenerator startTone() 在第一次调用时非常慢
【发布时间】:2017-11-16 23:20:43
【问题描述】:

我反复拨打ToneGenerator.startTone() 以发出短促的声音。但是在第一次调用时,它会阻塞很长时间。所以第一次爆发太长了。这是一个例子:

成员变量:

private ToneGenerator mDTMFPlayer

在构造函数中:

mDTMFPlayer = new ToneGenerator(AudioManager.STREAM_VOICE_CALL, TONE_RELATIVE_VOLUME);

OnClickListener.onClick() 发起的Thread 中:

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

第一个电话阻塞了将近半秒,这对于我的需要来说太长了。之后的任何调用都会使阻塞消失一段时间。奇怪的是,如果我稍等片刻再试一次,它又变慢了。似乎有一段时间后阻塞又回来了。

请指教。

【问题讨论】:

  • “一点”有多长? IOW,这是每个进程的问题吗?“一点”是在您的进程终止并通过用户操作重新创建之后?
  • 不,过程继续,我等待不到一秒钟,然后我再次单击调用 onClick() 的按钮并启动一个单独的线程(我不想在 GUI 上阻塞thread) 并再次调用 startTone()。
  • 好吧,startTone() 只是调用了一个native 方法(请参阅the source),所以我不确定您能做些什么。
  • 如果不是原生的,我可能已经找到原因了。 :)
  • 点。抱歉,如果我的评论另有暗示 - 无论如何,如果您没有得到答案,我的评论是为了让下一个人遇到这个问题。

标签: java android performance tone-generator


【解决方案1】:

我认为是 AudioManager.STREAM_VOICE_CALL 造成的。我设计的行为与您的相似。在我运行应用程序后,第一个 startTone() 调用的初始化时间很长。如果我退出并进入应用程序,所有 3 个呼叫都可以很快。但是如果在应用启动之前播放一些系统声音,它会显示相同的“慢,快,快”结果。

所以我想它与流切换/阻塞有关,因为使用AudioManager.STREAM_NOTIFICATION 在我的设备上只需要 4-10 毫秒。也可以在这里阅读更多信息:What is the difference between AudioManager's stream types at low level?

考虑这段代码:

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.cppToneGenerator.hToneGenerator.cppAudioService.java

【讨论】:

  • 最后我使用了实际上为此而设计的 STREAM_DTMF,而且完全没有延迟。完美的解决方案。感谢您的回答。肯定会给你赏金。
  • startTone 的实际持续时间应该是多长? 50 毫秒? 150 毫秒?默认/标准是什么?
猜你喜欢
  • 2013-07-08
  • 2017-04-23
  • 2021-02-01
  • 2014-02-15
  • 1970-01-01
  • 2023-03-13
  • 2017-01-24
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多