AIDL小结
来源:互联网 发布:应用数据可以删除吗 编辑:程序博客网 时间:2024/06/05 08:26
系统服务依赖的是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端的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;可能会阻塞等待返回结果
mRemot.transact(Stub.TRANSCATION_foo, _data, reply, 0);
......//从_replay中读取返回值_result
} finally{
......
}
return _result;
}
static final int TRANSACTION_foo = (android.os.Ibinder.FIRST_CALL_TRANSCATION + 0);
}
}
//声明IMyServer所提供的接口。
public int foo(java.lang.String str) throws android.os.RemoteException;
}
下面说说AIDL在AS上的操作:(以下demo参考自:http://blog.csdn.net/u011974987/article/details/51243539)
首先在new file 中选择AIDL,会自动生成一个名为“aidl”与java文件夹同级的文件夹,aidl文件就放在该文件夹下。注意包名和java文件一样是文件夹的路径。
// IMyInterface.aidlpackage com.example.zhangjinbiao.aidltest;// Declare any non-default types here with import statementsinterface IMyInterface { String getInfor(String s);}
写一个Service,在Service中返回一个IBinder(就是服务端stub的子类),然后在使用的时候调用asInterface(IBinder)转为IMyInterface(IInterface),该方法最终会返回一个Proxy。所以客户端最终使用的是Proxy。
下面是客户进程代码:
public class MainActivity extends AppCompatActivity { public final static String TAG = "AIDLTEST_MainActivity"; private IMyInterface myInterface; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { myInterface = IMyInterface.Stub.asInterface(service); Log.i(TAG, "连接Service 成功"); try { String s = myInterface.getInfor("我是Activity传来的字符串"); Log.i(TAG, "从Service得到的字符串:" + s); } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { Log.e(TAG, "连接Service失败"); } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); startAndBindService(); } private void startAndBindService() { Intent service = new Intent(MainActivity.this, MyService.class); //startService(service); bindService(service, serviceConnection, Context.BIND_AUTO_CREATE); }}
下面是服务端进程代码:
public class MyService extends Service { public final static String TAG = "AIDLTEST_MyService"; private IBinder binder = new IMyInterface.Stub() { @Override public String getInfor(String s) throws RemoteException { Log.i(TAG, s); return "我是 Service 返回的字符串"; } }; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreat"); } @Override public IBinder onBind(Intent intent) { return binder; }}
需要在Manifest中声明:
<service android:name=".MyService" android:process="com.xu.remote" />声明该Service在独立进程中。
下面是自动生成的IMyInterface.java文件:
/* * This file is auto-generated. DO NOT MODIFY. * Original file: /home/zhangjinbiao/AndroidStudioProject/AIDLTest/app/src/main/aidl/com/example/zhangjinbiao/aidltest/IMyInterface.aidl */package com.example.zhangjinbiao.aidltest;// Declare any non-default types here with import statementspublic interface IMyInterface extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.example.zhangjinbiao.aidltest.IMyInterface{private static final java.lang.String DESCRIPTOR = "com.example.zhangjinbiao.aidltest.IMyInterface";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.example.zhangjinbiao.aidltest.IMyInterface interface, * generating a proxy if needed. */public static com.example.zhangjinbiao.aidltest.IMyInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.example.zhangjinbiao.aidltest.IMyInterface))) {return ((com.example.zhangjinbiao.aidltest.IMyInterface)iin);}return new com.example.zhangjinbiao.aidltest.IMyInterface.Stub.Proxy(obj);}@Override public android.os.IBinder asBinder(){return this;}@Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{switch (code){case INTERFACE_TRANSACTION:{reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_getInfor:{data.enforceInterface(DESCRIPTOR);java.lang.String _arg0;_arg0 = data.readString();java.lang.String _result = this.getInfor(_arg0);reply.writeNoException();reply.writeString(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.example.zhangjinbiao.aidltest.IMyInterface{private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}@Override public android.os.IBinder asBinder(){return mRemote;}public java.lang.String getInterfaceDescriptor(){return DESCRIPTOR;}@Override public java.lang.String getInfor(java.lang.String s) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();java.lang.String _result;try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeString(s);mRemote.transact(Stub.TRANSACTION_getInfor, _data, _reply, 0);_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_getInfor = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}public java.lang.String getInfor(java.lang.String s) throws android.os.RemoteException;}
注意:AIDL一般是阻塞式调用,就像调用一般方法一样,要非阻塞调用需要设置IBinder接口类中打FLAY_ONEWAY字段.,在native曾中涉及到Binder调用打基本是阻塞式,而java framework层一般非阻塞式的.
- aidl小结
- AIDL小结
- android AIDL 小结
- android AIDL 小结
- android AIDL 小结
- android AIDL 小结
- AIDL 学习小结
- AIDL使用小结
- Android之——AIDL小结
- AIDL之Android开发艺术探索小结
- AIDL
- aidl
- AIDL
- AIDL
- AIDL
- AIDL
- AIDL
- aidl
- UVA-804 模拟
- 消息队列----RabbitMQ基础概念详细介绍
- 把keilC51中不使用的代码禁止分配空间,为程序瘦身!
- sql索引语法
- DOM事件探秘
- AIDL小结
- C语言scanf函数详细解释
- 记简单的输入框输入密码
- [041]一个简单的Makefile教程
- Linux下使用samba服务器实现
- 系统时间、星期、年月日
- maven相关
- 静下心来写点东西
- 《JS高程(3)》DOM节点层次Document类型-第10章笔记(12)