我想了解有界服务。在我尝试关注http://developer.android.com/guide/components/bound-services.html的示例程序下面。只要我可以播放,暂停和停止音频,该服务功能,但当我切换到另一个应用程序时,我得到以下服务未注册错误。
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)
由于编码似乎紧跟文档示例,我不知道哪里出错了。我使用minSdk级别8运行此应用程序。错误发生在MainActivity.onStop的
行 mService.unbindService(mConnection);
任何解决此问题的建议都会很棒。
由于
马丁
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;
}
};
}
和
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
}
}
答案 0 :(得分:59)
有类似的问题,但接受的答案对我来说不是解决方案。幸运的是,其中一条评论给了我答案:
取消绑定服务时,不应该引发onServiceDisconnected ,所以不要依赖它。如果您的服务和ServiceConnection之间的连接被删除,它应该通知您。
感谢@Waqas我发现错误:我只在boolean binded
和onServiceConnected()
内更新了onServiceDisconnected()
标记。现在我每次拨打unbindService()
时都添加了“binded = false”,问题就消失了。就是这样,不要依赖 onServiceDisconnected
答案 1 :(得分:19)
啊,其中一天
mService.unbindService(mConnection);
显然是无稽之谈,在错误的上下文中调用unbind。它应该是
unbindService(mConnection);
发布的编码中的其他错误是缺少
@Override
public boolean onUnbind(Intent intent) {
// All clients have unbound with unbindService()
releaseMediaPlayer();
return false;
}
答案 2 :(得分:7)
作为旁注,由于其他答案都没有帮助,我发现我的错误是使用不同的Context
进行绑定和取消绑定。我的绑定来自Application上下文,但我的unbind来自Activity上下文。
要解决此错误,我确保对bindService()
和unbindService()
使用相同的上下文。
答案 3 :(得分:2)
您可能需要确保mService不为null。以下行给了我“服务未注册”错误:
if (mContext != null) mContext.unbindService(mServiceConn);
这非常令人困惑,因为mContext和mServiceConn都不是null。
这解决了它:
if (mContext != null && mService != null) mContext.unbindService(mServiceConn);
答案 4 :(得分:0)
当我杀死该应用时,我的MediaPlayer
会停止,但只需5分钟或更短的时间,它就会自动重新启动。
要解决此问题,除了@ dorjeduck的答案之外,我还必须在致电mediaPlayer.stop()
之前致电mediaPlayer.release()
。