Binder机制,从Java到C (1. IPC in Application Remote Service)
转载请标注:张新燕:http://www.cnblogs.com/zhangxinyan
1. Application 中的 service
我们知道Android中Service有三种类型:Local Service,Local Bounded Service,Remote 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可以完成的功能接口
package com.example.remoteservice;
interface IRemoteService {
void doSomething ( );
}
2.实现Remote Service:写一个Service组件,在这个组件里,实现Stub(Stub是啥?后面有说)的具体功能,这些功能就对应了上面aidl文件里面定义的一些接口。
接着在回调函数onBind()中把这个实现的Stub对象返回出去。那谁会来调用这个onBind()函数呢?当然是ActivityManagerService啦,有关与ActivityManagerService的详细内容会新开一篇详细说明。下面就看代码吧:
 public class RemoteService extends Service {
         @Override
         public IBinder onBind(Intent intent) {
            if (IRemoteService.class.getName().equals(intent.getAction())) {
                return mRemoteBinder;  //把一个Binder对象返回出去。其实是返回到AMS里面了。AMS:ActivityManagerService。
            }
             return null;
         }
         private final IRemoteService.Stub mRemoteBinder =new IRemoteService.Stub() {//实现Stub对象要求的方法,即AIDL的实现。
            public void dosomething() {
                blablabla;
            }
         };
     }
3.访问Remote Service:接着就是在Activity里面启动和调用Service的功能了,怎么调用呢?看代码:
public class Helloworld extends Activity
{
...
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
bindService(new Intent(IRemoteService.class.getName()),mRemoteConnection,
Context.BIND_AUTO_CREATE); // 1.触发Service端回调onBind()。 (1)
...
mRemoteService.getPid(); //3. 会通过Binder IPC 将操作请求发送到Service端的Stub实现。 (3)
...
} private ServiceConnection mRemoteConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) { (2)
Log.i("binder_test","IBinder service : " + service.getClass());//通过Log发现,这个service是BinderProxy object,BinderProxy是什么呢?後面再說。暂时按字面理解为Binder代理对象。 mRemoteService = IRemoteService.Stub.asInterface(service); // 2.通过asInterface,把Binder代理对象转化成接口。
}
public void onServiceDisconnected(ComponentName className) {
mRemoteService = null;
}
};
}
说明:
(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
 package com.example.remoteservice;  
     public interface IRemoteService extends android.os.IInterface { 1
         public static abstract class Stub extends android.os.Binder implements
                com.example.remoteservice.IRemoteService {//继承Binder,并且实现了IRemoteService接口
              ...
            public static com.example.remoteservice.IRemoteService asInterface(android.os.IBinder obj) {//根据传进來的IBinder对象创建一个Service 代理對象給客戶端。
                ...
                android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
                if (((iin != null) && (iin instanceof com.example.remoteservice.IRemoteService))) {
                     return((com.example.remoteservice.IRemoteService) iin);
                }
                return new com.example.remoteservice.IRemoteService.Stub.Proxy(obj);  //看,返回的是Proxy这个对象。就是Service代理对象。
            }  
            public android.os.IBinder asBinder() {
                return this;
            }  
            @Override
            public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply,
                     int flags)throwsandroid.os.RemoteException { //把IPC消息取出来解析,找到具体执行方法。
                switch (code) {  //根据code值,找到方法。
                     case INTERFACE_TRANSACTION: {
                     }
                     case TRANSACTION_doSomething: {
                     }
                }
                return super.onTransact(code, data, reply, flags);
            }  
            private static class Proxy implements com.example.remoteservice.IRemoteService {//实现了IRemoteService接口
                private android.os.IBinder mRemote; //实际上是BinderProxy对象
               ...
                public int doSomething() throws android.os.RemoteException {
                      ...
                         mRemote.transact(Stub.TRANSACTION_doSomething,_data, _reply, 0);//通过BinderProxy將命令发送出去。
                     ….
            }
             static final int TRANSACTION_doSomething = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);   //这玩意就是用来区别方法的code。
         }  
         public void doSomething() throwsandroid.os.RemoteException;
     }  
这里面呢,会涉及到几个类,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)的更多相关文章
- Android Binder机制详解:手写IPC通信
		
想要掌握一样东西,最好的方式就是阅读理解它的源码.想要掌握Android Binder,最好的方式就是写一个AIDL文件,然后查看其生成的代码.本文的思路也是来自于此. 简介 Binder是Andro ...
 - Binder机制,从Java到C (2.  IPC in System Service :AMS)
		
1.建立Activity和Service的IPC之前 在上一篇 Binder机制,从Java到C (1. IPC in Application Remote Service) 里面有说到Activi ...
 - Binder机制,从Java到C (大纲)
		
转载请标注:张小燕:http://www.cnblogs.com/zhangxinyan/p/3487381.html 前段时间一直在看有关Binder机制的内容,觉得受益匪浅,整理记录于此,大家请随 ...
 - Binder机制,从Java到C (5. IBinder对象传递形式)
		
1.IBinder的传递 Binder IPC通信中,Binder是通信的媒介,Parcel是通信的內容.远程调用过程中,其参数都被打包成Parcel的形式來传递.IBinder对象当然也不例外,在前 ...
 - Binder机制,从Java到C (3.  ServiceManager in Java)
		
上一篇 Binder机制,从Java到C (2. IPC in System Service :AMS) 中提到 Application是通过ServiceManager找到了AMS 的servic ...
 - 进程间通信IPC与Binder机制原理
		
1, Intent隐式意图携带数据 2, AIDL(Binder) 3, 广播BroadCast 4, 内容提供者ContentProvider 5,Messager(内部通过binder实现) 6, ...
 - Android Binder机制简单了解
		
Binder -- 一种进程间通信(IPC)机制, 基于OpenBinder来实现 毫无疑问, 老罗的文章是不得不看的 Android进程间通信(IPC)机制Binder简要介绍和学习计划 浅谈Ser ...
 - 从mediaserver入手快速理解binder机制(最简单理解binder)【转】
		
本文转载自;https://blog.csdn.net/u010164190/article/details/53015194 Android的binder机制提供一种进程间通信的方法,使一个进程可以 ...
 - Android Binder机制(一) Binder的设计和框架
		
这是关于Android中Binder机制的一系列纯技术贴.花了一个多礼拜的时间,才终于将其整理完毕.行文于此,以做记录:也是将自己所得与大家分享.和以往一样,介绍Binder时,先讲解框架,然后再从设 ...
 
随机推荐
- Jquery基础教程第二版学习记录
			
本文仅为个人jquery基础的学习,简单的记录以备忘. 在线手册:http://www.php100.com/manual/jquery/第一章:jquery入门基础jquery知识:jquery能做 ...
 - JMeter 怎么保存登录状态
			
在Recording Controller中添加一个HTTP Cookie Manager Recording Controller右键-->add-->config element--& ...
 - js之面向对象----封装篇
			
学习了一天的面向对象总结一下,共分为三类 - -! 老规矩 第一部分是概念性知识!!! 面向对象编程,我们可以把他想象成我们在造人.一个对象便是一个人,这个人有胳膊有腿,这便是一个对象的属性或者方法. ...
 - MSMQ-发送消息到远程专用队列 实例
			
目录 一:MSMQ的一些理论上的知识 二:队列类型(Queue Type) 三:安装消息队列 四:在C#中Messagequeue class 五:MSMQ-发送消息到远程专用队列 六:例子 一. ...
 - 变焦控制ZoomControls
			
在安卓的webview中有这个点击放大缩小button,当时就在想如何实现那种效果,弄一个两个图标的ImageButton.但感觉又有些麻烦,昨天看疯狂安卓书.无意中发现另一个 ZoomButtons ...
 - ASP.NET MVC中加载WebForms用户控件(.ascx)
			
原文:ASP.NET MVC中加载WebForms用户控件(.ascx) 问题背景 博客园博客中的日历用的是ASP.NET WebForms的日历控件(System.Web.UI.WebControl ...
 - MVC验证12-使用DataAnnotationsExtensions对整型、邮件、最小值、文件类型、Url地址等验证
			
原文:MVC验证12-使用DataAnnotationsExtensions对整型.邮件.最小值.文件类型.Url地址等验证 本文体验来自http://dataannotationsextension ...
 - javascript4
			
javascript使用Unicode字符集编写的.javaScript是区分大小写的语言. 标示符就是一个名字.在javascript中用标示符来对变量和函数进行命名或者用做javascript代码 ...
 - Angular指令(一)
			
Angular开发者手册重点翻译之指令(一) 创建自定义的指令 这个文章将解释什么需要在自己的angularjs应用中创建自己的指令,以及如何实现它. 什么是指令 在高的层面上讲,指令是DOM元素中的 ...
 - 轻型ORM--Dapper
			
分享一个轻型ORM--Dapper选用理由 推荐理由:Dapper只有一个代码文件,完全开源,你可以放在项目里的任何位置,来实现数据到对象的ORM操作,体积小速度快:) Google Code下载地址 ...