AIDL、Binder、进程间通信方法

本文介绍了Android中AIDL的工作原理及其在进程间通信中的应用,包括如何编写AIDL文件来实现服务端与客户端间的通信,自定义对象的传递方法,以及与Binder和Messenger的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

AIDL:

AIDL可以作为客户端服务端连接,也可以访问系统里未对外暴露的api(比如挂断电话)

原理如下:

 

编写AIDL文件需注意以下几点:

 

实现进程通信:

 

AIDL默认支持传递基本类型,如要自定义传递类型:

 

 

AIDL中所指的服务端和客户端(访问者)之间的通信指的是两个应用之间的通信,并不是web中的Service和Client的通信。

当使用AIDL进行两个应用通信时,两边都需要使用相同的AIDL文件(通信规则文件)编译器会自动生成通信所需要的代码,只需要引用自动生成的代码进行通信即可。

如以下AIDL文件:

//aidl文件
interface StudentQuery {
    String queryStudent(int number);
}

会在gen目录下自动生成(AndroidStudio切换到Packages结构)StudentQuery.java的接口文件,如下:

public interface StudentQuery extends android.os.IInterface
{
/** Local-side IPC implementation stub class. */
public static abstract class Stub extends android.os.Binder implements StudentQuery
{

这样服务端定义的继承Service的类(Service在Manifest的注册最好使用隐式意图)中即可使用编译器自动生成通信类返回IBinder的代理对象给客户端,如下:

public class SutdentQueryService extends Service{
    private String[] names = {"aaa","bbb"};
    private IBinder binder = new StudentQueryBinder();
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }
    private String query(int number){
        return names[number-1];
    }
    private final class StudentQueryBinder extends StudentQuery.Stub {
        @Override
        public String queryStudent(int number) throws RemoteException {
            return query(number);

服务端返回IBinder代理对象,在客户端先用Intent去bindServier连接服务然后继承ServiceConnection再转换成使用AIDL文件的编译器自动生成的通信类的接口类型,然后便可调用服务端中的方法queryStudent(int number),如下:

Intent intent = new Intent("cn.student.query");
bindService(intent,studentConnection,BIND_AUTO_CREATE);
private final class StudentConnection implements ServiceConnection {
    @Override
    public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
        studentQuery = StudentQuery.Stub.asInterface(iBinder);

 

try {
    studentQuery.queryStudent(i);
} catch (RemoteException e) {

其实就是服务端暴露接口给访问者,两者通过Service和AIDL规则建立连接(连接通过IBinder代理对象),访问者调用服务端的方法。

如果需要传递自定义对象则自定义javabean实现Parcelable接口。

Serializable和Parcelable区别:

在于存储媒介的不同。Serializable使用IO读写存储在硬盘上。序列化过程使用了反射技术,并且期间产生临时对象。Parcelable是直接在内存中读写,内存的读写速度肯定优于硬盘读写速度,所以Parcelable序列化方式性能上要优于Serializable方式很多。

==============================================================================

Binder:

Binder工作在Linux层面,属于一个驱动,客户端程序调用Binder是通过系统调用完成的。

Binder是一种架构,这种架构提供了服务端接口、Binder驱动、客户端接口三个模块。

Binder实现了IBinder接口,是ServiceManager连接各种Manager(如WindowManager、ActivityManager等)的桥梁。
Binder包含四个部分:服务端(Server),客户端(Client),Binder驱动,ServiceManager,运作过程是:
  1. 服务端创建对应Binder实例对象,然后开启隐藏Binder线程,接收来自客户端的请求,同时,将自身的Binder注册到Service Manager,在Binder驱动创建mRemote对象。 
  2. 客户端想和服务端通信,通过Service Manager查找到服务端的Binder,然后Binder驱动将对应的mRemote对象返回 
  3. 至此,整个通信连接建立完毕

==============================================================================

Messenger:

通过Messenger可以在不同进程传递Message对象,在Message中放入需要传递数据即可。
Messenger是轻量级IPC方案,底层实现是AIDL。
服务端:创建Service和Handler并通过Handler创建Messenger对象,然后在Service的onBind()中返回Binder即可。
客户端:绑定服务端的Service后返回IBinder对象创建一个Messenger,通过这个Messenger就可向服务端发消息类型为Message。如需服务端回应客户端,客户端需创建Handler并创建一个新的Messenger把他通过Message的replyTo参数传给服务端,服务端通过replyTo参数即可回应。

 

进程、进程间通信:

一般情况下,一个应用程序就是一个进程,这个进程名称就是应用程序包名。我们知道进程是系统分配资源和调度的基本单位,所以每个进程都有自己独立的资源和内存空间,别的进程是不能任意访问其他进程的内存和资源的。

 
进程间通信4种方法:

对应4大组件Activity(Intent)、Content Provider(以Cursor对象返回)、Broadcast(sendBroadcast)和Service(用AIDL Service实现跨进程通信)。

 

保证进程不被杀死的方法:

1.Service设置成START_STICKY,kill后会被重启(等待5秒左右),重传Intent,保持与重启前一样
2.通过startForeground将进程设置为前台进程,做前台服务,优先级和前台应用一个级别除非内存非常紧缺,否则不会被kill
3.双进程Service:让2个进程互相保护,其中一个Service被清理后,另外没被清理的进程可以立即重启进程
4.QQ黑科技:在应用退到后台后,另起一个只有 1 像素的页面停留在桌面上,让自己保持前台状态,保护自己不被后台清理工具杀死
5.在已经root的设备下,修改相应的权限文件,将App伪装成系统级的应用(Android4.0系列的一个漏洞,已经确认可行)

 

并行与并发:

并发的关键是处理多个任务,不一定要同时。并行的关键是同时处理多个任务。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值