本文将探索并回忆服务相关的一些使用技巧。众所周知服务分为通过startService启动的在后台长期运行且与该活动脱离关系的服务 以及通过bindService绑定的服务,下面将通过案例来具体介绍2者服务。
服务是Android中实现程序后台运行的解决方案,所有的代码都是运行在主线程中的。
先贴一张活动的生命周期图:
(该图来自Android开发中服务Service的基本使用(总结))
startService
特点:startService方式开启服务,服务会在后台长期运行,知道用户手动停止,或者调用stopService才会停止。
操作案例:
仅操作startService,通过开启服务观察其生命周期,然后再次开启查看其执行,接着关闭查看生命周期。
运行结果:
解释与总结:
上图即呈现了startService启动服务时的日志log,当我们第一次启动时会执行onCreate() onStartCommand() 而当该服务存活时我们仍然再去启动,那么只会执行onStartCommand方法,也就是说该类服务 onCreate() 只会调用一次,也只能在这里做一些初始化的工作。
==> 生命周期函数 详解
onCreate() 服务创建的时候调用
onStartCommand() 服务启动的时候调用 (接收数据)
onDestory() 服务销毁的时候调用 (回收资源)
===> 终止自身活动
在服务外部调用 stopService可终止特定service,当然也可通过在服务内部 stopSelf()来终止活动
bindService
特点:
客户端建立一个与Service的连接,并使用此连接与Service进行通话,通过Context.bindService()方法来绑定服务,Context.unbindService()方法来关闭服务。多个客户端可以绑定同一个服务,如果Service还未被启动,bindService()方法可以启动服务。
[用于服务与Activity进行通信]
运行结果:
如上图所示,当一个活动想多次绑定一个服务只会执行一次生命周期
多次bind一个服务,只会执行一次 onCreate() -> onBind() 的过程
bindService一个通信的小案例
service.java
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind:... ");
return new MyTestBinder();
}
public class MyTestBinder extends Binder{
public void activityCallServiceDoThings(){
Log.e(TAG, "activityCallServiceDoThings: 活动通知服务完成某事---------" );
}
}
activity.java
/**
* 监视服务的状态-------------
*/
private class MyServiceConnection implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mMyTestBinder = (TestService.MyTestBinder) service;
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
// 活动绑定服务
findViewById(R.id.bindService).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "**执行操作** 第"+j+"此执行bindService...");
bindService(new Intent(MainActivity.this,TestService.class),mMyServiceConnection,BIND_AUTO_CREATE);
j++;
}
});
// 点击活动与服务之间进行通信
findViewById(R.id.doSomething).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Log.e(TAG, "**执行操作** 活动向服务传消息");
if (mMyTestBinder != null){
mMyTestBinder.activityCallServiceDoThings();
}
}
});
测试下 启动服务+绑定服务过程
startService + bindSerice
完成的运行结果如下:
一些蛮好的文章:
Android面试题:bindService获取代理是同步还是异步
AIDL的基本使用记录:
与bindsevice实现的活动与服务类似。
aidl不支持public
由原来继承自Binder改为继承自AA.Stub
保证2个AIDL文件所在的包名相同
// 活动启动远程的服务
Intent intent = new Intent();
// 隐式意图
// 这是服务对应的 <intent-filter><Action = "xxxxxx"/ ></intent-filter>
intent.setAction("com.zxl.pay");
bindService(intent,coon,BIND_AUTO_CREATE);
连接获取对象 AA.Stub.asInterface(XXX) 执行转化
Activity Service通信案例
Activity中启动服务,并设置回调方法
private void startService(){
Intent intent = new Intent(this,RemoteService.class);
mActyServiceConn = new ActyServiceConn();
bindService(intent,mActyServiceConn, Context.BIND_AUTO_CREATE);
}
private void stopService(){
if (mActyServiceConn != null){
unbindService(mActyServiceConn);
mActyServiceConn = null;
}
}
private class ActyServiceConn implements ServiceConnection{
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
mIMusic = (IMusic) service;
// 设置回调方法的方式,让service回调Activity方法
mIMusic.registerStop(new IStopBackAction() {
@Override
public void stopCallBack() {
stopService();
ServiceActivity.this.finish();
}
});
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
@Override
protected void onDestroy() {
if (mActyServiceConn != null){
stopService();
}
super.onDestroy();
}
public class RemoteService extends Service {
public RemoteService() {
}
@Override
public IBinder onBind(Intent intent) {
return new MusicClass();
}
private class MusicClass extends Binder implements IMusic{
@Override
public void play() {
Toast.makeText(RemoteService.this, "音乐开启", Toast.LENGTH_SHORT).show();
}
@Override
public void pause() {
Toast.makeText(RemoteService.this, "音乐暂停", Toast.LENGTH_SHORT).show();
}
@Override
public void stop() {
Toast.makeText(RemoteService.this, "音乐结束", Toast.LENGTH_SHORT).show();
// 回调Activity进行传值
if (mIStopBackAction != null){
mIStopBackAction.stopCallBack();
}
}
IStopBackAction mIStopBackAction;
@Override
public void registerStop(IStopBackAction iStopBackAction) {
this.mIStopBackAction = iStopBackAction;
}
}
}
public interface IMusic {
void play();
void pause();
void stop();
void registerStop(IStopBackAction iStopBackAction);
}