Aidl进阶 ----- 自定义类型传输
2020.8.7 第一次编辑。。。未完待续。。。
2020.8.11 第二次编辑。。。未完待续。。。
2020.8.12 第三次编辑。。。未完待续。。。
本片文章的目录结构如下:
AidlParcelableDemo
|--client
| |--src
| | |--main
| | |--aidl
| | | |--com.zhouxi.client
| | | |--IAidlService.aidl------------------------(1)
| | | |--ParcelableInfo.aidl----------------------(2)
| | |--java
| | | |--com.zhouxi.client
| | | |--MainActivity.java------------------------(3)
| | | |--ParcelableInfo.java----------------------(4)
|
|--aidlservice
| |--src
| | |--main
| | |--aidl
| | | |--com.zhouxi.client
| | | |--IAidlService.aidl-----------------------(5)
| | | |--ParcelableInfo.aidl---------------------(6)
| | |--java
| | | |--com.zhouxi.client
| | | |--AidlService.java------------------------(7)
| | | |--ParcelableInfo.java---------------------(8)
AidlParcelableDemo目录结构
上一篇文章介绍了 AIDL的基础知识,通过样例代码展示了AIDL的执行过程----两个apk之间通过AIDL接口传递数据,也就是通信,但是上文中传递的数据主要是基本数据类型。实际上AIDL也支持传递其他数据类型,例如自定义数据类型,本片文章主要聚焦在自定义数据类型的传递(中间不过度的说明AIDL的原理,不理解的可以先看上一篇文章),先上client的代码。
package com.zhouxi.client;
import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
public static final String TAG = MainActivity.class.getSimpleName();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.bindAidlService).setOnClickListener(this);
findViewById(R.id.unbindAidlService).setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (v.getId() == R.id.bindAidlService) {
Intent intent = new Intent();
intent.setAction("com.zhouxi.service.AidlService");
intent.setPackage("com.zhouxi.service");
bindService(intent, aidlServiceConnection, Context.BIND_AUTO_CREATE);
} else if (v.getId() == R.id.unbindAidlService) {
Log.e(TAG, "onClick: unbindAidlService");
unbindService(aidlServiceConnection);
}
}
public ServiceConnection aidlServiceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
ParcelableInfo inParcelableInfo = new ParcelableInfo("这是一条传入的自定义类型");
Log.e(TAG, "onServiceConnected: bind AidlService success.");
IAidlService aidlService = IAidlService.Stub.asInterface(service);
try {
Log.e(TAG, "onServiceConnected: the info of AidlService: " + aidlService.getServiceInfo(inParcelableInfo).getInfo());
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {
Log.e(TAG, "onServiceConnected: bind AidlService fail.");
}
};
}
该apk定义了两个按钮用来绑定和解绑AidlService,在绑定成功后,AidlService会返回自身的代理类,也就是
IAidlService aidlService = IAidlService.Stub.asInterface(service);
获取到代理类后就可以通过AIDL接口访问AidlService中的数据了(具体还要看接口实现),查看aidl文件,IAidlService定义了getServiceInfo方法,传入ParcelableInfo的自定义数据类型,返回值也是该类型,在这先把这个数据类型想象看基本数据类型来理解。
// IAidlService.aidl
package com.zhouxi.client;
import com.zhouxi.client.ParcelableInfo;
interface IAidlService {
ParcelableInfo getServiceInfo(in ParcelableInfo inParcelableInfo);
}
查看AidlService中对于这个接口的具体实现
package com.zhouxi.client;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;
import androidx.annotation.Nullable;
public class AidlService extends Service {
private static final String TAG = AidlService.class.getSimpleName();
@Override
public void onCreate() {
Log.e(TAG, "onCreate: AidlService is onCreate.");
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand: AidlService is onStartCommand.");
return super.onStartCommand(intent, flags, startId);
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy: AidlService is onDestroy.");
super.onDestroy();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Log.e(TAG, "onBind: AidlService is onBind.");
return new AidlBinder();
}
@Override
public boolean onUnbind(Intent intent) {
Log.e(TAG, "onUnbind: AidlService is onUnbind.");
return super.onUnbind(intent);
}
class AidlBinder extends IAidlService.Stub {
@Override
public ParcelableInfo getServiceInfo(ParcelableInfo inParcelbleInfo) {
Log.e(TAG, "the inParcelbleInfo is: " + inParcelbleInfo.getInfo());
inParcelbleInfo.setInfo("这是一条传出的自定义类型");
return inParcelbleInfo;
}
}
}
可以看出,AidlService中实现了IAidlService的接口方法,将入参inParcelbleInfo的字段修改成别的信息并输出,整个apk间的调用关系就结束了,接下来聚焦如何实现自定义类型通过AIDL接口传递
首先新建自定义类型ParcelableInfo同时实现Parcelable接口,IDE会自动提示实现并覆盖Parcelable接口的方法
设置ParcelableInfo所需要的字段和方法即可
从上面可以看出,用来AIDL接口传递的自定义类型生成很简单,新建类--实现类中的功能--实现Parcelable接口--Alter+Enter自动实现接口方法即可
package com.zhouxi.client;
import android.os.Parcel;
import android.os.Parcelable;
public class ParcelableInfo implements Parcelable {
private String info;
public ParcelableInfo(String info) {
this.info = info;
}
protected ParcelableInfo(Parcel in) {
info = in.readString();
}
public void setInfo(String info) {
this.info = info;
}
public String getInfo() {
return info;
}
/**
* 反序列化
*/
public static final Creator<ParcelableInfo> CREATOR = new Creator<ParcelableInfo>() {
@Override
public ParcelableInfo createFromParcel(Parcel in) {
return new ParcelableInfo(in);
}
@Override
public ParcelableInfo[] newArray(int size) {
return new ParcelableInfo[size];
}
};
@Override
public int describeContents() {
return 0;
}
/**
* 序列化过程
*
* @param dest
* @param flags
*/
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(info);
}
}
对于自定义类型,还需要与之相对应的aidl文件来声明,具体如下,只需要简单的声明声明parcelable类型以及自定义类型名字ParcelableInfo即可,两个aidl文件都需要放置在aidl文件夹下面,同时要保证client和service的包名保持一致。
// ParcelableInfo.aidl
package com.zhouxi.client;
// Declare any non-default types here with import statements
parcelable ParcelableInfo;
需要了解更多的,可以之前写的aidl入门文章
本文地址:https://blog.csdn.net/weixin_48968045/article/details/107853418
推荐阅读
-
Aidl进阶 ----- 自定义类型传输
-
2019年6月14日 Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)
-
游戏数据传输帧同步中,自定义浮点(float)、二维向量(vector2)、三维向量(vecter3)、四元数(Quaternion)的数据类型的实现
-
2019年6月14日 Web框架之Django_07 进阶操作(MTV与MVC、多对多表三种创建方式、前后端传输数据编码格式contentType、ajax、自定义分页器)
-
Aidl进阶 ----- 自定义类型传输
-
游戏数据传输帧同步中,自定义浮点(float)、二维向量(vector2)、三维向量(vecter3)、四元数(Quaternion)的数据类型的实现