为使应用程序之间能够彼此通信, Android 提供了 IPC (Inter Process Communication, 进程间通信)的一种独特实现: AIDL (Android Interface Definition Language, Android 接口定义语言).
简单来说, AIDL 就是定义一个接口, 客户端 (调用端) 通过 bindService 来与远程服务端建立一个连接, 在该连接建立时会将返回一个 IBinder 对象, 该对象是服务端 Binder 的 BinderProxy. 在建立连接时, 客户端通过 asInterface 函数将该 BinderProxy 对象包装成本地的 Proxy, 并赋值给 Proxy 类的 mRemote 字段, 本地通过 mRemote 即可调用远程方法.
1, 创建 .aidl 文件
首先打开 Android Studio,new 一个 AIDL file. 具体代码如下 :
- interface IMyAidlInterface {
- /**
- * 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);
- }
basicTypes 方法事接口自带的, 不过可以知道, 在 aidl 中只能使用这些基本类型参数: int, long, boolean, float,double , String ;
除了 basicTypes 方法之外, 我们也可以添加自己的方法. 因此, 可以删除 basicTypes 方法, 添加自己的方法.
二, 生成 .java 文件
添加完方法之后, 选中 .aidl 文件, 在弹出的菜单中选择 Synchronize LocalAIDLS... Service.java, 就会会自动帮你生成对应的 java 代码.
格式化代码之后, 如下所示:
- /*
- * This file is auto-generated. DO NOT MODIFY.
- * Original file: /Users/shenjiaqi/Documents/sjq/booksource/chapter6/DatabaseTest/app/src/main/aidl/com/example/databasetest/IMyAidlInterface.aidl
- */
- package com.example.databasetest;
- public interface IMyAidlInterface extends android.os.IInterface {
- /**
- * Local-side IPC implementation stub class.
- */
- public static abstract class Stub extends android.os.Binder implements com.example.databasetest.IMyAidlInterface {
- private static final java.lang.String DESCRIPTOR = "com.example.databasetest.IMyAidlInterface";
- /**
- * Construct the stub at attach it to the interface.
- */
- public Stub() {
- this.attachInterface(this, DESCRIPTOR);
- }
- /**
- * Cast an IBinder object into an com.example.databasetest.IMyAidlInterface interface,
- * generating a proxy if needed.
- */
- public static com.example.databasetest.IMyAidlInterface asInterface(android.os.IBinder obj) {
- if ((obj == null)) {
- return null;
- }
- android.os.IInterface iin = obj.queryLocalInterface(DESCRIPTOR);
- if (((iin != null) && (iin instanceof com.example.databasetest.IMyAidlInterface))) {
- return ((com.example.databasetest.IMyAidlInterface) iin);
- }
- return new com.example.databasetest.IMyAidlInterface.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;
- }
- }
- return super.onTransact(code, data, reply, flags);
- }
- private static class Proxy implements com.example.databasetest.IMyAidlInterface {
- 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();
- }
- }
- }
- static final int TRANSACTION_basicTypes = (android.os.IBinder.FIRST_CALL_TRANSACTION + 0);
- }
- /**
- * 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;
- }
如果, 你需要修改 .aidl 文件, 那么修改之后, 选择 build -> make project 即可, 会重新生成对应的 java 文件.
三, 传输复杂数据
如果, 需要传递复杂数据, 那么就需要实现 Parcelable 接口, 可序列化:
- public class Info implements Parcelable {
- private String content;
- public String getContent() {
- return content;
- }
- public void setContent(String content) {
- this.content = content;
- }
- public Info() {
- }
- public Info(Parcel in) {
- content = in.readString();
- }
- public static final Creator<Info> CREATOR = new Creator<Info>() {
- @Override
- public Info createFromParcel(Parcel in) {
- return new Info(in);
- }
- @Override
- public Info[] newArray(int size) {
- return new Info[size];
- }
- };
- @Override
- public int describeContents() {
- return 0;
- }
- @Override
- public void writeToParcel(Parcel dest, int flags) {
- dest.writeString(content);
- }
- /**
- * 参数是一个 Parcel, 用它来存储与传输数据
- *
- * @param dest
- */
- public void readFromParcel(Parcel dest) {
- // 注意, 此处的读值顺序应当是和 writeToParcel()方法中一致的
- content = dest.readString();
- }
- // 方便打印数据
- @Override
- public String toString() {
- return "content :" + content;
- }
- }
与此同时, 也要建一个 info.aidl 文件, 表明数据也是可以传递的.
- package com.viii.aidlclient;
- // 注意: Info.Info.java 的包名应当是一样的
- // 这个文件的作用是引入了一个序列化对象 Info 供其他的 AIDL 文件使用
- // 注意 parcelable 是小写
- parcelable Info;
这样就可以使用 info 对象了. 不用在受前面的基本类型变量所控制.
四, 建立 service
接下去, 新建一个 Service 负责接收消息, 并在 AndroidManifest.xml 里面注册 Service:
- public class MyService extends Service {
- private static final String TAG = "MyService";
- // private MyBinder mMyBinder = new MyBinder();
- @Nullable
- @Override
- public IBinder onBind(Intent intent) {
- Log.d(TAG, "onBind:");
- return null;
- }
- @Override
- public void onCreate() {
- Log.d(TAG, "onCreate:");
- super.onCreate();
- }
- @Override
- public int onStartCommand(Intent intent, int flags, int startId) {
- Log.d(TAG, "onStartCommand:");
- return super.onStartCommand(intent, flags, startId);
- }
- private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() {
- @Override
- public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
- }
- };
- }
这时候, 可以 basicTypes 方法添加具体函数代码, 实现你想要的功能.
5, 获取服务
接下去在 mainactivity 中进行绑定.
- public class MainActivity extends AppCompatActivity {
- private static final String TAG = "MainActivity";
- private IMyAidlInterface mService;
- private boolean mIsBound;
- private AdditionServiceConnection mServiceConnection;
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_main);
- doBindService() ;
- }/**
- * bind service
- */
- private void doBindService() {
- mServiceConnection = new AdditionServiceConnection();
- Intent intent = new Intent(this, MyService.class);
- bindService(intent, mServiceConnection, BIND_AUTO_CREATE);
- }
- /**
- * unbind service
- */
- private void doUnbindService() {
- if (mIsBound) {
- unbindService(mServiceConnection);
- mServiceConnection = null;
- mIsBound = false;
- }
- }
- /**
- * ServiceConection
- */
- class AdditionServiceConnection implements ServiceConnection {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- mService = IMyAidlInterface.Stub.asInterface((IBinder) service);
- mIsBound = true;
- try {
- // 设置死亡代理
- service.linkToDeath(mDeathRecipient, 0);
- } catch (RemoteException e) {
- e.printStackTrace();
- }
- Log.d(TAG, "onServiceConnected:");
- }
- @Override
- public void onServiceDisconnected(ComponentName name) {
- mService = null;
- mIsBound = false;
- Log.d(TAG, "onServiceDisconnected:");
- }
- }
- /**
- * 监听 Binder 是否死亡
- */
- private IBinder.DeathRecipient mDeathRecipient = new IBinder.DeathRecipient() {
- @Override
- public void binderDied() {
- if (mService == null) {
- return;
- }
- mService.asBinder().unlinkToDeath(mDeathRecipient, 0);
- mService = null;
- // 重新绑定
- doBindService();
- }
- };
- @Override
- protected void onStop() {
- super.onStop();
- doUnbindService();
- }
- }
将远程服务的 binder 拿到之后, 我们就可以调用相关方法实现自己的功能呢.
到这里, 一个 AIDL 就被我们实现了.
具体实例代码见 :https://download.csdn.net/download/szengjiaqi/10613236
来源: https://www.cnblogs.com/huansky/p/9465698.html