系统服务依赖的是Binder构架。
Binder和BinderProxy直接继承IBinder。
通信:服务Proxy(如:ActivityManagerService)通过BinderProxy,再通过BpBinder,再将请求传到Binder驱动。Binder驱动通过ServiceManager得到注册的IBinder对应的JavaBBinder,再层层上到java层的真正服务对象。这样可以实现跨进程通信。
在以上的构架基础上,ADIL为我们简化了整个通信的搭建过程。
首先,你要定义一个aidl格式的文件,如:
package com.udnderstanding.samples;
interface ImyServer{
int foo(String str);
}
这样就定义了一个名为IMyServer的Binder服务,并提供了一个可以跨Binder调用的接口foo()。
一个AIDL文件将被aidl工具解析成三个产物:
1.IMyServer接口:它仅仅用来在Java 中声明IMyServer.aidl中所声明的接口。
2.IMyServer.Stub类:这个继承自Binder类的抽象类实现了Bn端与Binder通信相关的代码
3.IMyServer.Stub.Proxy类。这个类实现了Bp端与Binder通信相关的代码。
在完成爱的了解析后,为了实现一个Bn端,开发者需要继承IMyServer.Stub类并实现其抽象方法。
每个MyServer实例都具有了作为Bn端的能力。
典型用法:
1.将MyServer类的实例通过ServiceManager.addService(String name, IBinder service)将其注册为一个系统服务。
2.在一个Android标准Service的onBind()方法中将其作为返回值使之可以被其他进程访问
3.通过binder调用将其传递给另外一个进程,使之成为一个跨进程的回调对象。
但是殊途同归,在Bp端所在进程中,一旦获取了IMyServer的BinderProxy(通过ServiceManager.geService()、onSrviceConnected()、或者其他方式),就可以通过如下方式获得一个IMyServer.Proxy:
//就是最终需要获得com.understanding.samples.IMyServer.Stub.Proxy,asInterface()返回就是这个类型
IMyServer remote = IMyServer.Stub.asInterface(binderProxy);
remote.foo("Hello AIDL");
下面是aidl工具自动解析成的文件。
public interface IMyServer extends android.os.IInterface{
//自动生成一个内部类
public static abstract class Stub extends android.os.Binder implements com.understanding.samples.IMyServer{
/********code:对应不同的方法,表示proxy所需调用的方法。
data:从proxy打包传过来的参数
在proxy发出请求后,最终会调用Stub的子类的onTransact()方法,而onTransact()中会调用foo(),所以子类需实现foo()
*/
public boolena onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
throws android.os.RemoteException{
switch(code){
......
case TRANSACTION_foo:{
......//从data中读取参数_arg0
//Stub类的子类需要实现foo()方法
int _result = this.foo(_arg0);
......//向reply中写入_result
return true;
}
}
return super.onTransact(code, data, reply, flags);
}
//调用了Bp端的foo对应会调用Bn端的foo。Bp端的foo()的逻辑是固定的,就是将传过来的参数打包传Bn端。
private static class Proxy implements com.understanding.samples.IMyServer{
......//Proxy类的其他实现
public int foo(java.lang.String str)
throws android.os.RemoteException{
android.os.Parcel _data = android.os.Parcel.obtain();
android.os.Parcel _reply = android.os.Parcel.obtain();
int _result;
try{
......//将参数str写入_data
//mRemot就是指向IMyServer Bn端的BinderProxy;可能会阻塞等待返回结果