Can we create and use Android MediaPlayer from a background thread?
I ask because it\'s strange that all callback events (like OnError
, OnPrepared
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