AIDL(Android接口描述语言)

aidl是 Android Interface definition language的缩写,一看就明白,它是一种android内部进程通信接口的描述语言,通过它我们可以定义进程间的通信接口。AIDL的作用是让你可以在自己的APP里绑定一个其他 进程 的service。这里希望大家明白一点(Android中的Service和其调 用者既可以在同一个App中,也可以在不同的App)

AIDL用法

声明 :我在这里用AS创建项目可能和ES有点流程上的区别,相对而言AS更简单了。

在这里我们先用两个应用间跨进程通信借以说明。创建一个服务端AIDLServerTest,创建一个客户端AIDLTest。

  • AIDLServerTest
    首先我们在服务端中创建一个Calculate.aidl文件。具体方法如下:


    Android《第三章:AIDL与Messenger》_第1张图片 image.png

    创建完成后我们给这个计算器(Calculate.aidl)添加加、减、乘、除的方法代码如下:

package com.bsoft.aidlservertest;// Declare any non-default types here with import statementsinterface Calculate {    float addition(float arg1,float arg2);    float subtraction(float arg1,float arg2);    float multiplication(float arg1,float arg2);    float division(float arg1,float arg2);}

这些做完之后我们需要手动构建下项目这是AS和ES有区别的地方,不会自动重构“Build----->Make Project”。
紧接着我们创建一个Service来提供我们的这些操作供外部应用使用,代码如下:

/** * Created by 泅渡者 * Created on 2017/9/22. */public class CalculateUtils extends Service {    Binder mBinder = new  Calculate.Stub(){        @Override        public float addition(float arg1, float arg2) throws RemoteException {            KLog.d("计算中");            return arg1+arg2;        }        @Override        public float subtraction(float arg1, float arg2) throws RemoteException {            KLog.d("计算中");            return arg1-arg2;        }        @Override        public float multiplication(float arg1, float arg2) throws RemoteException {            KLog.d("计算中");            return arg1*arg2;        }        @Override        public float division(float arg1, float arg2) throws RemoteException {            KLog.d("计算中");            return arg1/arg2;        }    };    @Override    public void onCreate() {        super.onCreate();        KLog.d("被执行");    }    @Override    public int onStartCommand(Intent intent, int flags, int startId) {        KLog.d("被执行");        return super.onStartCommand(intent, flags, startId);    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        KLog.d("被执行");        return mBinder;    }    @Override    public boolean onUnbind(Intent intent) {        KLog.d("被执行");        return super.onUnbind(intent);    }}
  • 这里我只是演示Service的使用,并没有做详细的处理。

做完这些我们的服务端就以经完成了,但别忘了注册(这里我对Service又起了 一个进程,主要是防止因方法操作时间过长而造成服务端的ANR)

                                                                
  • AIDLTest
    首先我们需要将服务端中的AIDL文件拷贝导当前项目目录:
    如下:
Android《第三章:AIDL与Messenger》_第2张图片 image.png

接着我们来看看怎么调用到另一个APP的中的工具呢?
代码如下

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private EditText edt_arg1, edt_arg2;    private TextView tv_solution;    private Button btn_submit;    private Calculate mService;    private ServiceConnection mConnection = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            mService = Calculate.Stub.asInterface(service);        }        @Override        public void onServiceDisconnected(ComponentName name) {            mService = null;        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        edt_arg1 = (EditText) findViewById(R.id.edt_arg1);        edt_arg2 = (EditText) findViewById(R.id.edt_arg2);        btn_submit = (Button) findViewById(R.id.btn_submit);        tv_solution = (TextView) findViewById(R.id.tv_solution);        btn_submit.setOnClickListener(this);        Intent intent = new Intent();        intent.setAction("com.bsoft.aidlservertest.CalculateUtils");        intent.setPackage("com.bsoft.aidlservertest");        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);    }    @Override    public void onClick(View v) {        switch (v.getId()) {            case R.id.btn_submit:                float arg1 = Float.parseFloat(edt_arg1.getText().toString());                float arg2 = Float.parseFloat(edt_arg2.getText().toString());                float solution;                try {                    solution = mService.multiplication(arg1, arg2);                    tv_solution.setText(solution + "");                } catch (RemoteException e) {                    e.printStackTrace();                }                break;        }    }    @Override    protected void onDestroy() {        super.onDestroy();        if (mConnection != null) {            unbindService(mConnection);        }    }}

注:如果提示说你的AIDL找不到,说明你的包路径不对。
我们来看下(先启动服务端,在启动客户端)客户端运行结果:

Android《第三章:AIDL与Messenger》_第3张图片 image.png
/com.bsoft.aidlservertest:remote D/CalculateUtils.java: [ (CalculateUtils.java:49)#onCreate ] 被执行/com.bsoft.aidlservertest:remote D/CalculateUtils.java: [ (CalculateUtils.java:62)#onBind ] 被执行/com.bsoft.aidlservertest:remote D/CalculateUtils.java: [ (CalculateUtils.java:35)#multiplication ] 计算中/com.bsoft.aidlservertest:remote D/CalculateUtils.java: [ (CalculateUtils.java:68)#onUnbind ] 被执行

这里并不是服务端APP的进程而是Service的指定进程
“com.bsoft.aidlservertest:remote”,说明我们的客户端已经成功链接到服务端并进行了运算操作。
并且当onUnbind执行时将服务端的Service进行了销毁操作。

Messenger基于消息的进程间通信

Messenger:允许实现基于消息的进程间通信的方式。
说白了也是用来提供跨进程通信的东东,但是不用我们去编写AIDL。
我们先用图来理解下它运行的过程:

Android《第三章:AIDL与Messenger》_第4张图片 image.png

好的我们来创建这个实例项目:

  • 服务端MessengerService代码如下
/** * Created by 泅渡者 * Created on 2017/9/22. */public class MessengerService extends Service {    private static final int FLAG = 0x110;    private Messenger messenger = new Messenger(new Handler() {        @Override        public void handleMessage(Message msgfromClient) {            Message messageToClient = Message.obtain(msgfromClient);            switch (msgfromClient.what) {                case FLAG:                    KLog.d("服务端接收导数据"+msgfromClient.arg1+"&&"+msgfromClient.arg2);                    messageToClient.what = FLAG;                    try {                        //模拟耗时                        Thread.sleep(2000);                        messageToClient.arg2 = msgfromClient.arg1 + msgfromClient.arg2;                        msgfromClient.replyTo.send(messageToClient);                    } catch (InterruptedException e) {                        e.printStackTrace();                    } catch (RemoteException e) {                        e.printStackTrace();                    }                    break;            }        }    });    @Override    public void onCreate() {        super.onCreate();        KLog.d("执行");    }    @Nullable    @Override    public IBinder onBind(Intent intent) {        KLog.d("执行");        return messenger.getBinder();    }}
                                                                        

这样我们的服务端就已经创建完毕(我们设置服务是隐式自启动,不用再去手动启动服务)

  • 客户端
public class MainActivity extends AppCompatActivity {    private static final int FLAG = 0x110;    private Messenger mService;    private boolean isConn = false;    private TextView tv_test;    private Button btn_test;    /**     * 客户端Messenger     */    private Messenger messenger = new Messenger(new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case FLAG:                    KLog.d("客户端收到服务端处理的结果:"+msg.arg2);                    tv_test.setText("20+10="+msg.arg2);                    break;            }        }    });    /**     * 连接服务端 Messenger     */    private ServiceConnection mConnect = new ServiceConnection() {        @Override        public void onServiceConnected(ComponentName name, IBinder service) {            mService = new Messenger(service);            isConn = true;            KLog.d("链接服务端成功");        }        @Override        public void onServiceDisconnected(ComponentName name) {            mService = null;            isConn = false;            KLog.d("链接服务端失败");        }    };    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        ServiceInvoked();        tv_test = (TextView) findViewById(R.id.tv_test);        btn_test = (Button) findViewById(R.id.btn_test);        btn_test.setOnClickListener(new View.OnClickListener() {            @Override            public void onClick(View v) {                Message msgFromClient = Message.obtain(null, FLAG, 20, 10);                msgFromClient.replyTo = messenger;                if (isConn) {                    //往服务端发送消息                    try {                        KLog.d("给服务端发送数据:"+msgFromClient.arg1+"&&"+msgFromClient.arg2);                        mService.send(msgFromClient);                    } catch (RemoteException e) {                        e.printStackTrace();                    }                }            }        });    }    private void ServiceInvoked() {        final Intent intent = new Intent();        intent.setAction("com.bsoft.messengerserver");        intent.setPackage("com.bsoft.messengerserver");        bindService(intent, mConnect, Service.BIND_AUTO_CREATE);    }    @Override    protected void onDestroy() {        super.onDestroy();        unbindService(mConnect);    }}

我们接下来看看运行结果:(首先启动服务端,再切掉,然后启动客户端)

  • 客户端日志及结果
D/MainActivity.java: [ (MainActivity.java:52)#onServiceConnected ] 链接服务端成功D/MainActivity.java: [ (MainActivity.java:79)#onClick ] 给服务端发送数据:20&&10D/MainActivity.java: [ (MainActivity.java:37)#handleMessage ] 客户端收到服务端处理的结果:30
  • 服务端日志
D/MessengerService.java: [ (MessengerService.java:49)#onCreate ] 执行D/MessengerService.java: [ (MessengerService.java:55)#onBind ] 执行D/MessengerService.java: [ (MessengerService.java:29)#handleMessage ] 服务端接收导数据20&&10

上面就是我们客户端跟服务端的通信,如果喜欢研究的话大可以去看看所谓的Messenger 只不过是对AIDL的封装而已。
这里如果我们需要通信的数据涉及对象时需要进行序列化。

更多相关文章

  1. 浅谈Android系统进程间通信(IPC)机制Binder中的Server和Client获得
  2. Android 新闻客户端案例
  3. Android ActivityManagerService(AMS)的进程管理
  4. android弹出抉择对话框-仿某团购网android客户端栏目选择
  5. android 启动默认的邮件客户端,多附件的问题
  6. 服务器端返回给客户端的数据格式
  7. [Android] [ Android启动流程 ] [ 下 ] [ Zygote、SystemServer
  8. 【Android 性能优化】应用启动优化 ( 安卓应用启动分析 | Launch

随机推荐

  1. Android开发学习---使用Intelij idea 13.
  2. android画图——Path()的使用
  3. 坑爹的android碎片化
  4. Android 中自定义View(二)
  5. linux mint 17编译android 2.3.1错误记录
  6. android 相对布局属性说明
  7. Android解惑
  8. Android LinearLayout 嵌套 button 监听L
  9. 【Android应用】【Shape使用总结】
  10. 如何调用Android隐藏API