转载请标注:张新燕:http://www.cnblogs.com/zhangxinyan

1. Application 中的 service

我们知道Android中Service有三种类型:Local ServiceLocal Bounded ServiceRemote Service

Local Service:基本是提供给自已应用使用,通过startService(intent)来启动。

Local Bounded Service:也是提供给自己应用使用,通过bindService(intent)启动,然后在回调中获得service,这种service一般很少写,因为既然只提供给自己使用,又何必从回调绕个圈子呢。用第一种service就好了。

RemoteService:可以共享給更多使用者,这里就會涉及到IPC机制。在Android中,IPC机制是通过Binder来实现的。接下来就让我们开始看看Binder究竟是什么玩意吧~

2.Remote Service:

先来看看App层会遇到IPC的地方。
我们在写App时,当遇到需要在后台默默做点什么事情时,就会采用Service这个组件,当你这个Service要大公无私的向外面提供服务时,我们会采用RemoteService这个玩意。下面我们就看一下怎么样来写一个RemoteService:

1.先定義一個aidl文件:在这个文件里写上这个Service可以完成的功能接口

  1. package com.example.remoteservice;
  2. interface IRemoteService {
  3. void doSomething ( );
  4. }

2.实现Remote Service:写一个Service组件,在这个组件里,实现Stub(Stub是啥?后面有说)的具体功能,这些功能就对应了上面aidl文件里面定义的一些接口。
接着在回调函数onBind()中把这个实现的Stub对象返回出去。那谁会来调用这个onBind()函数呢?当然是ActivityManagerService啦,有关与ActivityManagerService的详细内容会新开一篇详细说明。下面就看代码吧:

  1. public class RemoteService extends Service {
  2. @Override
  3. public IBinder onBind(Intent intent) {
  4. if (IRemoteService.class.getName().equals(intent.getAction())) {
  5. return mRemoteBinder; //把一个Binder对象返回出去。其实是返回到AMS里面了。AMS:ActivityManagerService。
  6. }
  7. return null;
  8. }
  9. private final IRemoteService.Stub mRemoteBinder =new IRemoteService.Stub() {//实现Stub对象要求的方法,即AIDL的实现。
  10. public void dosomething() {
  11. blablabla;
  12. }
  13. };
  14. }

3.访问Remote Service:接着就是在Activity里面启动和调用Service的功能了,怎么调用呢?看代码:

  1. public class Helloworld extends Activity
  2. {
  3. ...
  4. @Override
  5. public void onCreate(Bundle savedInstanceState)
  6. {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9. bindService(new Intent(IRemoteService.class.getName()),mRemoteConnection,
  10. Context.BIND_AUTO_CREATE); // 1.触发Service端回调onBind()。     (1)
  11. ...
  12. mRemoteService.getPid(); //3. 会通过Binder IPC 将操作请求发送到Service端的Stub实现。    (3)
  13. ...
  14. }
  15.  
  16. private ServiceConnection mRemoteConnection = new ServiceConnection() {
  17. public void onServiceConnected(ComponentName className, IBinder service) {    2
  18. Log.i("binder_test","IBinder service : " + service.getClass());//通过Log发现,这个service是BinderProxy object,BinderProxy是什么呢?後面再說。暂时按字面理解为Binder代理对象。
  19.  
  20. mRemoteService = IRemoteService.Stub.asInterface(service); // 2.通过asInterface,把Binder代理对象转化成接口。
  21. }
  22. public void onServiceDisconnected(ComponentName className) {
  23. mRemoteService = null;
  24. }
  25. };
  26. }

说明:
(1)  :在这里调用bindService,最后其实会调用到AMS(ActivityManagerService)中。AMS就会去查找当前系统中有没有已经启动过这个Service了,如果没有启动这个Service,就把它启动起来。然后会调用它的onBind()回调,获得Service的Binder对象。再经过一系列处理后,从调用者 Activity 的 (2)这个地方回调回来,把service传给它,当然其中对象会有一些变化,我们在回调的这个地方把返回的service打印了出来:

所以那个回调 onServiceConnected传进来的 IBinder service,它其实是一个BinderProxy!按照字面意思,我们称它为 Binder代理对象,先不管这个IBinder是来的,也不管BinderProxy到底是什么,先往下看,看下去你就会慢慢知道了。
这个对象返回到Activity中之后,通过asInterface进行一个转化,转化成了接口,其实是转化成了Proxy对象啦,Proxy对象实现了接口。
那这个转化得来的mRemoteService,我们以后就称之为 Service代理对象。
(3) :这样,获得了Service的代理对象之后,就可以通过Service代理对象调用Service的功能啦。虽然Service具体的执行是在另外一个进程,但是你是感觉不到的。

3. AIDL 工具

上面说的内容似乎有点乱,那我们整理下上面的访问过程,可以看一下下面的图:

这里面的Stub对象,Stub.Proxy对象,这些对象我们上面都没有创建吧?这些类其实都是由aidl工具自动生成的。

Client中Activity,通过bindService,触发Service回调onBind()方法,把一个Binder代理对象返回给Client。

Client通过转化,转化成一个Service代理对象,Client通过这个Service代理对象,在通过底层的Binder驱动,就可以调用进Service进程。在Service进程收到请求后,会根据里面的一个参数值,找到对应的函数,执行具体的操作。

下面这个类就是用了aidl工具后,IRemoteService.aidl自动生成的对应的类:IRemoteService.java

  1. package com.example.remoteservice;
  2.  
  3. public interface IRemoteService extends android.os.IInterface { 1
  4. public static abstract class Stub extends android.os.Binder implements
  5. com.example.remoteservice.IRemoteService {//继承Binder,并且实现了IRemoteService接口
  6. ...
  7. public static com.example.remoteservice.IRemoteService asInterface(android.os.IBinder obj) {//根据传进來的IBinder对象创建一个Service 代理對象給客戶端。
  8. ...
  9. android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
  10. if (((iin != null) && (iin instanceof com.example.remoteservice.IRemoteService))) {
  11. return((com.example.remoteservice.IRemoteService) iin);
  12. }
  13. return new com.example.remoteservice.IRemoteService.Stub.Proxy(obj);  //看,返回的是Proxy这个对象。就是Service代理对象。
  14. }
  15.  
  16. public android.os.IBinder asBinder() {
  17. return this;
  18. }
  19.  
  20. @Override
  21. public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply,
  22. int flags)throwsandroid.os.RemoteException { //把IPC消息取出来解析,找到具体执行方法。
  23. switch (code) { //根据code值,找到方法。
  24. case INTERFACE_TRANSACTION: {
  25. }
  26. case TRANSACTION_doSomething: {
  27. }
  28. }
  29. return super.onTransact(code, data, reply, flags);
  30. }
  31.  
  32. private static class Proxy implements com.example.remoteservice.IRemoteService {//实现了IRemoteService接口
  33. private android.os.IBinder mRemote; //实际上是BinderProxy对象
  34. ...
  35. public int doSomething() throws android.os.RemoteException {
  36. ...
  37. mRemote.transact(Stub.TRANSACTION_doSomething,_data, _reply, 0);//通过BinderProxy將命令发送出去。
  38. ….
  39. }
  40. static final int TRANSACTION_doSomething = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);   //这玩意就是用来区别方法的code。
  41. }
  42.  
  43. public void doSomething() throwsandroid.os.RemoteException;
  44. }

这里面呢,会涉及到几个类,Proxy啦,Binder啦等等,他们的关系图可以在下图中看出:

那Stub和Proxy都实现了了IRemoteService。但是呢Proxy只是把参数包装一下,通过mRemote发送出去。

Stub就是真正实现的地方了,不过这边实现的代码其实是写在Service里的,就是那个mRemoteBinder。

Proxy类是Stub的一个子类。Proxy里面的mRemote就是BinderProxy,通过它就可以把请求发送出去,然后再通过底层Binder的一些操作,最后走到Service进程里去执行一些操作。

那来总结一下吧,上面这個过程可以概括的说是:

1.Activity通过AMS的bindService(String name),让AMS做一些查找操作,然后AMS把一個service的Binder代理对象返回给Activity。
2.Activity通过一個转换,创建一個service代理对象Proxy,其是在Proxy里面,还是利用Binder代理对象向service发送命令。

下一篇会将一下AMS里面的IPC机制:

Binder机制,从Java到C (2. IPC in System Service :AMS)

Binder机制,从Java到C (1. IPC in Application Remote Service)的更多相关文章

  1. Android Binder机制详解:手写IPC通信

    想要掌握一样东西,最好的方式就是阅读理解它的源码.想要掌握Android Binder,最好的方式就是写一个AIDL文件,然后查看其生成的代码.本文的思路也是来自于此. 简介 Binder是Andro ...

  2. Binder机制,从Java到C (2. IPC in System Service :AMS)

    1.建立Activity和Service的IPC之前 在上一篇 Binder机制,从Java到C (1. IPC in Application Remote Service)  里面有说到Activi ...

  3. Binder机制,从Java到C (大纲)

    转载请标注:张小燕:http://www.cnblogs.com/zhangxinyan/p/3487381.html 前段时间一直在看有关Binder机制的内容,觉得受益匪浅,整理记录于此,大家请随 ...

  4. Binder机制,从Java到C (5. IBinder对象传递形式)

    1.IBinder的传递 Binder IPC通信中,Binder是通信的媒介,Parcel是通信的內容.远程调用过程中,其参数都被打包成Parcel的形式來传递.IBinder对象当然也不例外,在前 ...

  5. Binder机制,从Java到C (3. ServiceManager in Java)

    上一篇 Binder机制,从Java到C (2. IPC in System Service :AMS)  中提到 Application是通过ServiceManager找到了AMS 的servic ...

  6. 进程间通信IPC与Binder机制原理

    1, Intent隐式意图携带数据 2, AIDL(Binder) 3, 广播BroadCast 4, 内容提供者ContentProvider 5,Messager(内部通过binder实现) 6, ...

  7. Android Binder机制简单了解

    Binder -- 一种进程间通信(IPC)机制, 基于OpenBinder来实现 毫无疑问, 老罗的文章是不得不看的 Android进程间通信(IPC)机制Binder简要介绍和学习计划 浅谈Ser ...

  8. 从mediaserver入手快速理解binder机制(最简单理解binder)【转】

    本文转载自;https://blog.csdn.net/u010164190/article/details/53015194 Android的binder机制提供一种进程间通信的方法,使一个进程可以 ...

  9. Android Binder机制(一) Binder的设计和框架

    这是关于Android中Binder机制的一系列纯技术贴.花了一个多礼拜的时间,才终于将其整理完毕.行文于此,以做记录:也是将自己所得与大家分享.和以往一样,介绍Binder时,先讲解框架,然后再从设 ...

随机推荐

  1. Unix / 类 Unix shell 中有哪些很酷很冷门很少用很有用的命令?(转)

    著作权归作者所有. 商业转载请联系作者获得授权,非商业转载请注明出处. 作者:孙立伟 链接:http://www.zhihu.com/question/20140085/answer/14107336 ...

  2. 向西项目管理工具Maven一片

    前言 相信仅仅要做过 Java 开发的童鞋们,对 Ant 想必都不陌生,我们往往使用 Ant 来构建项目,尤其是涉及到特别繁杂的工作量.一个 build.xml 可以完毕编译.測试.打包.部署等非常多 ...

  3. Ajax.BeginForm的异步提交数据 简介

    Html.BeginForm与Ajax.BeginForm都是MVC架构中的表单元素,它们从字面上可以看到区别,即Html.BeginForm是普通的表单提交,而Ajax.BeginForm是支持异步 ...

  4. TRILL浅析

    1 TRILL概述 TRILL的全称就是Transparent Interconnection of Lots of Links,顾名思义,其本质就是将非常多条链路透明地组织在一起,以致于上层IP应用 ...

  5. [kmp+dp] hdu 4628 Pieces

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4622 Reincarnation Time Limit: 6000/3000 MS (Java/Ot ...

  6. 剑指XX(游戏10) - 走正步工厂一个安静的农场游戏的代码

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2lsYW5ncXVhbg==/font/5a6L5L2T/fontsize/400/fill/I0JBQk ...

  7. 【phpMyAdmin】更改配置文件连接到其他server

    默认phpMyAdmin安装完毕后对机器的访问mysql,但有时我们需要访问其它server的mysql数据库,所以我们需要配置. 真,phpMyAdmin已经为我们做了配置的选项.可是须要我们进行一 ...

  8. mongodb操作:利用javaScript封装db.collection.find()后可调用函数源码解读

    { "_mongo" : connection to YOURIP:27017{ SSL: { sslSupport: false, sslPEMKeyFile: "&q ...

  9. android项目总体界面架构(可直接复用)

    文章解读.效果图.源代码下载链接 http://blog.csdn.net/gao_chun/article/details/37903673

  10. MPEG-DASH on IIS Practice in Action

    1. 准备  IIS Media Service已经安装准备好(如上),注意需要在2008上安装,2003安装不了,或者就算能安装也很麻烦 一个或多个码率的媒体文件如MP4已经准备好 DASH MPD ...