Service是android中的服务组件, 经常用来执行一些运行在后台的耗时操作。 使用一个Service需要继承Service类, 并根据需要重写生命周期方法。 Service的生命周期如下:

   public abstract IBinder onBind (Intent intent): 该方法是一个抽象方法, 因此Service子类必须实现这个方法。 它返回一个IBinder对象, 应用程序可以通过这个对象与Service组件通信(关于这一点, 其后会有详细的讲解), 以bindService()方式启动Service时回调该方法。
  public void onCreate (): 当Service第一次被创建后回调的方法。
  public void onDestroy (): Service关闭之前回调的方法。
  public int onStartCommand (Intent intent, int flags, int startId): 以startService(Intent intent)的方式启动Service时, 系统都会回调该方法。

  public boolean onUnbind (Intent intent): 当所有绑定该Service的组件都断开连接时回调该方法。

  从图中可以看出, Service可以有两种启动方式:
  1. 以startService(Intent intent)的方式启动。 此时启动的Service与调用者之间没有关联, 即使调用者已经退出, Service仍然可以继续运行, 而且调用者和Service之间无法进行数据交换和通信。 如果需要停止Service的运行, 只能调用Context类的stopService(intent)方法, 或者由Service本身调用其stopSelf()等方法。
  2. 以bindService(Intent service, ServiceConnection conn, int flags)的方式启动。
  此时调用者与Service绑定在一起, 如果调用者退出, 则Service也随之退出, 而且调用者和Service之间可以进行数据交换或通信。

  根据调用者和Service是否在一个应用程序内, 可以将调用者和Service之间的通信分为进程内通信和进程间通信。
  a. 进程内通信。 bindService(Intent service, ServiceConnection conn, int flags)方法的第二个参数为ServiceConnection对象, 最后一个参数通常可以是Service。BIND_AUTO_CREATE。 ServiceConnection是一个接口, 该接口包含2个方法:
  onServiceConnected(ComponentName name, IBinder service): 该方法在调用者和Service成功绑定之后由系统回调。
  方法中的第一个参数ComponentName是所绑定的Service的组件名称, 而IBinder对象就是Service中onBinder()方法的返回值。 要实现调用者和Service之间的通信, 只需要调用IBinder对象中定义的方法即可。

  onServiceDisconnected(ComponentName name): 该方法在调用者解除和Service的绑定之后由系统回调。

  以下是利用Service实现进程内通信的一个例子。
  首先自定义Service类:
  Java代码

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
publicclassMyServiceextendsService {
publicclassMyBinderextendsBinder {
/**
* 获取Service的运行时间
* @return
*/
publiclonggetServiceRunTime() {
returnSystem.currentTimeMillis() - startTime;
}
}
privatelongstartTime;
/**
* MyBinder是Binder的子类, 而Binder实现了IBinder接口。
*/
@Override
publicIBinder onBind(Intent intent) {
returnnewMyBinder();
}
@Override
publicvoidonCreate() {
super.onCreate();
startTime = System.currentTimeMillis();
}
}


  然后在activity中绑定上述的Service:

  Java代码

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
publicclassMainActivityextendsActivity {
privateMyBinder binder = null
/** Called when the activity is first created. */
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 创建一个指向MyService的intent
Intent intent = newIntent("cn.xing.action.my_service");
this.bindService(intent,newMyServiceConnection(),
Service.BIND_AUTO_CREATE);
Button button = (Button) this.findViewById(R.id.button);
button.setOnClickListener(newView.OnClickListener() {
@Override
publicvoidonClick(View v) {
if(binder != null) {
Toast.makeText(getApplicationContext(),"MyService已经运行了"+ binder.getServiceRunTime()
+"毫秒", Toast.LENGTH_LONG).show();
}
}
});
}
/**
* 实现ServiceConnection接口
*
* @author xing
*
*/
privatefinalclassMyServiceConnectionimplementsServiceConnection {
/**
* 和MyService绑定时系统回调这个方法
*/
@Override
publicvoidonServiceConnected(ComponentName name, IBinder service) {
// MyService中的onBinder()方法的返回值实际上是一个MyBinder对象, 因此可以使用强制转换.
binder = (MyBinder) service;
}
/**
* 解除和MyService的绑定时系统回调这个方法
*/
@Override
publicvoidonServiceDisconnected(ComponentName name) {
// 解除和MyService的绑定后, 将binder设置为null.
binder = null
}
}
}


  b.进程间通信。 调用者和Service如果不在一个进程内, 就需要使用android中的远程Service调用机制。

  android使用AIDL定义进程间的通信接口。 AIDL的语法与java接口类似, 需要注意以下几点:
  1. AIDL文件必须以.aidl作为后缀名。
  2.AIDL接口中用到的数据类型, 除了基本类型, String, List, Map, CharSequence之外, 其他类型都需要导包, 即使两种在同一个包内。 List和Map中的元素类型必须是AIDL支持的类型。
  3. 接口名需要和文件名相同。
  4. 方法的参数或返回值是自定义类型时, 该自定义的类型必须实现了Parcelable接口。
  5. 所有非java基本类型参数都需要加上in, out, inout标记, 以表明参数是输入参数, 输出参数, 还是输入输出参数。
  6. 接口和方法前不能使用访问修饰符和static, final等修饰。

  下面通过一个例子来演示android远程Service调用机制的各个步骤:
  1. 创建remoteService项目。
  2. 在cn.xing.remoteservice包下定义aidl文件--IRemoteService.aidl:
  Java代码

?
代码片段,双击复制
01
02
03
04
packagecn.xing.remoteservice;
interfaceIRemoteService{
intgetServiceRunTime();
}


  Eclipse的ADT插件会在gen目录的cn.xing.remoteservice包下自动根据aidl文件生成IRemoteService接口。
  接口中有一个static的抽象内部类Stub, Stub类继承了Binder类并实现了IRemoteService接口。 Stub类有如下的静态方法:
  public static cn.xing.remoteservice。IRemoteService asInterface(android.os.IBinder obj)
  该方法接受一个IBinder对象, 返回值是IRemoteService的instance, 通过这个instance我们就可以调用IRemoteService中定义的方法了。

  3. 在remoteService项目的cn.xing.remoteservice包下创建远程服务类RemoteService:

  Java代码

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
publicclassRemoteServiceextendsService {
privatelongstartTime;
/**
* IRemoteService.Stub类实现了IBinder和IRemoteService接口
* 因此Stub的子类对象可以作为onBinder()方法的返回值.
* @author xing
*
*/
publicclassMyBinderextendsIRemoteService.Stub {
@Override
publiclonggetServiceRunTime()throwsRemoteException {
returnSystem.currentTimeMillis() - startTime;
}
};
@Override
publicIBinder onBind(Intent intent) {
returnnewMyBinder();
}
@Override
publicvoidonCreate() {
super.onCreate();
startTime = System.currentTimeMillis();
}
}


  4. 创建一个新的android项目invokeRemoteService, 并复制remoteService项目中的aidl文件(连同包结构一起复制)到invokeRemoteService项目中。

  5. 在invokeRemoteService项目中绑定远程服务, 并调用远程方法。

  Java代码

?
代码片段,双击复制
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
publicclassMainActivityextendsActivity {
privateIRemoteService iRemoteService = null
/** Called when the activity is first created. */
@Override
publicvoidonCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// 创建一个指向RemoteService的intent
Intent intent = newIntent("cn.xing.action.remote_service");
this.bindService(intent,newMyServiceConnection(),
Service.BIND_AUTO_CREATE);
Button button = (Button) this.findViewById(R.id.button);
button.setOnClickListener(newView.OnClickListener() {
@Override
publicvoidonClick(View v) {
if(iRemoteService != null) {
try{
Toast.makeText(getApplicationContext(),"MyService已经运行了"+ iRemoteService.getServiceRunTime()
+"毫秒", Toast.LENGTH_LONG).show();
}catch(RemoteException e) {
e.printStackTrace();
}
}
}
});
}
/**
* 实现ServiceConnection接口
*
* @author xing
*
*/
privatefinalclassMyServiceConnectionimplementsServiceConnection {
/**
* 和RemoteService绑定时系统回调这个方法
*/
@Override
publicvoidonServiceConnected(ComponentName name, IBinder service) {
// 此处不能使用强制转换, 应该调用Stub类的静态方法获得IRemoteService接口的实例对象
iRemoteService = IRemoteService.Stub.asInterface(service);
}
/**
* 解除和RemoteService的绑定时系统回调这个方法
*/
@Override
publicvoidonServiceDisconnected(ComponentName name) {
// 解除和RemoteService的绑定后, 将iRemoteService设置为null.
iRemoteService = null
}
}
}

Service与AIDL详解相关推荐

  1. Android四大组件Service之AIDL详解

    Android四大组件Service之AIDL详解 前言 简介 基础知识 AIDL 服务端 定义AIDL文件规则 创建 .aidl 文件 清单注册 通过 IPC 传递对象 调用 IPC 方法 Andr ...

  2. Android进阶——AIDL详解之使用远程服务AIDL实现进程间带远程回调接口和自定义Bean的较复杂通信小结(二)

    文章大纲 引言 一.远程回调AIDL接口的应用 1.封装基本的父类和一些工具类 2. 创建服务端的AIDL 2.1.定义回调AIDL接口 2.2.定义业务AIDL接口 3.实现服务端对应AIDL的带有 ...

  3. @Controller,@Service,@Repository,@Component详解

    转载自 @Controller,@Service,@Repository,@Component详解 @Controller 用来表示一个web控制层bean,如SpringMvc中的控制器. @Ser ...

  4. 容器编排技术 -- Kubernetes kubectl create service nodeport 命令详解

    容器编排技术 -- Kubernetes kubectl create service nodeport 命令详解 1 kubectl create service nodeport 2 语法 3 示 ...

  5. 容器编排技术 -- Kubernetes kubectl create service loadbalancer 命令详解

    容器编排技术 -- Kubernetes kubectl create service loadbalancer 命令详解 1 kubectl create service loadbalancer ...

  6. 容器编排技术 -- Kubernetes kubectl create service externalname 命令详解

    容器编排技术 -- Kubernetes kubectl create service externalname 命令详解 1 kubectl create service externalname ...

  7. 容器编排技术 -- Kubernetes kubectl create service clusterip 命令详解

    容器编排技术 -- Kubernetes kubectl create service clusterip 命令详解 1 kubectl create service clusterip 2 语法 3 ...

  8. android aidl编译,Android AIDL详解

    概述 AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言.是的,首先我们知道的第一点就是:AIDL是一种语言.既然是 ...

  9. Android进阶——AIDL详解

    看这篇之前先看看binder: Android--Binder机制. 1. 简介 AIDL(Android 接口定义语言),可以使用它定义客户端与服务端进程间通信(IPC)的编程接口,在 Androi ...

最新文章

  1. acess dao示例
  2. java中后端拼接字符串返回前台页面换行显示
  3. 非模态的titlewindow,点击外部时的事件
  4. Dataset之AllstateClaimsSeverity:AllstateClaimsSeverity数据集(Kaggle2016竞赛)的简介、下载、案例应用之详细攻略
  5. Hibernate事实:有利于双向集vs列表
  6. LeetCode 5235. 找出输掉零场或一场比赛的玩家(计数)
  7. mysql 数据库连接 w3school_PHP 连接 MySQL
  8. python基础编程语法-Python编程入门——基础语法详解
  9. 如何在 Mac 上创建自动填充的智能文件夹?
  10. jupyter 设置主题Error:Could not find a version that satisfies the requirement jupyterthemes from version
  11. linux下载ed2k资源,linux下迅雷替代方案-linux下载工具
  12. Easy AR初级开发教程
  13. mysql加入时间戳sql语句,SQL插入时间戳问题
  14. 企业SOA平台 JBoss SOA
  15. 分步:配置 IPAM 以管理 IP 地址空间
  16. rabbitmq 连接报错 An unexpected connection driver error occured
  17. 50例大数据术语英文翻译及详解
  18. 让SEO更具有杀伤力-黑链
  19. 对比一下各大博客的优缺点
  20. mybatis-plus的mapper.xml路径配置:Invalid bound statement (not found):...

热门文章

  1. Mysql Explain 结果字段解释
  2. Google面试题及答案
  3. MySQL 数据库 分页查询/聚合查询
  4. 2019年六大新兴信息安全方向
  5. JavaI/O:使用InputStreamReader和BufferedReade实现控制器输入输出
  6. Vue 全家桶 + Electron 开发的一个跨三端的应用
  7. 网络主机监控-nagios应用漫谈(三)
  8. 多线程同步之 WaitableTimer (等待定时器对象)[续三]
  9. DIY敷脸亲身示范做法 - 生活至上,美容至尚!
  10. Oracle等待事件说明