当前位置: 首页 > news >正文

Android AIDL跨进程通信

aidl跨进程通信的步骤:
1、创建aidl文件。
2、build后生成aidl对应的java文件。
3、创建服务端Service。
4、创建客户端Activity,bindService(),获取IBinder的proxy 。

一、创建aidl文件

// IImoocAIDL.aidl
package com.mecury.aidltest;
// Declare any non-default types here with import statements
interface IImoocAIDL {    
    //计算num1 + num2    
    int add(int num1,int num2);
}

二、build后生成对应的interface类:

aidl生成的对应的interface类 IImoocAIDL 中,有两个继承自IImoocAIDL的类:
抽象类 stub 和 实际类 Proxy。

Proxy运行在客户端,当客户端远程调用此方法时,其内部实现是这样的:

1、客户端调用 proxy. add(int num1, int num2) 时,add方法内会调用transact方法;
2、transact方法会发起RPC请求,同时当前线程挂起;
3、然后服务端中的stub类中的onTransact方法会被调用;
4、直到RPC过程结束,被挂起的线程继续执行,并从_reply中取出RPC返回的结果。

在这里插入图片描述

/*
 * This file is auto-generated.  DO NOT MODIFY.
 * Original file: F:\\AS for android\\AIDLTest\\aidlclient\\src\\main\\aidl\\com\\mecury\\aidltest\\IImoocAIDL.aidl
 */
package com.mecury.aidltest;
// Declare any non-default types here with import statements

public interface IImoocAIDL extends android.os.IInterface {
    /**
     * Local-side IPC implementation stub class.
     */
    public static abstract class Stub extends android.os.Binder implements com.mecury.aidltest.IImoocAIDL {
        private static final java.lang.String DESCRIPTOR = "com.mecury.aidltest.IImoocAIDL"; //Binder的唯一标识

        /**
         * Construct the stub at attach it to the interface.
         */
        public Stub() {
            this.attachInterface(this, DESCRIPTOR);
        }

        /**
         * Cast an IBinder object into an com.mecury.aidltest.IImoocAIDL interface,
         * generating a proxy if needed.
         */
        //将服务端的Binder对象转换成客户需要的AIDL对象,转换区分进程,客户端服务端位于同一进程,返回服务端的
        //Stub对象本身;否则返回的是系统的封装后的Stub.proxy对象。
        public static com.mecury.aidltest.IImoocAIDL asInterface(android.os.IBinder obj) {
            if ((obj == null)) {
                return null;
            }
            android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
            if (((iin != null) && (iin instanceof com.mecury.aidltest.IImoocAIDL))) {
                return ((com.mecury.aidltest.IImoocAIDL) iin);
            }
            return new com.mecury.aidltest.IImoocAIDL.Stub.Proxy(obj);
        }
        //返回当前Binder对象
        @Override
        public android.os.IBinder asBinder() {
            return this;
        }

        //运行在服务端的Binder线程池中
        @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_add: {
                    data.enforceInterface(DESCRIPTOR);
                    //读取客户端传递过来再data中存储的方法的参数
                    int _arg0;
                    _arg0 = data.readInt();
                    int _arg1;
                    _arg1 = data.readInt();
                    //调用方法
                    int _result = this.add(_arg0, _arg1);
                    //将计算结果写入reply中
                    reply.writeNoException();
                    reply.writeInt(_result);
                    return true;
                }
            }
            return super.onTransact(code, data, reply, flags); //向Transact传递数据
        }
        
        //代理类,运行在客户端
        private static class Proxy implements com.mecury.aidltest.IImoocAIDL {
            private android.os.IBinder mRemote; //声明一个IBinder对象

            Proxy(android.os.IBinder remote) {
                mRemote = remote;
            }
            //返回当前Binder对象
            @Override
            public android.os.IBinder asBinder() {
                return mRemote;
            } 

            public java.lang.String getInterfaceDescriptor() {
                return DESCRIPTOR;
            }
            
            //客户端调用此方法,传递进来num1和num2两个参数,
            @Override
            public int add(int num1, int num2) throws android.os.RemoteException {
                android.os.Parcel _data = android.os.Parcel.obtain();
                android.os.Parcel _reply = android.os.Parcel.obtain();
                int _result;
                try {
                    //向_data中写入参数
                    _data.writeInterfaceToken(DESCRIPTOR);
                    _data.writeInt(num1);
                    _data.writeInt(num2);
                    //通过transact方法向服务端传递参数,并调用了方法,返回的结果写入_reply中
                    mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);
                    _reply.readException();
                    _result = _reply.readInt();
                } finally {
                    _reply.recycle();
                    _data.recycle();
                }
                return _result;
            }
        }
        //标识位
        static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
    }
    
    //计算num1 + num2
    public int add(int num1, int num2) throws android.os.RemoteException;
}

三、创建服务端Service

在服务端Service中创建继承于IImoocAIDL.Stub的IBinder类:

public class IRemoteService extends Service {

    //客户端绑定service时会执行
    @Override
    public IBinder onBind(Intent intent) {
        return iBinder;
    }

    private IBinder iBinder = new IImoocAIDL.Stub(){

        @Override
        public int add(int num1, int num2) throws RemoteException {
            Log.e("TAG","收到了来自客户端的请求" + num1 + "+" + num2 );
            return num1 + num2;
        }
    };
}

同时,在AndroidManifest.xml中注册该Service,并定义其所在的进程remote:

<service android:name=".IRemoteService"
         android:process=":remote"
         android:exported="true">
         <intent-filter>
            <action android:name="com.mecury.aidltest.IRomoteService"/>
         </intent-filter>
</service>

四、创建客户端Activity,bindService(),获取IBinder的proxy

MainActivity: 这里onServiceConnected中返回的iBinder, 经过IImoocAIDL.Stub.asInterface(service)后返回的是Stub的proxy。

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    private Button button;
    private IImoocAIDL iImoocAIDL;

    private ServiceConnection conn = new ServiceConnection() {

        //绑定服务,回调onBind()方法
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            iImoocAIDL = IImoocAIDL.Stub.asInterface(service);
        }

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

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

        bindService();
        initView();

    }

    private void initView() {
        button = (Button) findViewById(R.id.button);
        button.setOnClickListener(this);
    }


    @Override
    public void onClick(View v) {
        try {
            int res = iImoocAIDL.add(1, 2);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    private void bindService() {
        Intent intent = new Intent();
        //绑定服务端的service
        intent.setAction("com.mecury.aidltest.IRomoteService");
        //新版本(5.0后)必须显式intent启动 绑定服务
        intent.setComponent(new ComponentName("com.mecury.aidltest","com.mecury.aidltest.IRemoteService"));
        //绑定的时候服务端自动创建
        bindService(intent, conn, Context.BIND_AUTO_CREATE);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unbindService(conn);
    }
}

总结:

进程间通信的关键:不是Service, 而是APDL中 IBinder 的实现类stub 和 Proxy,真正实现进程间通信 是通过 transact方法 和 onTransact方法。

相关文章:

  • Java大牛必会|分布式缓存实现方案之Spring Cache
  • KF、EKF、IEKF、UKF卡尔曼滤波器
  • Neo4j入门+深入
  • 21年icpc上海区域赛B题Strange Permutations (容斥+生成函数)
  • 【CSS】QQ邮箱布局,词典四列布局,行内布局
  • 滑动窗口问题
  • Java的输入 Scanner in=new Scanner(System.in);
  • 接口请求返回状态码
  • Cocos Creator游戏引擎
  • [静态时序分析简明教程(一)] 绪论
  • ADU87、DCB20X-E等设备以RTSP方式添加第三方相机或录像机教程
  • 计算机网络常见面试题汇总(建议收藏)
  • 【从零带你玩转Linux】Linux环境搭建
  • AMBA总线相关知识记录
  • vscode快速安装教程
  • httpie使用详解
  • JAVA SE 6 GC调优笔记
  • Material Design
  • nginx 配置多 域名 + 多 https
  • node学习系列之简单文件上传
  • Perseus-BERT——业内性能极致优化的BERT训练方案
  • php中curl和soap方式请求服务超时问题
  • vue中实现单选
  • 批量截取pdf文件
  • 深度学习中的信息论知识详解
  • 线性表及其算法(java实现)
  • ​水经微图Web1.5.0版即将上线
  • # 睡眠3秒_床上这样睡觉的人,睡眠质量多半不好
  • #Linux(make工具和makefile文件以及makefile语法)
  • #数学建模# 线性规划问题的Matlab求解
  • #中国IT界的第一本漂流日记 传递IT正能量# 【分享得“IT漂友”勋章】
  • $ git push -u origin master 推送到远程库出错
  • $forceUpdate()函数
  • (1)STL算法之遍历容器
  • (4)通过调用hadoop的java api实现本地文件上传到hadoop文件系统上
  • (70min)字节暑假实习二面(已挂)
  • (AngularJS)Angular 控制器之间通信初探
  • (MonoGame从入门到放弃-1) MonoGame环境搭建
  • (二)丶RabbitMQ的六大核心
  • (免费分享)基于springboot,vue疗养中心管理系统
  • (七)理解angular中的module和injector,即依赖注入
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (算法设计与分析)第一章算法概述-习题
  • (转)全文检索技术学习(三)——Lucene支持中文分词
  • ***测试-HTTP方法
  • ***汇编语言 实验16 编写包含多个功能子程序的中断例程
  • 、写入Shellcode到注册表上线
  • .apk 成为历史!
  • .h头文件 .lib动态链接库文件 .dll 动态链接库
  • .NET Core 2.1路线图
  • .NET Core 通过 Ef Core 操作 Mysql
  • .net core使用ef 6
  • .NET精简框架的“无法找到资源程序集”异常释疑
  • @ModelAttribute使用详解
  • @property python知乎_Python3基础之:property