31

我正在尝试了解有界服务。在我尝试遵循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

}

}
4

5 回答 5

69

有类似的问题,但接受的答案不是我的解决方案。幸运的是,其中一条评论给了我答案:

取消绑定服务时不应引发onServiceDisconnected,因此不要依赖它。如果您的 Service 和 ServiceConnection 之间的连接断开,它应该会通知您。

感谢@Waqas,我发现了错误:我只在and内部更新了boolean binded标志。现在我每次打电话时都添加了“binded=false” ,问题就消失了。就是这样,不要依赖onServiceDisconnectedonServiceConnected()onServiceDisconnected()unbindService()

于 2013-05-23T11:52:15.647 回答
20

啊,这些日子之一

mService.unbindService(mConnection);

显然是胡说八道,在错误的上下文中调用 unbind。它应该是

unbindService(mConnection); 

发布的编码中的其他错误是缺少

@Override
public boolean onUnbind(Intent intent) {
    // All clients have unbound with unbindService()

    releaseMediaPlayer();

    return false;
}
于 2012-09-05T13:02:35.033 回答
11

作为旁注,由于其他答案都没有帮助,我发现我的错误是使用不同Context的绑定和取消绑定。我的绑定来自应用程序上下文,但我的解除绑定来自活动上下文。

为了修复该错误,我确保对bindService()and使用相同的上下文unbindService()

于 2015-07-04T13:41:23.100 回答
3

您可能需要确保 mService 不为空。以下行给了我“服务未注册”错误:

if (mContext != null) mContext.unbindService(mServiceConn);

这非常令人困惑,因为 mContext 和 mServiceConn 都不为空。

这修复了它:

if (mContext != null && mService != null) mContext.unbindService(mServiceConn);

于 2014-06-30T22:30:08.733 回答
0

当我杀死该应用程序时,我MediaPlayer会停止,但 5 分钟或更短的时间它会自行重新启动。

为了解决这个问题,除了@dorjeduck 的回答之外,我还必须在 callmediaPlayer.stop()之前先打电话mediaPlayer.release()

于 2014-11-14T19:02:03.533 回答