您的位置:首页 > 其它

Service后台播放音乐

2017-03-09 17:11 369 查看
Service(服务),是没有前台界面的,service并不依赖于UI,因为service只能在后台运行。

Service同样运行在主线程中,所以Service中不能有耗时的操作(这里指的是service不是IntentService),如果有耗时操作,我们可以像Activity那样,重新开个线程进行操作.

Service的启动方式有两种:startService和bindService;

startService

如果使用startService启动服务,Service的生命周期是这样子的:

onCreate—>onStartCommand—->onDestroy;

使用startService启动服务,主要用于程序内部的service.

bindService

如果使用bindService启动服务,service的生命周期是:

onCreate—->onBind—->onUnbind—->onDestroy;

使用bindService启动服务,可以用于程序内部service,也可以允许多个应用绑定一个服务。

当我已经通过startService启动服务后,然后又调用bindService,这时候,onCreate方法不会再次调用,而是直接调用onBind方法。

要实现后台播放音乐,需要继承service,实现service的方法,在service中创建MediaPlayer对象并且创建音乐播放的操作方法,以便在页面中调用服务的方法,操作音乐的播放和停止。

和Activity一样,使用service要在Manifest文件中声明:

<service android:name=".service.LocalService">

</service>


声明的时候也可以为service定义,指明service的action,这样其他应用就可以使用intent访问这个服务。

<service android:name=".service.LocalService">
<intent-filter>
<action android:name="com.xiao.action.MYSERVICE" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>


在Manifest中声明服务后,实现servicve:

public class LocalService extends Service implements MediaPlayer.OnPreparedListener{

//绑定service时返回的bind对象
private IBinder localBinder = new LocalBinder();
//播放器
private MediaPlayer mediaPlayer;
//音乐是否准备好
private boolean isPrepared = false;

@Override
public void onCreate() {
super.onCreate();
Log.i("yxs","create");
//初始化播放器,这些操作建议放在onStartCommand方法中
mediaPlayer = MediaPlayer.create(getApplicationContext(), R.raw.banma);
//设置音乐循环播放
mediaPlayer.setLooping(true);
////监听音乐是否准备好,需要实现onPrepared方法
mediaPlayer.setOnPreparedListener(LocalService.this);
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.i("yxs","onStartCommand");
return START_STICKY;
}

/**
* 播放音乐
*/
public void playerStart(){
//判断是否准备好
if(isPrepared) {
//判断播放器是否为null,和是否正在播放
if (mediaPlayer != null && !mediaPlayer.isPlaying()) {
mediaPlayer.start();
}
}
}

/**
* 音乐暂停
*/
public void playerPause(){
//如果当前正在播放音乐,则暂停
if(mediaPlayer.isPlaying()){
mediaPlayer.pause();
}
}

@Override
public void onPrepared(MediaPlayer mp) {
//如果准备就绪,则isPrepared 赋值为真
isPrepared = true;
Log.i("yxs","是否准备好"+isPrepared);
}

//内部类,返回service实例
public class LocalBinder  extends Binder{
public LocalService getLocalService(){
Log.i("yxs","构造");
return LocalService.this;
}
}

@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.i("yxs","onBind");
//返回Binder对象,以便在页面中通过binder获取service实例,操作音乐播放器
return localBinder;
}

@Override
public boolean onUnbind(Intent intent) {
Log.i("yxs","onUnbind");
return super.onUnbind(intent);
}

@Override
public void onDestroy() {
Log.i("yxs","onDestroy");
super.onDestroy();
}
}


这样,一个简单的音乐播放服务,就完成了,当然,这只限于程序内播放,如果跨进程就不行了,我们可以通过startService启动改服务:

intent = new Intent(this,LocalService.class);
startService(intent);


在service中,因为我们在onbind中返回了对象,所以,我们也可以通过bindservice来启动服务:

public class ServiceHandlerActivity extends Activity {
//通过bindService启动服务,接收service实例
private LocalService localService;

//判断是否绑定

//服务连接类,实现ServiceConnection接口,在实现方法中接收service对象,通过bindService启动服务时,需要连接类对象
private MyServiceConnection myServiceConnection;

//通过startService启动服务
private Intent intent;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_service_handler);
//实例化服务连接类
myServiceConnection = new MyServiceConnection();
//通过startService启动服务
intent = new Intent(this,LocalService.class);
startService(intent);
}

@Override
protected void onDestroy() {
super.onDestroy();
}

/**
* 按钮的点击事件
*/
public void  btnClick(View v){
if(mBind) {//如果绑定了,则播放音乐
localService.playerStart();
}
}

/**
* 绑定service
* @param v
*/
public void btnBind(View v){
if(!mBind) {//如果未绑定,则绑定
bindService(intent, myServiceConnection, Context.BIND_AUTO_CREATE);
mBind = true;
}
}

/**
* 解绑service
* @param v
*/
public void btnUnBind(View v){
if(mBind) {//如果你已经绑定,则解绑
unbindService(myServiceConnection);
mBind = false;
}
}

/**
* 音乐暂停
* @param v
*/
public void btnStop(View v){
localService.playerPause();
}
//服务连接类m,实现了ServiceConnection
private class MyServiceConnection implements ServiceConnection{

//连接成功回调方法,在此方法中接收service实例
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取IBinder对象
LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
//通过IBinder对象,获取service实例
localService = binder.getLocalService();
//已绑定
mBind = true;
Log.i("yxs","连接");
}

@Override
public void onServiceDisconnected(ComponentName name) {
Log.i("yxs","取消连接");
mBind = false;
}
}
}


这里需要说明,通过startService启动服务,不需要服务连接类,而通过bindService则需要服务连接类,在实现ServiceConnection中,我们需要实现两个方法:连接成功,连接失败,连接成功后,我们通过IBinder对象获取serivce实例,才可以操作播放器。

通过bindService启动服务后,就意味着,activity和service绑定到了一起,activity生则service生,activity死,则service死(自动解除绑定);如果我们绑定后,执行了播放音乐,此时在解除绑定,那么,音乐不会停止,即使activity销毁,音乐依旧在播放,因为服务没有停止,除非杀掉进程。

如何结束服务:

如果是通过startService开启服务:

通过service对象调用stopService(intent);传入开启服务的intent对象


通过bindservice开启服务

通过service对象调用stopSelf();结束服务
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: