【Android】进程间通信IPC——AIDL
16lz
2021-12-15
AIDL
官网定义
AIDL(Android 接口定义语言)与您可能使用过的其他 IDL 类似。 您可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口。 在 Android 上,一个进程通常无法访问另一个进程的内存。 尽管如此,进程需要将其对象分解成操作系统能够识别的原语,并将对象编组成跨越边界的对象。 编写执行这一编组操作的代码是一项繁琐的工作,因此 Android 会使用 AIDL 来处理。
支持类型
- Java基本数据类型(int,long,char,boolean,float,double等);
- CharSequence,String
- 实现Parcelable的对象
- List和Map(元素必须是以上支持的数据类型,生成方法使用List和Map,接受端实际类型为ArrayList和HashMap)
- AIDL
实现
实现Parcelable实体
要传递的实体类UserBean
public class UserBean implements Parcelable { private String name; private int age; private String address; public UserBean() { } public UserBean(String name, int age, String address) { this.name = name; this.age = age; this.address = address; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } protected UserBean(Parcel in) { name = in.readString(); age = in.readInt(); address = in.readString(); } public static final Creator CREATOR = new Creator() { @Override public UserBean createFromParcel(Parcel in) { return new UserBean(in); } @Override public UserBean[] newArray(int size) { return new UserBean[size]; } }; @Override public int describeContents() { return 0; } @Override public void writeToParcel(Parcel dest, int flags) { dest.writeString(name); dest.writeInt(age); dest.writeString(address); } /** * 需要手动添加,Android Studio没法直接生成 */ public void readFromParcel(Parcel reply) { name = reply.readString(); age = reply.readInt(); address = reply.readString(); } @Override public String toString() { return "UserBean{" + "name='" + name + '\'' + ", age=" + age + ", address='" + address + '\'' + '}'; }}
注: Android Studio中实现Parcelable设置完属性就能快速生成必要的代码,但是readFromParcel方法需要手动实现,否则无法编译通过会报错
Process 'command 'D:\software\android\sdk\build-tools\28.0.3\aidl.exe'' finished with non-zero exit value 1
AIDL文件
映射对象
// UserBean.aidlpackage com.sjl.exercise.bean;// Declare any non-default types here with import statementsparcelable UserBean;
接口aidl
注:
- import声明任何非默认类型(例 UserBean)
- 方法中除了基本数据类型,其他类型的需要标上方向类型(in,out,inout)
// ICustomAidlInterface.aidlpackage com.sjl.exercise;// Declare any non-default types here with import statementsimport com.sjl.exercise.bean.UserBean;interface ICustomAidlInterface { String getCurrentTime(); void insertUser(in UserBean userBean); List getUsers(); void clearUser();}
定义完成后Make Project一下等待构建完成
服务端
创建远程服务
public class RemoteService extends Service { private static final String TAG = "RemoteService"; private List list = new ArrayList<>(); ICustomAidlInterface.Stub stub = new ICustomAidlInterface.Stub() { @Override public String getCurrentTime() throws RemoteException { return new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date()); } @Override public void insertUser(UserBean userBean) throws RemoteException { list.add(userBean); } @Override public List getUsers() throws RemoteException { return list; } @Override public void clearUser() throws RemoteException { list.clear(); } }; @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate"); Toast.makeText(this, "远程服务onCreate", Toast.LENGTH_SHORT).show(); } /** * 返回IBinder用于通信 * @param intent * @return */ @Override public IBinder onBind(Intent intent) { Log.i(TAG, "onBind"); Toast.makeText(this, "远程服务onBind", Toast.LENGTH_SHORT).show(); return stub; } @Override public boolean onUnbind(Intent intent) { Log.i(TAG, "onUnbind"); Toast.makeText(this, "远程服务onUnbind", Toast.LENGTH_SHORT).show(); return super.onUnbind(intent); } @Override public void onDestroy() { Log.i(TAG, "onDestroy"); Toast.makeText(this, "远程服务onDestroy", Toast.LENGTH_SHORT).show(); super.onDestroy(); }}
AndroidManifest.xml配置服务,定义Action用于隐式唤醒
客户端
拷贝服务端的aidl文件及自定义的UserBean对象放到客户端的中,路径需要与服务端保持一致
绑定服务
Intent intent = new Intent(); //AndroidManifest.xml中定义的服务器端Action intent.setAction("com.sjl.aidl.remote"); //5.0后无法通过隐式Intent绑定远程Service,需设置包名 intent.setPackage("com.sjl.exercise"); bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE);
获取到AIDL接口
private ICustomAidlInterface iCustomAidlInterface; private ServiceConnection serviceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { iCustomAidlInterface = ICustomAidlInterface.Stub.asInterface(service); Log.i(TAG, "onServiceConnected"); Toast.makeText(MainActivity.this, "service connected", Toast.LENGTH_SHORT).show(); } @Override public void onServiceDisconnected(ComponentName name) { Log.i(TAG, "onServiceDisconnected"); iCustomAidlInterface = null; } };
调用AIDL接口
iCustomAidlInterface.getCurrentTime();UserBean userBean = new UserBean();userBean.setName("name" + cnt);userBean.setAddress("address" + cnt);userBean.setAge(cnt);iCustomAidlInterface.insertUser(userBean);iCustomAidlInterface.getUsers();iCustomAidlInterface.clearUser();
服务端
AIDL
UserBean
客户端
AIDL
UserBean
更多相关文章
- android 线程,服务,活动
- 初学Android,使用自定义的XML资源(十八)
- Android简介
- Android高手进阶教程(四)之----Android(安卓)中自定义属性(attr.
- android中Intent传值与Bundle传值详解
- Android中配置和使用Google Map服务
- Android菜鸟的成长笔记(6)——剖析源码学自定义主题Theme
- Android开发者必知的5个开源库
- Android高手进阶教程(四)之----Android(安卓)中自定义属性(attr.