1.Service概述

Service服务是一个没有用户界面的在后台运行执行操作的应用组件,其它组件可以通过Intent意图启动这个Service去完成特定的功能,比如通过Service可以完成播放音乐等后台操作,且每个Service必须在manifest中 通过<service>来声明配置。每个service运行在宿主线程上,因此,访问网络读取Sdcard等耗时操作需要放在工作线程中!Android系统有五种进程Foreground
Process(比如Activity处于resumed状态),Visible Process(比如activity处于paused状态),Service Process,Background Process(比如activity处于stopped状态),Empty Process,service处于第三级,后台的Activiy处于第四等级,后台运行的进程被杀死的概率比service大。

2.Service的启动方式

(1).startService()

//    1.startService开启
public void start(View view) {//显示意图或者使用隐式意图找到Service对象Intent intent = new Intent(this, TestService.class);startService(intent);
}

(2).bindService()绑定服务

// 2.bindService绑定服务
public void bind(View view) {Intent intent = new Intent(this, TestService.class);conn = new MyServiceConn();bindService(intent, conn, Context.BIND_AUTO_CREATE);
}
class MyServiceConn implements ServiceConnection {/** Service服务返回一个IBinder对象,该onServiceConnected函数将接受该IBinder对象*/@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {System.out.println("得到binder对象");binder = (IMyBinder) service;}/**  一般不会被调用, 只有在Service被破坏了或者被杀死的时候调用. *  例如, 系统资源不足, 要关闭一些Services, 刚好连接绑定的 Service 是被关闭者之一,  这个时候onServiceDisconnected() 就会被调用。*/@Overridepublic void onServiceDisconnected(ComponentName name) {}
}

(3).两种启动方式的区别

可以多次启动同一服务,但只能一次终止该服务。两种启动方式对应服务的生命周期不调,bindService可以得到Binder代理对象。

通过startService方式启动的服务,在退出当前activity时,service服务仍然存在,但无法操作服务内部方法;

通过bindService可以得到Binder对象,间接调用服务内部方法,但在用户退出当前该Activity时,服务终止。

结合以上两种优点,结论

Activity使用startService启动服务(延长该服务的生命周期),再使用bindService()(服务已存在,但为得到Binder代理对象),再定义一个接口用于暴露MyBinder代理对象的方法,自定义MyBinder类(继承Binder实现接口),在服务的onBind()中返回MyBinder的实例化对象,Activity中ServiceConnection子类实例化对象的onServiceConnected()接收该Binder对象,再将该Binder对象强转为接口类型。通过调用Binder对象方法,达到在Binder对象内部操作服务方法。

更多Activity调用服务方法,请看下面源代码!

3.Service的生命周期

(1).startService启动方式的生命周期

1).context.startService() 当前activity调用startService()方法
2).service.onCreate() 当前服务如果首次创建,会执行服务的onCreate方法,执行一次 
3).service.onStart()   每次activity调用startService()都会执行该方法  
4).context.stopService()  停止当前服务   
5).service.onDestroy()    调用了服务onDestroy方法

(2).bindService启动方式的生命周期

1).context.bindService()绑定服务,可以指定服务标签,比如服务不存在可以自动创建
2).   service.onCreate()  服务如果首次创建,会执行服务的onCreate方法,执行一次 
3).   service.onBind() 每次绑定都会执行该方法,并返回一个Binder对象,通过该Binder对象,可以间接执行服务中的方法  
4).context.onUnbind() 解除绑定,如果当前服务是在绑定时候创建的,则销毁该服务 
5).   service.onDestroy()  销毁服务,Service调用onDestroy()

(3).混合启动方式的生命周期(***)

1).context.startService()   activity调用startService()方法
2).   service.onCreate()    服务首次创建,会执行服务的onCreate方法,执行一次
3).   service.onStart()       每次startService()都会执行该方法 
4).context.bindService()   操作同一服务,以得到Binder代理对象
5).   service.onBind();       返回Binder对象
6).在activity中操作binder对象,从而调用服务中方法
7).context.unbindService()可以在当前Activity销毁时,即在Activity的onDestroy解除绑定,用try语句,如果没有绑定服务可能出现异常
8).context.stopService()   activity停止服务 
9).   service.onDestroy()   服务销毁

4.IntentService

public abstract class IntentService extends Service {private volatile Looper mServiceLooper;private volatile ServiceHandler mServiceHandler;private String mName;private boolean mRedelivery;private final class ServiceHandler extends Handler {public ServiceHandler(Looper looper) {super(looper);}@Overridepublic void handleMessage(Message msg) {onHandleIntent((Intent)msg.obj);stopSelf(msg.arg1);}}@Overridepublic void onCreate() {super.onCreate();HandlerThread thread = new HandlerThread("IntentService[" + mName + "]");thread.start();   /** 在thread.start();    对应执行的run方法中,执行了* Looper.prepare();* Looper.loop();* 操作,然后将生成的looper作为参数,传递到handler中,虽然该handler在主线程中创建,* 但是由于为其制定了looper,故工作线程在阻塞掉用Loop.loop(),调用依然在工作线程中,* 耗时操作可以方法onHandleIntent中,可以处理接收到intent对象*/mServiceLooper = thread.getLooper();mServiceHandler = new ServiceHandler(mServiceLooper);}@Overridepublic void onStart(Intent intent, int startId) {Message msg = mServiceHandler.obtainMessage();msg.arg1 = startId;msg.obj = intent;mServiceHandler.sendMessage(msg);}protected abstract void onHandleIntent(Intent intent);
}

可查看Android_Thread多线程_Handler,Message,Looper,MessageQueue多线程和特殊UI更新一文

5.粘性Service和非粘性Service

只有在系统内存很低时,才有可能强制杀死Service来回收系统资源。如果该Service绑定在有用户焦点的Activity上,很少可能被杀死;如果在foreground中定义,几乎不可能被杀死。onStartCommand()必须返回一个整数,该返回值描述了服务被杀死后如何再处理该服务,下面接受3种类型!

(1).START_NOT_STICKY

If the system kills the service 
after onStartCommand() returns, do not recreate the service, unless there are pending intents to deliver. This is the safest option
to avoid running your service when not necessary and when your application can simply restart any unfinished jobs.

(2).START_STICKY

If the system kills the service 
after onStartCommand() returns, recreate the service and call onStartCommand(),but do not redeliver the last intent. Instead, the
system callsonStartCommand() with a 
null intent,
 unless there were pending intents to start the service, in which case, those intents are delivered. This is suitable for media players (or similar services) that are not executing commands, but running indefinitely and waiting
for a job.

(3).START_REDELIVER_INTENT

If the system kills the service 
after onStartCommand() returns, recreate the service and call onStartCommand() withthe last intent that was delivered to the service.
Any pending intents are delivered in turn. This is suitable for services that are actively performing a job that should be immediately resumed, such as downloading a file.

6.Service完成UI的更新

public class MainActivity extends Activity {private ProgressBar bar;private IMyBinder mBinder;private Handler handler = new Handler(){public void handleMessage(Message msg) {bar.setProgress(Integer.parseInt(msg.obj.toString()));} };@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);bar = (ProgressBar) findViewById(R.id.progressBar1);startService(new Intent(this, MyService.class));bindService(new Intent(this, MyService.class), conn, Context.BIND_AUTO_CREATE);}public void click(View view){mBinder.doLongWork();}private ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {mBinder = (IMyBinder) service;//得到binder对象,为其设定handler对象mBinder.setHandler(handler);};};
}
public class MyService extends Service {private Handler mHandler;private Mybinder binder;@Overridepublic void onCreate() {super.onCreate();binder = new Mybinder();}@Overridepublic IBinder onBind(Intent intent) {return binder;}class Mybinder extends Binder implements IMyBinder{@Overridepublic void setHandler(Handler handler) {//用于接收handler对象,完成ui的更新mHandler = handler;}@Overridepublic void doLongWork() {//开启线程,完成耗时操作new Thread(){public void run() {for(int i=0; i<11; i++){try {Thread.sleep(300);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("i = "+i);Message msg = mHandler.obtainMessage();msg.obj = i*10;mHandler.sendMessage(msg);}}}.start();}}
}
/*** 提供一个公共接口* @author Administrator**/
public interface IMyBinder {public void setHandler(Handler handler);public void doLongWork();
}

7.服务类型分类

(1).本地服务

服务依附在主进程上而不是独立的进程,服务通信很方便。主进程终止后,服务也会终止,音乐播放等后台操作大多是这种类型。

服务通信,一种方式是通过绑定服务,根据返回Binder对象调用;另一种是在服务类别声明一个广播接收者内部类,其它应用通过发送一个广播,来达到通信目的。通信过程请看后面介绍。

(2).远程服务

该服务是独立的进程,这种Service是常驻的,如果想其它应用与该service通信,必须满足一定机制要求。达到远程服务通信,除了发送一个广播,还可以根据aidl(安卓接口定义语言)。

8.服务通信

(1).通用型(本地/远程)

1).广播接收者

 
/*** TestService.java* 允许第三方应用,启动该服务完成计算的功能,第三方广播的intent设置需要计算的参数,* 在内部类广播接收者中获得该参数信息,并调用服务的方法,完成计算功能* @author Administrator*/
public class TestService extends Service {private MyReceiver receiver;@Overridepublic void onCreate() {/** 服务开启的时候注册一个广播接收者,广播接收者注册不用再清单文件中配置* 其action为com.baidu.caluservice2*/receiver = new MyReceiver();IntentFilter filter = new IntentFilter();filter.addAction("com.baidu.caluservice2");registerReceiver(receiver, filter);  //注册接收者super.onCreate();}//内部类的广播接收者class MyReceiver extends BroadcastReceiver{@Overridepublic void onReceive(Context context, Intent intent) {//得到传递的参数信息int m = intent.getIntExtra("m", 0);int n = intent.getIntExtra("n", 0);// 调用服务的计算功能int result = methodService(m, n);Toast.makeText(getApplicationContext(), m+"+"+n+"="+result, Toast.LENGTH_SHORT).show();}}//服务计算功能public int methodService(int m, int n){int result = m*n;return result;}@Overridepublic IBinder onBind(Intent intent) {// TODO Auto-generated method stubreturn null;}// 对于注册的广播接收者,在服务销毁时,应该解除广播的注册@Overridepublic void onDestroy() {unregisterReceiver(receiver);super.onDestroy();}
}
<!-- AndroidManifest.xml -->
<service android:name="com.baidu.calu.TestService"><intent-filter><action android:name="com.baidu.caluservice"/></intent-filter>
</service>
/*** TestService.java* 第三方应用发送一个携带传递参数的广播,通过其它应用的服务,完成计算的功能* @author Administrator**/
public class MainActivity extends Activity {private EditText textm;private EditText textn;private Intent intent;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textm = (EditText) this.findViewById(R.id.textm);textn = (EditText) this.findViewById(R.id.textn);//首先应该启动第三方服务,完成广播接收者注册初始化intent = new Intent();intent.setAction("com.baidu.caluservice");startService(intent);}public void start(View view){//发送一个广播,并未intent设置需要传递的参数信息Intent intent2 = new Intent();intent2.setAction("com.baidu.caluservice2");//设置需要传递 的参数信息intent2.putExtra("m", Integer.parseInt(textm.getText().toString()));intent2.putExtra("n", Integer.parseInt(textn.getText().toString()));sendBroadcast(intent2);}@Overrideprotected void onDestroy() {stopService(intent);super.onDestroy();}
}

2).Parcel

private ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Parcel data = Parcel.obtain();Parcel reply = Parcel.obtain();data.writeInt(10);data.writeInt(20);try {/** transact(),将包含数据的data,调用binder对象的onTransact()方法,* 接收onTransact()写入的数据reply,通过reply得到执行结果* 实际上,service中的binder的onTransact()方法在主线程中调用,不能执行耗时操作* 可以在执行service.transact(100, data, reply, 0);时使用多线程*/service.transact(100, data, reply, 0);int result = reply.readInt();//得到结果} catch (RemoteException e) {e.printStackTrace();}data.recycle();reply.recycle();};
};
public class MyService extends Service {private Mybinder binder;@Overridepublic void onCreate() {super.onCreate();binder = new Mybinder();}@Overridepublic IBinder onBind(Intent intent) {return binder;}class Mybinder extends Binder{@Overrideprotected boolean onTransact(int code, Parcel data, Parcel reply,int flags) throws RemoteException {/** Parcel data  activity写入的数据* Parcel reply 执行完成之后写入的数据*/int x = data.readInt();int y = data.readInt();reply.writeInt(x+y);return super.onTransact(code, data, reply, flags);}}
}

(2).代理通信

1).本地Binder通信

/*** MainActivity.java* @author Administrator**/
public class MainActivity extends Activity {private EditText textm;private EditText textn;private IMyBinder binder; //Binder对象@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textm = (EditText) this.findViewById(R.id.textm);textn = (EditText) this.findViewById(R.id.textn);}public void start(View view){Intent intent = new Intent(this, CalService.class);// 绑定服务bindService(intent, new MyServiceConn(), Context.BIND_AUTO_CREATE);}class MyServiceConn implements ServiceConnection{@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {//service返回Binderdialing对象,由于代理对象私有,只能强转为其实现的接口类型binder = (IMyBinder) service;String m = textm.getText().toString();String n = textn.getText().toString();try {//调用binder的方法,从而调用service内部计算方法,并得到计算的返回值int result = binder.method(Integer.parseInt(m), Integer.parseInt(n)); Toast.makeText(MainActivity.this, m+"+"+n+"="+result, Toast.LENGTH_SHORT).show();} catch (Exception e) {e.printStackTrace();}}//服务异常退出或者终止时才调用该方法@Overridepublic void onServiceDisconnected(ComponentName name) {}}
}
/*** IMyBinder.java* 供代理类继承,并暴露代理类的方法,供调用者使用* @author Administrator**/
interface IMyBinder {int method(int m, int n);
}
/*** CalService.java* 计算服务* @author Administrator**/
public class CalService extends Service {private MyBinder binder;@Overridepublic void onCreate() {binder = new MyBinder();super.onCreate();}//每次绑定会调用该方法@Overridepublic IBinder onBind(Intent intent) {return binder;}//内部代理类,该类应该设置为私有的,只向外暴露继承接口的方法private class MyBinder extends Binder implements IMyBinder {@Overridepublic int method(int m, int n) {//调用服务内部方法int result = methodService(m, n);return result;}}// 服务计算功能public int methodService(int m, int n) {int result = m + n;return result;}
}

2) .远程aidl通信

/*** TestService.java* 允许第三方应用,启动该服务完成计算的功能,第三方广播的intent设置需要计算的参数,* 在内部类广播接收者中获得该参数信息,并调用服务的方法,完成计算功能* @author Administrator**/
public class TestService extends Service {private MyBinder binder;@Overridepublic void onCreate() {System.out.println("onCreate");binder = new MyBinder();super.onCreate();}//返回Binder对象@Overridepublic IBinder onBind(Intent intent) {System.out.println("onBind");return binder;}//直接继承IMyBinder的Stub内部类,由于该类已经继承了Binderprivate class MyBinder extends IMyBinder.Stub{@Overridepublic int method(int m, int n) throws RemoteException {//调用service方法int result = methodService(m, n);return result;}}//计算中心public int methodService(int m, int n){int result = m*n;return result;}
}
/*** 服务下的IMyBinder.aidl文件* aidl文件,该文件定义不能使用public使用权限,由于接口已经默认为public,该文件会自动编译* 调用该服务的应用也应该声明同样的IMyBinder.aidl文件,注意包名也应该一致* @author Administrator**/
interface IMyBinder {int method(int m, int n);
}
/*** MainActivity.java* 第三方应用发送一个携带传递参数的广播,通过其它应用的服务,完成计算的功能* @author Administrator**/
public class MainActivity extends Activity {private EditText textm;private EditText textn;private IMyBinder binder; @Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);textm = (EditText) this.findViewById(R.id.textm);textn = (EditText) this.findViewById(R.id.textn);}public void start(View view){//绑定服务Intent intent = new Intent();intent.setAction("com.baidu.caluservice");bindService(intent, new MyServiceConn(), Context.BIND_AUTO_CREATE);}class MyServiceConn implements ServiceConnection{@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {//得到服务onBind返回的Binder对象binder = IMyBinder.Stub.asInterface(service); //使用该方式得到返回的接口对象String m = textm.getText().toString();String n = textn.getText().toString();try {//调用binder方法,并得到返回值int result = binder.method(Integer.parseInt(m), Integer.parseInt(n)); Toast.makeText(MainActivity.this, m+"+"+n+"="+result, Toast.LENGTH_SHORT).show();} catch (Exception e) {e.printStackTrace();}}@Overridepublic void onServiceDisconnected(ComponentName name) {}}
}
/*** 第三方应用的IMyBinder.aidl文件* 注意包名应该与服务的包名一致* @author Administrator**/
interface IMyBinder {int method(int m, int n);
}

Android_Service组件详解相关推荐

  1. Android笔记——四大组件详解与总结

    android四大组件分别为activity.service.content provider.broadcast receiver. -------------------------------- ...

  2. ReactNative ViewPageAndroid组件详解

    源码传送门 在我们开发Android的时候,ViewPage这个控件的使用频率还是很高的,最简单的就是制作引导页,应用程序的主界面等,在ReactNative开发中实现该功能的组件是ViewPageA ...

  3. Android Lifecycle 生命周期组件详解

    转载请标明出处:https://blog.csdn.net/zhaoyanjun6/article/details/99695779 本文出自[赵彦军的博客] 一.Lifecycle简介 为什么要引进 ...

  4. Cinder 组件详解 - 每天5分钟玩转 OpenStack(47)

    Cinder 组件详解 - 每天5分钟玩转 OpenStack(47) 本节我们将详细讲解 Cinder 的各个子服务. cinder-api cinder-api 是整个 Cinder 组件的门户, ...

  5. Android应用开发—Intent组件详解

    转载自:Android中Intent组件详解 Intent是不同组件之间相互通讯的纽带,封装了不同组件之间通讯的条件. Intent本身是定义为一个类别(Class),一个Intent对象表达一个目的 ...

  6. ue4移动到一定距离_UE4移动组件详解(一)——移动框架与实现原理

    原文链接(转载请标明):UE4移动组件详解(一)--移动框架与实现原理_Jerish的博客-CSDN博客​blog.csdn.net 前言 关于UE4的移动组件,我写了一篇非常详细的分析文档.由于篇幅 ...

  7. SpringCloud分布式开发五大组件详解

    SpringCloud分布式开发五大组件详解 https://blog.csdn.net/weixin_40910372/article/details/89466955 服务发现--Netflix ...

  8. Tkinter 组件详解(十):Scale

    Tkinter 组件详解之Scale Scale(刻度)组件看起来像是一个带数据的 Scrollbar(滚动条)组件,但事实上它们是不同的两个东东.Scale 组件允许用于通过滑动滑块来选择一个范围内 ...

  9. Unity 之 UGUI Dropdown下拉选单组件详解

    Unity 之 UGUI Dropdown下拉选单组件详解 1,属性面板 1), Dropdown的组成 2,代码操作 3,使用实例 1), 控制菜单展开方向 4,相关扩展 1), Lua中动态添加O ...

最新文章

  1. golang http 操作 简介
  2. 转:并口编程参考资料
  3. vuedraggable示例_vue拖拽列表vuedraggable
  4. 停车场管理系统代码_jsp19109商场商铺停车场服务系统-SSM-Mysql
  5. Builder模式和Spring框架
  6. fscanf()php,fscanf函数的用法
  7. 用 Python 编写一个天气查询应用
  8. [ZJOI2010]排列计数
  9. 211.添加与搜索单词-数据结构设计
  10. Windows-局域网文件服务器文件共享软件 FtpServer
  11. 基于HTML5+CSS制作 H5移动端电商购物网页设计35页面(包括主页,商品详情,转账,付款,购物车等页面) 功能齐全...
  12. 希尔伯特空间/再生核希尔伯特空间
  13. 前端面试题(不定期更新)
  14. 【Unity】Button基础-按钮更换图片样式
  15. MySQL误操作数据恢复之误删表
  16. java中的画图公式_GitHub - oneSaber/Compiler-java: 函数绘图语言java实现
  17. ubuntu解决微信无法输入中文
  18. Win7解决telnet不是内部或外部命令的方法
  19. RESTful API 末尾斜杠
  20. 千里马若有人赏识--不论对错,不为输赢,我就是认真。

热门文章

  1. centos安装python gcc sqlite
  2. 在U盘上安装Linux系统解决方案
  3. div隐藏select显示的解决办法(就死select挡住了div) 不是网上找到的那五种
  4. 诗与远方:无题(五)
  5. Maven自学日志01---安装
  6. 记一次从Sql Server中图片二进制流还原回图片的开发过程
  7. 计算机进程调度论文,计算机操作系统小论文Linux进程调度.doc
  8. 微信小程序父子组件通信
  9. shell 文本后几行_Shell和Vi编辑器
  10. php 获取内容页图片,织梦CMS如何从列表页获取内容页的图片