最近有一段时间没写博客了,打算最近趁着有时间补补,本文是总结的AIDL的基本使用和原理。 分为两个部分:一是简单的上手demo,二是对代码逻辑进行分析。
一:简单的AIDL小Demo: 服务端: 1.新建服务端工程AIDLserver,新建AIDL文件: Android——AIDL基础实现demo以及原理探究_第1张图片
2.打开该文件,编写一个测试方法: Android——AIDL基础实现demo以及原理探究_第2张图片
3.点击build-rebuild进行编译,可以看到生成的java类文件,在最后一行可以看到自己刚才写的测试方法input(): Android——AIDL基础实现demo以及原理探究_第3张图片
4.编写服务端的服务类: Android——AIDL基础实现demo以及原理探究_第4张图片
这里要注意一定要返回Ibinder实例。 5.在Manifest里配置该服务,在Activity中启动服务并运行程序: Android——AIDL基础实现demo以及原理探究_第5张图片
启动服务 Android——AIDL基础实现demo以及原理探究_第6张图片


客户端: 1.新建客户端工程AIDLClient,新建一个module工程mylibrary: Android——AIDL基础实现demo以及原理探究_第7张图片
2.把之前服务端的aidl文件夹复制到客户端相同位置,并rebuild客户端: Android——AIDL基础实现demo以及原理探究_第8张图片
3.在MainActivity中绑定服务端的TESTServer服务,并通过ServiceConnection进行消息回调,在其的onServiceConnected方法中得到IMyAidlInterface的实例。 4.之后创建一个按钮的点击方法,在其中直接调用IMyAidlInterface实例对象发出客户端的信息并直接获得服务端的回调结果。 (3、4完整代码如下): public class MainActivity  extends AppCompatActivity {
    Button  btn_test_aidl ;

    @Override
    protected void  onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState) ;
        setContentView(R.layout. activity_main) ;

        btn_test_aidl = (Button) findViewById(R.id. btn_test_aidl) ;
        //绑定服务
        Intent intent =  new Intent() ;
        intent.setComponent( new ComponentName( "com.example.aidlserver" "com.example.aidlserver.MyService")) ;
        bindService(intent conn BIND_AUTO_CREATE) ;

        btn_test_aidl.setOnClickListener( new View.OnClickListener() {
            @Override
            public void  onClick(View view) {
                try {
                    String rep =  iMyAidlInterface.input( "客户端发出的信息") ;
                    Log. i( "nangua" "从服务端调用成功的结果:" + rep) ;
               catch (Exception e) {
                    e.printStackTrace() ;
                }
            }
        }) ;
    }

    IMyAidlInterface  iMyAidlInterface ;

    /**
     * 服务回调方法
     */
    private ServiceConnection  conn new ServiceConnection() {
        @Override
        public void  onServiceConnected(ComponentName name IBinder service) {
            iMyAidlInterface = IMyAidlInterface.Stub. asInterface(service) ;
        }

        @Override
        public void  onServiceDisconnected(ComponentName name) {
            iMyAidlInterface null;
        }
    } ;

    @Override
    protected void  onDestroy() {
        super.onDestroy() ;
        //解绑服务,回收资源
        unbindService( conn) ;
    }

}

最后,点击客户端测试按钮,查看双端显示的Log:


二.底层实现原理:
围绕着IMyAidlInterface的代码(方便查找):
/* * This file is auto-generated.  DO NOT MODIFY. * Original file: E:\\Android-workspace\\AIDLsample\\AIDLClient\\app\\src\\main\\aidl\\com\\example\\aidlserver\\IMyAidlInterface.aidl */package com.example.aidlserver;// Declare any non-default types here with import statementspublic interface IMyAidlInterface extends android.os.IInterface{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.example.aidlserver.IMyAidlInterface{private static final java.lang.String DESCRIPTOR = "com.example.aidlserver.IMyAidlInterface";/** Construct the stub at attach it to the interface. */public Stub(){this.attachInterface(this, DESCRIPTOR);}/** * Cast an IBinder object into an com.example.aidlserver.IMyAidlInterface interface, * generating a proxy if needed. */public static com.example.aidlserver.IMyAidlInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.example.aidlserver.IMyAidlInterface))) {return ((com.example.aidlserver.IMyAidlInterface)iin);}return new com.example.aidlserver.IMyAidlInterface.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_basicTypes:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();long _arg1;_arg1 = data.readLong();boolean _arg2;_arg2 = (0!=data.readInt());float _arg3;_arg3 = data.readFloat();double _arg4;_arg4 = data.readDouble();java.lang.String _arg5;_arg5 = data.readString();this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);reply.writeNoException();return true;}case TRANSACTION_input:{data.enforceInterface(DESCRIPTOR);java.lang.String _arg0;_arg0 = data.readString();java.lang.String _result = this.input(_arg0);reply.writeNoException();reply.writeString(_result);return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.example.aidlserver.IMyAidlInterface{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;}/**    * 自动生成的方法     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */@Override public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);_data.writeInt(anInt);_data.writeLong(aLong);_data.writeInt(((aBoolean)?(1):(0)));_data.writeFloat(aFloat);_data.writeDouble(aDouble);_data.writeString(aString);mRemote.transact(Stub.TRANSACTION_basicTypes, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}@Override public java.lang.String input(java.lang.String str) 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(str);mRemote.transact(Stub.TRANSACTION_input, _data, _reply, 0);_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}}static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_input = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);}/**    * 自动生成的方法     * Demonstrates some basic types that you can use as parameters     * and return values in AIDL.     */public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, java.lang.String aString) throws android.os.RemoteException;public java.lang.String input(java.lang.String str) throws android.os.RemoteException;}


从客户端开始,一步步说: 1.首先在onCreate方法中,绑定了服务端的TestServer服务:
//绑定服务        Log.d("nangua","客户端onCreate中绑定服务");        Intent intent = new Intent();        intent.setComponent(new ComponentName("com.example.aidlserver", "com.example.aidlserver.TestService"));        bindService(intent, conn, BIND_AUTO_CREATE);
其中我们传入的ServiceConnection为:
    /**     * 服务回调方法     */    private ServiceConnection conn = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            Log.d("nangua","客户端回调获得iMyAidlInterface实例");            iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);        }        @Override        public void onServiceDisconnected(ComponentName name) {            iMyAidlInterface = null;        }    };
在onServiceConnected中,我们调用了IMyAidlInterface实例的Stub内部类的asInterface方法,我们走进该方法:
public static com.example.aidlserver.IMyAidlInterface asInterface(android.os.IBinder obj){if ((obj==null)) {return null;}android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);if (((iin!=null)&&(iin instanceof com.example.aidlserver.IMyAidlInterface))) {return ((com.example.aidlserver.IMyAidlInterface)iin);}return new com.example.aidlserver.IMyAidlInterface.Stub.Proxy(obj);}
可以看到最后一行返回结果是调用了Stub内部类的代理内部类Proxy的构造方法,该方法为:
private android.os.IBinder mRemote;Proxy(android.os.IBinder remote){mRemote = remote;}
可以看到讲传入的远程服务类的IBinder实例保存到了本地,变量名为mRemote(意思是拿到的远程实例). 到此为止,我们可以知道客户端的IMyAidlInterface实例iMyAidlInterface就是该代理类实例mRemote。
然后在我们的点击方法中:
  btn_test_aidl.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View view) {                try {                    Log.d("nangua","点击了");                    String rep = iMyAidlInterface.input("客户端发出的信息");                    Log.d("nangua", "从服务端调用成功的结果:" + rep);                } catch (Exception e) {                    e.printStackTrace();                }            }        });
是调用了该实例的input方法,所以现在看到Proxy代理类的input方法:
@Override public java.lang.String input(java.lang.String str) 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(str);mRemote.transact(Stub.TRANSACTION_input, _data, _reply, 0);_reply.readException();_result = _reply.readString();}finally {_reply.recycle();_data.recycle();}return _result;}
可以看到其中关键的一句:
mRemote.transact(Stub.TRANSACTION_input, _data, _reply, 0);
调用了mRemote实例的transact方法,其中TRANSACTION_input是标志值。 该方法会调用服务端的onTransact方法!
所以此时我们看到服务端IMyAidlInterface实例的代理类Proxy的onTranscat方法:
@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_basicTypes:{data.enforceInterface(DESCRIPTOR);int _arg0;_arg0 = data.readInt();long _arg1;_arg1 = data.readLong();boolean _arg2;_arg2 = (0!=data.readInt());float _arg3;_arg3 = data.readFloat();double _arg4;_arg4 = data.readDouble();java.lang.String _arg5;_arg5 = data.readString();this.basicTypes(_arg0, _arg1, _arg2, _arg3, _arg4, _arg5);reply.writeNoException();return true;}case TRANSACTION_input:{data.enforceInterface(DESCRIPTOR);java.lang.String _arg0;_arg0 = data.readString();java.lang.String _result = this.input(_arg0);reply.writeNoException();reply.writeString(_result);return true;}}return super.onTransact(code, data, reply, flags);}
可以看到在case TRANSACTION_input:的情况下, 会得到客户端传来的数据:
java.lang.String _arg0;_arg0 = data.readString();
然后执行服务端的input方法:
java.lang.String _result = this.input(_arg0);
最后将数据保存:
reply.writeNoException();reply.writeString(_result);
并返回数据:
return super.onTransact(code, data, reply, flags);
onTransact方法走的是底层代码,通过这个方法的实现,可以将服务端的数据回传给客户端。
此时,客户端的执行方法终于收到了回传的参数:
                    String rep = iMyAidlInterface.input("客户端发出的信息");
到此,全过程结束。

总结:
可以看到整个数据交互过程,就是客户端通过绑定服务,得到服务端的Aidl实例mRemote,并通过调用该实例的input方法,并在input方法中最终调用进程间通信的底层方法onTransact,实现数据从客户端到服务端,再到客户端的整个回调。过程虽然比较复杂,但是思路是连贯的。












更多相关文章

  1. android studio 3.x 以上版本的Native JNI/NDK 调用c++/c语言程
  2. Android WebView 不支持 H5 input type="file" 解决方法
  3. 在Android App开发中实现任意Java方法的拦截
  4. 关于Android长按出现复制粘贴栏在顶部占位问题解决方法
  5. Android进程保活方法 --转自腾讯Bugly公众号
  6. Android客户端代码保护技术-完整性校验
  7. win10通过网线连接树莓派和PC方法(Android things)

随机推荐

  1. 浅谈android的selector,背景选择器
  2. android仿今日头条App、多种漂亮加载效果
  3. Android样式基础--shape篇
  4. Android发布, Android中国网站正式成立,
  5. 腾讯面试官:Binder的系统服务是如何获取的
  6. Android(安卓)应用程序基础
  7. Android(安卓)X86
  8. android:layout_gravity和android:gravit
  9. Android应用程序开发实用案例50则
  10. (mac)Android(安卓)Studio安装以及Fetchi