Ensure Mediaplayer Oncompletionlistener Is Called And The Thread Is Not Dead
I have a recurrent alarm that triggers a BroadcastReceiver that starts an IntentService that plays a sound using MediaPlayer. However, my OnCompletionListener (used for realeasing
Solution 1:
For Controll Media player that are play via local service, it is better to send Media player reference to other class Like CarefulMediaPlayer(mp, this);. You handle all media player properties in this class. I think it help you.
Thanks
Solution 2:
I struggled for sometime with this issue and finally I got it to work properly using the below class. The idea is to use a thread with a Looper that remains alive and handles all the MediaPlayer logic.
I only quit the looper and clean the thread if the service received explicit stop message
publicclassPlayServiceextendsIntentService {
privatestatic PowerManager.WakeLock wakeLock;
privatestaticfinalStringTAG="PlayService";
privatestaticStringLOCK_NAME= TAG;
publicstaticfinalStringEXTRA_FILE="file";
publicstaticfinalStringACTION_PLAY="play";
privatestaticfinalStringACTION_STOP="stop";
publicstaticfinalintMSG_START=1;
publicstaticfinalintMSG_STOP=2;
publicPlayService(String name) {
super(name);
}
publicPlayService() {
super("PlayService");
}
@OverridepublicvoidonCreate() {
super.onCreate();
}
@OverrideprotectedvoidonHandleIntent(Intent intent) {
Messagemsg=newMessage();
if (ACTION_PLAY.equalsIgnoreCase(intent.getAction())) {
StringfileName= intent.getExtras().getString(EXTRA_FILE);
msg.what = MSG_START;
msg.obj = fileName;
} elseif (ACTION_STOP.equalsIgnoreCase(intent.getAction())) {
msg.what = MSG_STOP;
}
try {
PlayMediaThread.getInstance(this).sendMessage(msg);
} catch (InterruptedException e) {
Log.e(TAG, e.getMessage());
}
}
publicstatic PowerManager.WakeLock acquireLock(Context context) {
if (wakeLock == null || !wakeLock.isHeld()) {
PowerManagerpowerManager= (PowerManager) context
.getSystemService(Context.POWER_SERVICE);
wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
LOCK_NAME);
wakeLock.setReferenceCounted(true);
wakeLock.acquire();
}
return wakeLock;
}
publicstaticvoidreleaseLock(Context context) {
if (wakeLock != null && wakeLock.isHeld()) {
wakeLock.release();
}
}
}
classPlayMediaThreadextendsThreadimplementsOnCompletionListener,
OnErrorListener, OnPreparedListener {
privatestaticSemaphoresemaphore=newSemaphore(0);
privatestatic Handler handler;
privatestatic Looper myLooper;
privatestatic Context context;
privatestatic String currentFileName;
privatestatic MediaPlayer player;
privatestatic PlayMediaThread instance;
privatestaticfinalStringTAG="PlayMediaThread";
privatePlayMediaThread(Context context)throws InterruptedException {
super(TAG);
PlayMediaThread.context = context;
start();
// To insure that the looper was initialized correctly before return an// instance
semaphore.acquire();
}
publicstatic PlayMediaThread getInstance(Context context)throws InterruptedException {
if (instance == null) {
instance = newPlayMediaThread(context);
}
PlayMediaThread.context = context;
return instance;
}
publicvoidsendMessage(Message msg) {
handler.sendMessage(msg);
}
publicvoidquitLooper() {
try {
if (myLooper != null) {
myLooper.quit();
Log.i(TAG, "After quit");
}
} catch (Exception ex) {
Log.e(TAG, ex.getMessage());
}
}
@Overridepublicvoidrun() {
Looper.prepare();
myLooper = Looper.myLooper();
handler = newHandler() {
@OverridepublicvoidhandleMessage(Message msg) {
if (msg.what == PlayService.MSG_START) {
startPlayer((String) msg.obj);
} elseif (msg.what == PlayService.MSG_STOP) {
// when stop command is coming from the activity i.e. user// explicitly clicked stop, I quit the looper and// clean the thread
stopPlayer(true);
}
}
};
semaphore.release();
Log.i(TAG, "Before Loop");
Looper.loop();
}
privatevoidstopPlayer(boolean clean) {
if (player != null) {
if (player.isPlaying()) {
player.stop();
}
player.release();
player = null;
}
if (clean) {
PlayService.releaseLock(context);
quitLooper();
instance = null;
}
}
privatevoidstartPlayer(String fileName) {
if (player != null && player.isPlaying() && currentFileName != null
&& currentFileName.equalsIgnoreCase(fileName)) {
return;
}
currentFileName = fileName;
stopPlayer(false);
player = newMediaPlayer();
player.setOnCompletionListener(this);
player.setOnErrorListener(this);
player.setOnPreparedListener(this);
try {
player.setDataSource(context, Uri.parse(currentFileName));
player.prepare();
player.start();
PlayService.acquireLock(context);
} catch (Exception e) {
Log.e(TAG, e.getMessage());
}
}
@OverridepublicbooleanonError(MediaPlayer mp, int arg1, int arg2) {
Log.e(TAG, "onError");
stopPlayer(true);
returnfalse;
}
@OverridepublicvoidonCompletion(MediaPlayer mp) {
Log.d(TAG, "onCompletion");
// Just to quit the looper and clean the thread
stopPlayer(true);
}
@OverridepublicvoidonPrepared(MediaPlayer mp) {
Log.d(TAG, "onPrepared");
}
}
Post a Comment for "Ensure Mediaplayer Oncompletionlistener Is Called And The Thread Is Not Dead"