I am trying to understand bounded services. Below my sample program in which I try to follow http://developer.android.com/guide/components/bound-services.html . The service functions as far as I can play, pause, and stop the audio yet when I switch to another app I get the following Service not registered error.
java.lang.RuntimeException: Unable to stop activity {com.example.dd_services_audio_01/com.example.dd_services_audio_01.MainActivity}: java.lang.IllegalArgumentException: Service not registered: com.example.dd_services_audio_01.MainActivity$1@2afca5d8
09-05 14:04:32.625: E/AndroidRuntime(5810): at android.app.ActivityThread.performStopActivityInner(ActivityThread.java:2451)
09-05 14:04:32.625: E/AndroidRuntime(5810): at android.app.ActivityThread.handleStopActivity(ActivityThread.java:2496)
As the coding seems to follow the documentation example closely I have no clue where things go wrong. I run this app with minSdk level 8. The error happens in MainActivity.onStop at the line
mService.unbindService(mConnection);
Any suggestions to solve this would be great.
Thanks
martin
package com.example.dd_services_audio_01;
import android.app.Activity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Environment;
import android.os.IBinder;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import com.example.dd_services_audio_01.AudioPlayerService.AudioPlayerBinder;
public class MainActivity extends Activity {
private final String TAG = "MainActivity";
AudioPlayerService mService;
boolean mBound = false;
Button mPlay, mPause, mStop;
String audioFile = Environment.getExternalStorageDirectory()
+ "/justdzongsar/DJKR_AboutToGetIt.mp3";
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.d(TAG,"onCreate");
setContentView(R.layout.activity_main);
mPlay = (Button) findViewById(R.id.buttonPlay);
mPause = (Button) findViewById(R.id.buttonPause);
mStop = (Button) findViewById(R.id.buttonStop);
mPlay.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mService.play(audioFile);
}
});
mPause.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mService.pause();
}
});
mStop.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
mService.stop();
}
});
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.activity_main, menu);
return true;
}
@Override
protected void onStart() {
super.onStart();
// Bind to LocalService
Intent intent = new Intent(this, AudioPlayerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
if (mBound) {
mService.unbindService(mConnection);
mBound=false;
}
}
/** Defines callbacks for service binding, passed to bindService() */
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className, IBinder service) {
// We've bound to LocalService, cast the IBinder and get
// LocalService instance
AudioPlayerBinder binder = (AudioPlayerBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mService = null;
mBound = false;
}
};
}
and
package com.example.dd_services_audio_01;
import java.io.IOException;
import android.app.Service;
import android.content.Intent;
import android.media.MediaPlayer;
import android.media.MediaPlayer.OnCompletionListener;
import android.media.MediaPlayer.OnPreparedListener;
import android.os.Binder;
import android.os.IBinder;
import android.util.Log;
public class AudioPlayerService extends Service implements OnPreparedListener,
OnCompletionListener {
private final String TAG = "AudioPlayerService";
private final IBinder mBinder = new AudioPlayerBinder();
private MediaPlayer mMediaPlayer;
private String currentDataSource;
public class AudioPlayerBinder extends Binder {
public AudioPlayerService getService() {
Log.v(TAG, "AudioPlayerBinder: getService() called");
return AudioPlayerService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
// TODO Auto-generated method stub
return mBinder;
}
@Override
public boolean onUnbind(Intent intent) {
// All clients have unbound with unbindService()
return false;
}
@Override
public void onStart(Intent intent, int startId) {
Log.i(TAG,
"AudioPlayerService: onStart() called, instance="
+ this.hashCode());
}
@Override
public void onDestroy() {
Log.i(TAG, "AudioPlayerService: onDestroy() called");
releaseMediaPlayer();
}
// -----
public void play(String audioFile) {
Log.d(TAG, "audio play called with file " + audioFile);
if (mMediaPlayer != null && audioFile.compareTo(currentDataSource) == 0) {
if (mMediaPlayer.isPlaying() == true) {
return;
}
mMediaPlayer.start();
return;
}
releaseMediaPlayer();
try {
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setDataSource(audioFile);
mMediaPlayer.setOnPreparedListener(this);
mMediaPlayer.setOnCompletionListener(this);
currentDataSource = audioFile;
mMediaPlayer.prepareAsync();
} catch (IOException ioe) {
Log.e(TAG, "error trying to play " + audioFile, ioe);
}
}
public void pause() {
Log.d(TAG, "audio pause");
if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
mMediaPlayer.pause();
}
}
public void seek(int timeInMillis) {
if (mMediaPlayer != null) {
mMediaPlayer.seekTo(timeInMillis);
}
}
public int elapsed() {
if (mMediaPlayer == null) {
return 0;
}
return mMediaPlayer.getCurrentPosition();
}
public void stop() {
Log.d(TAG, "audio stop");
releaseMediaPlayer();
}
// --
private void releaseMediaPlayer() {
if (mMediaPlayer == null) {
return;
}
if (mMediaPlayer.isPlaying()) {
mMediaPlayer.stop();
}
mMediaPlayer.release();
mMediaPlayer = null;
}
@Override
public void onCompletion(MediaPlayer arg0) {
// TODO Auto-generated method stub
releaseMediaPlayer();
}
@Override
public void onPrepared(MediaPlayer mp) {
if (mp != null) {
mp.start();
}
// TODO Auto-generated method stub
}
}
As a sidenote, since none of the other answers helped, I found that my error was using a different
Context
for bind and unbind. My bind was from the Application context, but my unbind was from the Activity context.To fix the error, I made sure to use the same context for
bindService()
andunbindService()
.You may need to ensure that mService is not null. The following line gave me the "Service not Registered" error:
if (mContext != null) mContext.unbindService(mServiceConn);
This was very confusing because both mContext and mServiceConn were not null.
This fixed it:
if (mContext != null && mService != null) mContext.unbindService(mServiceConn);
My
MediaPlayer
would stop when I killed the app, but 5 minutes layer or less it would start back up again all on its own.To fix this, in addition to @dorjeduck's answer, I had to also call
mediaPlayer.stop()
before callingmediaPlayer.release()
.Ah, one of these days
is obviously nonsense, calling unbind in the wrong context. It should be
Additional mistake in the posted coding is the missing of
Had a similar problem, but the accepted answer was not the solution for me. Luckily one of the comments gave me the answer:
Thanks to @Waqas I found the error: I was updating the
boolean binded
flag only insideonServiceConnected()
andonServiceDisconnected()
. Now I've added "binded=false" every time I callunbindService()
and the problem has gone. That's it, don't rely on onServiceDisconnected