Is Android MediaPlayer multithreaded?

前端 未结 1 700
无人共我
无人共我 2021-01-28 19:09

Can we create and use Android MediaPlayer from a background thread?

I ask because it\'s strange that all callback events (like OnError, OnPrepared

相关标签:
1条回答
  • 2021-01-28 19:43

    You can create and use MediaPlayer from background thread. But to receive callbacks on the background thread that thread must have Looper implemented. If thread does not have Looper callbacks will be called on the main (UI) thread.

    From Android documentation MediaPlayer:

    Callbacks

    Applications may want to register for informational and error events in order to be informed of some internal state update and possible runtime errors during playback or streaming. Registration for these events is done by properly setting the appropriate listeners (via calls to setOnPreparedListener(OnPreparedListener)setOnPreparedListener, setOnVideoSizeChangedListener(OnVideoSizeChangedListener)setOnVideoSizeChangedListener, setOnSeekCompleteListener(OnSeekCompleteListener)setOnSeekCompleteListener, setOnCompletionListener(OnCompletionListener)setOnCompletionListener, setOnBufferingUpdateListener(OnBufferingUpdateListener)setOnBufferingUpdateListener, setOnInfoListener(OnInfoListener)setOnInfoListener, setOnErrorListener(OnErrorListener)setOnErrorListener, etc).

    In order to receive the respective callback associated with these listeners, applications are required to create MediaPlayer objects on a thread with its own Looper running (main UI thread by default has a Looper running).


    Most basic example to observe difference between creating MediaPlayer on threads with or without Lopper:

            HandlerThread thread = new HandlerThread("mp") {
    //        Thread thread = new Thread() {
    
            @Override
            public void onLooperPrepared() {
    //        public void run() {
                Log.d("XAPP", "BG Thread " + Long.toString(Thread.currentThread().getId()));
                MediaPlayer player = MediaPlayer.create(MainActivity.this, R.raw.sound);
                player.setOnPreparedListener(new MediaPlayer.OnPreparedListener()
                {
                    @Override
                    public void onPrepared(MediaPlayer mp)
                    {
                        Log.d("XAPP", "onPrepared " + Long.toString(Thread.currentThread().getId()));
                        mp.start();
                    }
                });
    
                player.setOnCompletionListener(new MediaPlayer.OnCompletionListener()
                {
                    @Override
                    public void onCompletion(MediaPlayer mp)
                    {
                        Log.d("XAPP", "onCompletion " + Long.toString(Thread.currentThread().getId()));
                    }
                });
    
            }};
    
            thread.start();
    

    HandlerThread has a Looper and running the above code will result in following logcat output . all callbacks are executed on background thread

    01-11 14:33:04.122 5099-5099/xxx D/XAPP: UI Thread 1
    01-11 14:33:04.122 5099-5173/xxx D/XAPP: BG Thread 416
    01-11 14:33:04.152 5099-5173/xxx D/XAPP: onPrepared 416
    01-11 14:33:05.133 5099-5173/xxx D/XAPP: onCompletion 416
    

    Switching to Thread implementation (uncomment Thread() line and run() line, and comment HandlerThread() and onLooperPrepared() lines) that does not have Looper will yield following logcat where callbacks are executed in the context of main thread

    01-11 14:31:45.706 4916-4916/xxx D/XAPP: UI Thread 1
    01-11 14:31:45.706 4916-4994/xxx D/XAPP: BG Thread 413
    01-11 14:31:45.736 4916-4916/xxx D/XAPP: onPrepared 1
    01-11 14:31:46.717 4916-4916/xxx D/XAPP: onCompletion 1
    
    0 讨论(0)
提交回复
热议问题