这是一块很大的内容,本人知识浅薄,只敢以简洁而称
ipc ,即进程间通信,android中大概有以下几种方法:
1 广播;
2 文件共享;
3 localsocket;
4 Messenger;
5 aidl。
使用方法,
一 广播最为简单,也是android四大组件之一,默认的发送方式就是全局广播,发送出去,在需要的地方注册过滤监听即可,这里不详细说明。
二 文件共享,效率不高,可通过继承FileObserver这个文件监控类来实现文件的监控,这里也不详细说明。
l三 ocalsocket方式,相对于普通的socket,它不需要绑定ip和端口,客户端和服务端之间通过文件来传输(linux一切都是文件),服务端在创建localsocket的时候只要创建文件描述符,客户端绑定即可正常通信。个人以为这种情况下,用于c层和java层的通信,因为c层不具备android的一些封装特性。
Messenger方式和aidl方式:android自家的东西,所以如果两个apk之间比较频繁的通信的话,建议还是用这两个。
四 Messenger方式,先说一下步骤:
(1)服务端创建一个handler;
(2)根据服务端创建的handler创建一个messenger对象;
(3)通过Messenger获得binder对象,通过实现onBinder()把该binder传给客户端;
(4)客户端通过bindservice把该binder对象转化为Messenger(其实就是Messenger的一个实例化),然后就可以使用messenger对象给服务端发送消息了;
(5)服务端使用第一步创建的handler,来一个handleMessage即可;
当然服务端要给客户端回消息也很简单,在客户端发送的时候设置replyto当前类的一个messenger对象,把这个对象发给服务器,然后服务器也拿这个replyto对象send即可实现把消息回传给客户端。
核心思想就是binder通信,就是服务端该怎么想办法把它的binder通过onBinder函数传给客户端,然后客户端肯定就是通过bindService来获取该binder,然后该转就转为相关的操作对象,就可以给服务端发送消息或者调用服务端方法。
五 最后说一下aidl,这个android进程间通信很常用的东西,相比于messenger来说,它是服务端多线程处理客户端的请求的,也就是说,每来一个客户端请求,它都会另起一个线程去处理;而messenger是单线程的,每一个message都会堆放在一个消息队列中,然后挨个出栈执行。
aidl的方式,依旧先说一下步骤:
(1)服务端创建aidl文件(其实客户端也行,只是习惯先弄服务端),里面定义给客户端调用的接口;
(1.1)如果要传输的数据类型不是基础的数据类型,而是对象啥的,要先定义一个bean类,并且序列化,实现Parcelable接口;
(1.2)新建一个aidl文件,引入上面序列化的对象供其他aidl文件使用(注:所有非默认支持的数据类型都得通过一个AIDL定义才能使用);
(1.3)新建第二个aidl文件,用于定义接口,并显式的import上面的bean类;
(2)新建service类,(先把之前的aidl生成java类,rebuild一下),在service类中实现aidl中的接口;
(2.1)怎么实现接口呢?重写xxxx(aidl接口类).stub这个内部超类,这个超类是aidl文件转java文件自动生成的,为啥要重写stub这个超类的,这个是约定的。服务端的代理就是stub,客户端的代理就是proxy,然后就交由这两个代理通信了。
(2.2)service想办法把binder通过onBinder函数抛出去,binder从何而来,刚才实例化stub这个超类得到的。
(2.3)另外,值得注意的是,在service类中要设置intent-filter 的action,不然客户端是找不到该服务的。
(3) 首先把服务端创建的aidl文件和javabean类复制过来,注意包名要一致。
(4)建立ServiceConnect对象,实现里面的onServiceConnected方法和onServiceDisconnected方法,在onServiceConnect方法中通过Stub.asInterface方法把binder对象转为proxy并赋予javabean类,实现客户端对于该javabean类的实例化,往后就可以通过该实例来调用aidl的接口方法。
aidl还要注意的一点就是数据的流向问题,通过设置tag来设置数据的流向,tag分为in,out,inout,这三个tag的意思大概如此:
in:服务端定义数据为in,即数据只能由客户端流向服务端,而服务端流向客户端的为null;
out:服务端定义数据为out,即数据只能有服务端流向客户端,客户端流向流向服务端的为null;
inout:两端可以同时流向。
我们如果去翻看android的源码就会知道,aidl用的场景非常多,所以我们如果在写应用层的时候,当有必要要把一个apk分成两个写的时候,而且要求多线程的去相应,不妨使用aidl的方式。
这里说的aidl还是比较模糊,如果想要再进一步的了解,最简单的方式就是看aidl转过来的java文件,我们会看到它帮我们生成了并且封装了很多用于客户端和服务端用于通信的类。