从Android的aidl调用说起(一)
来源:互联网 发布:北京 职称评审知乎 编辑:程序博客网 时间:2024/05/22 08:05
aidl是提供给Android进程通信的工具。一个进程要跟另外一个进程通信正式因为有了aidl变得简单。
首先,我们看一下利用aidl进程调用的例子:
server:
1、aidl定义接口
package com.lbeing.service;
interface INetwork{String send(String url);}2、实现接口
public class NetworkServiceImpl extends INetwork.Stub {private static final String TAG = "NetworkServiceImpl";@Overridepublic String send(String url) {new Thread(new Runnable() {@Overridepublic void run() {throw new NullPointerException();}},"NetworkServiceImpl").start();String ret="RequestTime:"+System.currentTimeMillis()+"url:"+url;return ret;}}
3、通过service实现远程服务
public class NetworkService extends Service {@Overridepublic IBinder onBind(Intent intent) {return stub;}INetwork.Stub stub = new NetworkServiceImpl();}4、manifest文件中声明服务
这样Service端建好了。
Client端
1、拷入刚才建立的aidl文件
2、bindService
Intent intent = new Intent("android.intent.action.AIDLService");bindService(intent, conn, Context.BIND_AUTO_CREATE);
其中conn对象中实现onServiceConnected方法
private ServiceConnection conn = new ServiceConnection() {@Overridepublic void onServiceDisconnected(ComponentName name) {}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {network = INetwork.Stub.asInterface(service);}};3、调用接口
network.send("http://www.baidu.com");
这样远程调用成功。但是AIDL是个什么东西,做了什么事情呢?我们看一下gen下生成的Inetwork.java文件
public interface INetwork extends android.os.IInterface {/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implementscom.lbeing.service.INetwork {private static final java.lang.String DESCRIPTOR = "com.lbeing.service.INetwork";private static final String TAG = "Stub";/** Construct the stub at attach it to the interface. */public Stub() {this.attachInterface(this, DESCRIPTOR);long pid =Process.myPid();//Log.d(TAG, "[Stub]"+pid);}/** * Cast an IBinder object into an com.lbeing.service.INetwork interface, * generating a proxy if needed. */public static com.lbeing.service.INetwork asInterface(android.os.IBinder obj) {long pid =Process.myPid();//Log.d(TAG, "[asInterface]:"+pid);if ((obj == null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin != null) && (iin instanceof com.lbeing.service.INetwork))) {return ((com.lbeing.service.INetwork) iin);}return new com.lbeing.service.INetwork.Stub.Proxy(obj);}@Overridepublic android.os.IBinder asBinder() {long pid =Process.myPid();//Log.d(TAG, "[asBinder]:"+pid);return this;}@Overridepublic boolean onTransact(int code, android.os.Parcel data,android.os.Parcel reply, int flags)throws android.os.RemoteException {long pid =Process.myPid();//Log.d(TAG, "[onTransact]:"+pid);switch (code) {case INTERFACE_TRANSACTION: {reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_send: {data.enforceInterface(DESCRIPTOR);java.lang.String _arg0;_arg0 = data.readString();java.lang.String _result = this.send(_arg0);reply.writeNoException();reply.writeString(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.lbeing.service.INetwork {private android.os.IBinder mRemote;private String TAG ="Proxy";long pid =Process.myPid();Proxy(android.os.IBinder remote) {mRemote = remote;//Log.i(TAG, "[Proxy]:"+pid);}@Overridepublic android.os.IBinder asBinder() {//Log.i(TAG, "[asBinder]:"+pid);return mRemote;}public java.lang.String getInterfaceDescriptor() {//Log.i(TAG, "[getInterfaceDescriptor]");return DESCRIPTOR;}@Overridepublic java.lang.String send(java.lang.String url)throws android.os.RemoteException {//Log.i(TAG, "[send]:"+pid);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(url);mRemote.transact(Stub.TRANSACTION_send, _data, _reply, 0);_reply.readException();_result = _reply.readString();} finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_send = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);}public java.lang.String send(java.lang.String url)throws android.os.RemoteException;}这一个生成的文件中一共有三个类,INetwork、Stub、Proxy这三个作用是什么呢?
类图关系如下:
通过Inetwork.aidl生成了INetwork.java.该接口类定义了Stub的内部虚类,Stub类中定义了一个Proxy内部类。看着是比较头疼。所以在上图中把他们分开了。
他们是怎么调用的呢?首先client端通过proxy对象调用方法。通过binder.transact()调用远程方法,远程方法即Stub的实现类,会触发onTransact()方法。那么他们怎么知道调用了那个方法,参数和结果是怎么传递的呢。要回答这个问题,还是要从生成代码入手。
因为Client和Server端,都是有Adt插件生成,保证了双方生成代码一致性
看proxy的send方法实现。
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(url);mRemote.transact(Stub.TRANSACTION_send, _data, _reply, 0);_reply.readException();_result = _reply.readString();} finally {_reply.recycle();_data.recycle();}return _result;1、首先把参数序列号
2、调用transact方法
3、读取结果。
远程怎么知道调用那个方法的呢,这个是有transact的第一个参数保证确定,因为Client/Server代码一致,通过约定(ADT)生成代码保证。
调用方法问题解决了,那参数和结果是怎么传递的呢?答案同样是约定。
入参是:向Parcel对象中写入String数据,远程获取数据后,首先从Parcel获取String数据,作为send如参,调用成功后,把返回值写入Parcel中,
这样远程调用就完成了。
说了这么多,是不是aidl了解比较清楚了呢,那你知道Client怎么获取到proxy对象的吗?
可能有人会说,不就是通过bindService中获取的嘛,那么bindService又做了什么事情呢?下次再接着说
- 从Android的aidl调用说起(一)
- android aidl的调用
- 一、一切从指数的扩展说起
- 从setcontentView说起----Android的Windows
- Android 从MVP说起
- Android自定义工具栏(一)——从ActionBar说起
- Android关于创建AIDL以及调用AIDL的问题
- 从一本书说起
- 指针的本质(一) 从CPU的位数说起
- 从动态网页的本质说起(一)
- Android远程服务一:android AIDL远程服务调用
- android中的跨进程通信的实现(一)——远程调用过程和aidl
- android中的跨进程通信的实现(一)——远程调用过程和aidl
- android中的跨进程通信的实现(一)——远程调用过程和aidl
- Android中的跨进程通信的实现(一)——远程调用过程和aidl
- Android AIDL远程调用
- Android AIDL远程调用
- Android AIDL远程调用
- Perl 十条基本的开发实践
- 用SQL做数学题
- leetcode第一刷_ First Missing Positive
- 一个无奈的事实是,与恒大首回合表现平庸的樱花球员
- JFrame 组件添加或者删除后,如何更新窗口
- 从Android的aidl调用说起(一)
- 实时监控运行中java程序工具:btrace
- Java线程计数器CyclicBarrier和CountDownLatch的使用
- Service的远程调用
- 热血传奇Tile地图绘制方法分析及平滑绘制分析
- oracle 下WITH CHECK OPTION用法
- 生活的乐趣
- Servlet @Autowired Spring Bean 的方法 .
- 利用任务计划自动删除指定日期的SQLServer备份文件