我正在尝试在Android中编写音乐播放器,并尝试使用服务在后台无限循环播放音乐。我需要服务与活动进行交互以进行音量控制等。问题是,如果我使用服务绑定器,那么当活动在后台时,服务可能会随活动终止。如何确保服务可以在没有活动和活动的情况下继续运行,仍然可以调用某些服务的方法?
使用带有活页夹的前台服务是一种解决方案吗?服务不会以这种方式被杀死?
提前致谢!
答案 0 :(得分:2)
Per this process priority blog post,唯一比前台服务更高优先级的是前台活动。这意味着前台服务几乎永远不会被杀死。
根据building an audio app service documentation:
正在播放服务时,它应该在前台运行。这使系统知道服务正在执行有用的功能,如果系统内存不足,则不应该被杀死。前台服务必须显示通知,以便用户知道它并可以选择控制它。 onPlay()回调应该将服务放在前台。
答案 1 :(得分:0)
注意:服务将终生运行,直到您使用stopSelf()或stopService()方法终止服务
使用以下方法检查您的服务是否正在运行。
public static boolean isServiceRunning(String serviceClassName){
final ActivityManager activityManager = (ActivityManager)Application.getContext().getSystemService(Context.ACTIVITY_SERVICE);
final List<RunningServiceInfo> services = activityManager.getRunningServices(Integer.MAX_VALUE);
for (RunningServiceInfo runningServiceInfo : services) {
if (runningServiceInfo.service.getClassName().equals(serviceClassName)){
return true;
}
}
return false;
}
对于音乐播放器应用,您需要创建绑定服务。检查此文档docs
public class MusicPlayerService extends Service {
// Binder given to clients
private final IBinder mBinder = new LocalBinder();
/**
* Class used for the client Binder. Because we know this service always
* runs in the same process as its clients, we don't need to deal with IPC.
*/
public class LocalBinder extends Binder {
MusicPlayerService getService() {
// Return this instance of MusicPlayerService so clients can call public methods
return MusicPlayerService.this;
}
}
@Override
public IBinder onBind(Intent intent) {
return mBinder;
}
/** method for clients */
public void play() {
}
public void pause() {
}
public void stop() {
}
}
在您的活动课程中, 声明mBound布尔变量,
boolean mBound;
添加bindServiceImplementation
@Override
protected void onStart() {
super.onStart();
// Bind to MusicPlayerService
Intent intent = new Intent(this, MusicPlayerService.class);
bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
}
@Override
protected void onStop() {
super.onStop();
// Unbind from the service
if (mBound) {
unbindService(mConnection);
mBound = false;
}
}
create要与MusicPlayerService类进行通信,请初始化ServiceConnection对象
private ServiceConnection mConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName className,
IBinder service) {
// We've bound to MusicPlayerService, cast the IBinder and get MusicPlayerService instance
LocalBinder binder = (LocalBinder) service;
mService = binder.getService();
mBound = true;
}
@Override
public void onServiceDisconnected(ComponentName arg0) {
mBound = false;
}
};
然后您可以调用MusicPlayerService公共方法,如下所示,
public void onButtonClick(View v) {
if (mBound) {
// However, if this call were something that might hang, then this request should
// occur in a separate thread to avoid slowing down the activity performance.
mService.play();
mService.pause();
mService.stop();
}
}