aidl(Android Interface Definition Language) 进程间通信

需求场景:

1.两个不同的应用程序之间通讯需要

2.复用以前app已有的功能

实现原理:

1.IPC

在这之前我们先简单说一下IPC,IPC是Inter-Process Communication的缩写,

是进程间通信或者跨进程通信的意思,既然说到进程,大家要区分一下进程和线程,

进程一般指的是一个执行单元,它拥有独立的地址空间,也就是一个应用或者一个程序。

线程是CPU调度的最小单元,是进程中的一个执行部分或者说是执行体,两者之间是包含与被包含的关系。

因为进程间的资源不能共享的,所以每个系统都有自己的IPC机制,Android是基于Linux内核的移动操作系统

但它并没有继承Linux的IPC机制,而是有着自己的一套IPC机制。

2.Binder

Binder就是Android中最具特色的IPC方式,AIDL其实就是通过Binder实现的,

因为在我们定义好aidl文件后,studio就帮我们生成了相关的Binder类。

事实上我们在使用AIDL时候继承的Stub类,就是studio帮我们生成的Binder类,

所以我们可以通过查看studio生成的代码来了解Binder的工作原理

代码实现:

服务端:

1.编写aidl文件

android studio 可以直接通过编写的aidl文件build生成相应的继承 android.os.IInterface 的接口文件

// IRemoteInterface.aidl

package com.tpv.app.aidldemo;

// Declare any non-default types here with import statements

interface IRemoteInterface {

/**

* Demonstrates some basic types that you can use as parameters

* and return values in AIDL.

*/

void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,

double aDouble, String aString);

String callRemote();

int add(int a,int b);

}

生成的java文件:

/*

* This file is auto-generated. DO NOT MODIFY.

* Original file: D:\\git\\AidlDemo\\app\\src\\main\\aidl\\com\\tpv\\app\\aidldemo\\IRemoteInterface.aidl

*/

package com.tpv.app.aidldemo;

// Declare any non-default types here with import statements

public interface IRemoteInterface extends android.os.IInterface

{

/**

* Local-side IPC implementation stub class.

*/

public static abstract class Stub extends android.os.Binder implements com.tpv.app.aidldemo.IRemoteInterface

{

private static final java.lang.String DESCRIPTOR = "com.tpv.app.aidldemo.IRemoteInterface";

/**

* Construct the stub at attach it to the interface.

*/

public Stub()

{

this.attachInterface(this, DESCRIPTOR);

}

/**

* Cast an IBinder object into an com.tpv.app.aidldemo.IRemoteInterface interface,

* generating a proxy if needed.

*/

public static com.tpv.app.aidldemo.IRemoteInterface asInterface(android.os.IBinder obj)

{

if ((obj == null))

{

return null;

}

android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);

if (((iin != null) && (iin instanceof com.tpv.app.aidldemo.IRemoteInterface)))

{

return ((com.tpv.app.aidldemo.IRemoteInterface) iin);

}

return new com.tpv.app.aidldemo.IRemoteInterface.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_callRemote:

{

data.enforceInterface(DESCRIPTOR);

java.lang.String _result = this.callRemote();

reply.writeNoException();

reply.writeString(_result);

return true;

}

case TRANSACTION_add:

{

data.enforceInterface(DESCRIPTOR);

int _arg0;

_arg0 = data.readInt();

int _arg1;

_arg1 = data.readInt();

int _result = this.add(_arg0, _arg1);

reply.writeNoException();

reply.writeInt(_result);

return true;

}

}

return super.onTransact(code, data, reply, flags);

}

private static class Proxy implements com.tpv.app.aidldemo.IRemoteInterface

{

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 callRemote() 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);

mRemote.transact(Stub.TRANSACTION_callRemote, _data, _reply, 0);

_reply.readException();

_result = _reply.readString();

} finally

{

_reply.recycle();

_data.recycle();

}

return _result;

}

@Override

public int add(int a, int b) throws android.os.RemoteException

{

android.os.Parcel _data = android.os.Parcel.obtain();

android.os.Parcel _reply = android.os.Parcel.obtain();

int _result;

try

{

_data.writeInterfaceToken(DESCRIPTOR);

_data.writeInt(a);

_data.writeInt(b);

mRemote.transact(Stub.TRANSACTION_add, _data, _reply, 0);

_reply.readException();

_result = _reply.readInt();

} finally

{

_reply.recycle();

_data.recycle();

}

return _result;

}

}

static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);

static final int TRANSACTION_callRemote = (android.os.IBinder.FIRST_CALL_TRANSACTION + 1);

static final int TRANSACTION_add = (android.os.IBinder.FIRST_CALL_TRANSACTION + 2);

}

/**

* 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 callRemote() throws android.os.RemoteException;

public int add(int a, int b) throws android.os.RemoteException;

}

2.编写service文件

package com.tpv.app.aidldemo;

import android.app.Service;

import android.content.Intent;

import android.os.IBinder;

import android.os.RemoteException;

public class RemoteService extends Service

{

private MyBinder mBinder;

public RemoteService()

{

}

@Override

public void onCreate()

{

super.onCreate();

if (null==mBinder)

{

mBinder=new MyBinder();

}

}

@Override

public IBinder onBind(Intent intent)

{

return mBinder;

}

//自定义一个继承接口文件中binder类,用来获取客户端的调用

class MyBinder extends IRemoteInterface.Stub

{

@Override

public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException

{

}

@Override

public String callRemote() throws RemoteException

{

return "成功调用远程服务";

}

@Override

public int add(int a, int b) throws RemoteException

{

return a+b;

}

}

}

在注册清单注册service

android:name=".RemoteService"

android:enabled="true"

android:exported="true"

android:process=":remote"

>

属性设置

android:process=":remote"

如果我们需要让一个服务在一个远端进程中运行(而不是标准的它所在的apk的进程中运行),我们可以在声明文件中这个服务的标签中通过android:process属性为其指定一个进程。

注意:这里选择”remote”这个名字是随意主观的,你能用其他名字来让这个服务在另外的进程中运行。冒号’:’这个前缀将把这个名字附加到你的包所运行的标准进程名字的后面作为新的进程名称。

根据需要在注册清单设置过滤条件

客户端:

复制服务端的aidl文件到main文件夹下,包名需和服务端包名一致,build生成接口文件在debug文件夹下

\build\generated\source\aidl\debug\包名\类名.java

1.编写ServiceConnection接收服务端传回的数据

private ServiceConnection aidl =new ServiceConnection()

{

@Override

public void onServiceConnected(ComponentName name, IBinder service)

{

Log.e(getClass().getSimpleName(),"绑定服务:");

mAidlBinder = IRemoteInterface.Stub.asInterface(service);

}

@Override

public void onServiceDisconnected(ComponentName name)

{

mAidlBinder=null;

}

};

2.bindService 获取与客户端服务连接

Intent intent=new Intent();

intent.setAction("过滤条件");

//从 Android 5.0开始 隐式Intent绑定服务的方式已不能使用,所以这里需要设置Service所在服务端的包

intent.setPackage("服务端包名");

bindService(intent,aidl,BIND_AUTO_CREATE);

3.获取服务端返回的数据

try

{

String text = mAidlBinder.callRemote();

} catch (RemoteException e)

{

e.printStackTrace();

}

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐