前言
因项目需求,需要提供跨进程接口给第三方应用使用,特对此进行一个小的总结,希望对大家有一定的帮助
一、AIDL是什么?
AIDL是一个缩写,全称是Android Interface Definition Language,也就是Android接口定义语言,是跨进程通讯的一种方式。
二、使用步骤
1.服务端创建
在main目录下创建aidl文件夹, 创建包com.xxx.xxx, 创建xx.aidl文件,定义需要的接口,因为需要服务端请求异步数据,所以需要定义个回调接口和数据类bean。
1.1 IDataProvide.aidl 创建
package com.xxx.xxx.aidl; import com..xxx.xxx.aidl.InPackageInfo; import com..xxx.xxx.aidl.InTaskCallback; interface IDataProvider { void getPackages(String packageName); void registerCallback(InTaskCallback callback); //注册接口 void unregisterCallBack();//移除接口 }
1.2 InPackageInfo 数据类
package com.xxx.xxx.aidl; import android.os.Parcel; import android.os.Parcelable; public class InPackageInfo implements Parcelable { private String status = ""; private String startDate = ""; public InPackageInfo (String s, String date){ super(); status = s; startDate = date; } protected InPackageInfo(Parcel in) { status = in.readString(); startDate = in.readString(); } public String getStatus() { return status; } public void setStatus(String status) { this.status = status; } public String getStartDate() { return startDate; } public void setStartDate(String startDate) { this.startDate = startDate; } public static final Creator<InPackageInfo> CREATOR = new Creator<InPackageInfo>() { @Override public InPackageInfo createFromParcel(Parcel in) { return new InPackageInfo(in); } @Override public InPackageInfo[] newArray(int size) { return new InPackageInfo[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel parcel, int i) { parcel.writeString(status); parcel.writeString(startDate); } }
1.3 InPackageInfo.aidl 创建
package com.indibox.tv.aidl; parcelable InPackageInfo;
1.4 InTaskCallback.aidl 回调创建
package com.xxx.xxx.aidl; import com.indibox.tv.aidl.InPackageInfo; interface InTaskCallback { void getPackages(inout List<InPackageInfo> packageName); }
1.5 创建服务类 DataProviderService,
package com.xxx.xxx.aidl; import android.app.Service; import android.content.Intent; import android.os.IBinder; public class DataProviderService extends Service { private DataProvider mDataProvider = new DataProvider(); public DataProviderService(){ } @Override public IBinder onBind(Intent intent) { return mDataProvider; }
public class DataProvider extends IDataProvider.Stub { private static final String TAG = "DataProvider"; @Override public void getPackages(String packageName) throws RemoteException { DataPackagesUtils.getInstance().getPackages(packageName); } @Override public void registerCallback(InTaskCallback callback) throws RemoteException { DataPackagesUtils.getInstance().setTaskCallback(callback); } @Override public void unregisterCallBack() throws RemoteException { DataPackagesUtils.getInstance().setTaskCallback(null); } }}
注:记得要在AndroidManifest.xml 文件注册DataProviderService,设置action(启动服务的标识)
至此,服务端的准备工作已经完成了,接下来实现客户端。
2.客户端实现
2.1 为了确保不出错,建议直接把服务端的aidl文件夹拷贝
2.2 客户端调用
package com.xxx.aidldemo; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.os.IBinder; import android.os.RemoteException; import android.util.Log; import com.xxx.xxx.aidl.IDataProvider; import com.xxx.xxx.aidl.InPackageInfo; import com.xxx.xxx.aidl.InTaskCallback; import java.util.List; public class XMAIDLManager { private Context mContext; private IDataProvider mDataProvider; private OnConnectionListener mListener; public XMAIDLManager(Context context, OnConnectionListener listener) { mContext = context; mListener = listener; } private ServiceConnection connection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, final IBinder service) { Log.d("AIDL", "onServiceConnected"); mDataProvider = IDataProvider.Stub.asInterface(service); try { mDataProvider.registerCallback(new TaskCallback()); //设置回调 mDataProvider.getPackages("inditvpackage"); //启动请求 } catch (RemoteException e) { e.printStackTrace(); } } @Override public void onServiceDisconnected(ComponentName name) { mDataProvider = null; } }; class TaskCallback extends InTaskCallback.Stub { @Override public void getPackages(List<InPackageInfo> packageName) throws RemoteException { Log.d("TaskCallback", "getPackages"); //服务端异步请求数据回调接口 } } public void startService() { //启动服务 Intent intent = new Intent(); intent.setAction("你的action"); intent.setPackage("包名"); mContext.bindService(intent, connection, Context.BIND_AUTO_CREATE); } public void stopService() { try { mDataProvider.unregisterCallBack(); mContext.unbindService(connection); } catch (RemoteException e) { e.printStackTrace(); } } public interface OnConnectionListener { void onConnection(List<InPackageInfo> packageInfos); } }
到此AIDL的跨进程的服务端和客户端就实现了,可以进行数据类bean(可自定义)的传递以及服务端异步回调数据给客户端。
总结
使用过程中主要是数据类型的传递,如果是基本的数据类型可以直接传递,当传递特定对象时需要对这个对应对象进行Parcelable 序列化操作,对应记得传对象参数是,需要标识 in /out/ inout,否则编译会出错。整体AIDL使用还是比较方便的,希望此文章会对大家有帮助。