【发布时间】:2014-08-19 04:27:03
【问题描述】:
我需要在我的 Android 应用中异步播放声音。
这是一个短哔 mp3(1 秒长),但我仍然需要它来完全不阻塞当前线程...毫秒很重要,线程正忙于寻找新的蓝牙数据。
需要播放声音的线程是 Intent Service。
我在主线程中函数调用的开头附近有以下代码...这是为了准备 MP3,以便稍后播放。我希望我可以像这样初始化它,并在需要时调用某种“PlaySound”方法。
我的理解是,通过使用 OnPreparedListener,MediaPlayer 将为我处理在不同线程中播放声音的所有细节。
MediaPlayer objMediaPlayer = MediaPlayer.create(getApplicationContext(),R.raw.beeplow);
objMediaPlayer.setOnPreparedListener(new MediaPlayer.OnPreparedListener() {
@Override
public void onPrepared(MediaPlayer mp) {
mp.start();
}
});
以上似乎工作,没有崩溃。
然后,稍后我想播放声音:
//play sound...
objMediaPlayer.prepareAsync();
这确实会播放声音......但是,史诗失败,线程崩溃。
我做错了什么?
如果有帮助的话,这里是 LogCat 信息:
08-19 14:17:51.790 15995-16037/com.example.owner.soundtest V/MediaPlayer﹕ setVideoSurfaceTexture
08-19 14:17:51.790 15995-16037/com.example.owner.soundtest V/MediaPlayer﹕ prepareAsync
08-19 14:17:51.790 15995-16037/com.example.owner.soundtest E/MediaPlayer﹕ prepareAsync called in state 8
08-19 14:17:51.800 15995-16037/com.example.owner.soundtest I/MediaPlayer﹕ Info (973,0)
08-19 14:17:51.800 15995-16037/com.example.owner.soundtest I/MediaPlayer﹕ Don't send intent. msg.arg1 = 0, msg.arg2 = 0
08-19 14:17:51.800 15995-16037/com.example.owner.soundtest V/MediaPlayer-JNI﹕ start
08-19 14:17:51.800 15995-16037/com.example.owner.soundtest V/MediaPlayer﹕ start
08-19 14:17:52.260 15995-16008/com.example.owner.soundtest V/MediaPlayer﹕ message received msg=2, ext1=0, ext2=0
08-19 14:17:52.260 15995-16008/com.example.owner.soundtest V/MediaPlayer﹕ playback complete
08-19 14:17:52.260 15995-16008/com.example.owner.soundtest V/MediaPlayer﹕ callback application
08-19 14:17:52.270 15995-16008/com.example.owner.soundtest W/MessageQueue﹕ Handler (android.media.MediaPlayer$EventHandler) {42fb2890} sending message to a Handler on a dead thread
java.lang.RuntimeException: Handler (android.media.MediaPlayer$EventHandler) {42fb2890} sending message to a Handler on a dead thread
at android.os.MessageQueue.enqueueMessage(MessageQueue.java:311)
at android.os.Handler.enqueueMessage(Handler.java:623)
at android.os.Handler.sendMessageAtTime(Handler.java:592)
at android.os.Handler.sendMessageDelayed(Handler.java:563)
at android.os.Handler.sendMessage(Handler.java:500)
at android.media.MediaPlayer.postEventFromNative(MediaPlayer.java:2776)
at dalvik.system.NativeStart.run(Native Method)
08-19 14:17:52.270 15995-16008/com.example.owner.soundtest V/MediaPlayer﹕ back from callback
更多信息
这是否与我正在使用的“getApplicationContext()”有关...这是创建对象的正确方法吗?我对 Android 还是很陌生,尽管阅读和研究了很多小时,但所有这些 Context 和 Intent 的东西并没有深入了解。
以上所有代码都是在 Intent Service 的线程中调用的……所以它已经完全与 UI 断开了。
黑客修复
通过在我的线程开始处执行此操作:
MediaPlayer objMediaPlayer = MediaPlayer.create(getBaseContext(),R.raw.beeplow);
然后每次我想播放短哔声时,我都会这样做:
if(objMediaPlayer.isPlaying()){
objMediaPlayer.stop();
objMediaPlayer.release();
objMediaPlayer = MediaPlayer.create(getBaseContext(),R.raw.beeplow);
}
objMediaPlayer.start();
似乎有效。天哪,代码太丑了,形式也很糟糕,但是,我只想播放 $** 声音,而不需要花费数小时和数百行代码!疯狂。
正确修复???
以下似乎有效。希望这是正确的方法......当我看到其他解决方案时,它们似乎是隐藏在服务等中的 50 多行代码等等。我喜欢下面的这个......如果这是正确的触发线程的方式我会在任何地方都这样做!
new Thread(new Runnable() {
@Override
public void run() {
MediaPlayer objMediaPlayer = MediaPlayer.create(getBaseContext(),R.raw.beeplow);
objMediaPlayer.start();
}
}, "PlayBeepLow").start();
【问题讨论】:
标签: android multithreading audio