播放Android Android异步。然后播放然后崩溃线程

时间:2014-08-19 04:27:03

标签: android multithreading audio

我需要在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断开连接。

Hacky Fix

在我的主题开始时这样做:

        MediaPlayer objMediaPlayer = MediaPlayer.create(getBaseContext(),R.raw.beeplow);

然后每次我想发出短促的哔哔声时我会这样做:

                    if(objMediaPlayer.isPlaying()){
                        objMediaPlayer.stop();
                        objMediaPlayer.release();
                        objMediaPlayer = MediaPlayer.create(getBaseContext(),R.raw.beeplow);
                    }
                    objMediaPlayer.start();

似乎工作。上帝糟糕的代码和糟糕的形式,但是,是的,我只想播放$ **声音而不花费数小时和数百行代码! Craxy。

正确修复???

以下似乎有效。希望这是正确的方法...当我看到其他解决方案时,它们似乎是50多行代码埋在服务等等。我喜欢下面这个...如果这是正确的如何开除一个线程我将在任何地方这样做!

                    new Thread(new Runnable() {
                        @Override
                        public void run() {
                            MediaPlayer objMediaPlayer = MediaPlayer.create(getBaseContext(),R.raw.beeplow);
                            objMediaPlayer.start();
                        }
                    }, "PlayBeepLow").start();

1 个答案:

答案 0 :(得分:1)

  

在死线程上向处理程序发送消息

IntentService中执行此操作并不安全,因为它在用完工作时会自行停止。

  

所有上述代码都在Intent Service的一个线程中调用...   所以它已经完全脱离了用户界面。

处理完所有请求后,IntentService-onHandleIntent 会自行停止

我建议在Service中进行,并处理自己的线程

@Override
public int onStartCommand(final Intent intent, int flags, final int startId) 
{
    new Thread(new Runnable() {
        @Override
        public void run() {
            // handle your own media playing here...
        }
    }, "MplayerService").start();

    ...
}

如果您希望用户控制您的媒体播放器

我建议绑定服务here

来自文档的更多信息:

Service 服务是一个应用程序组件,表示应用程序希望在不与用户交互或为其他应用程序提供功能的情况下执行较长时间运行的操作使用。

IntentService IntentService是服务的基类,可根据需要处理异步请求(表示为Intents)。客户端通过startService(Intent)调用发送请求;服务根据需要启动,使用工作线程依次处理每个Intent,并在工作失败时自行停止。

希望有所帮助。