今天介绍下安卓跨进程同时AIDL基本使用和需要注意的地方,我以登录为例,
新建个项目MyAidl,新建一个IMyAidlInterface 的AIDL接口,
在interface Nmae输入接口名称
//再在aidl文件夹下新建一个Bean对象,(注意自定义bean对象,需要现在aidl新建编译,再建Java类bean,要不你在aidl会报类名冲突)
Bean.adil代码如下
// Bean.aidl
package cn.zdh.myaidl;
// Declare any non-default types here with import statements
//导入对应的Bean对象
parcelable Bean;
再在Java文件夹新建个Bean对象代码如下(注意自定义bean类需要实现parcelable,如果aidl接口使用out 或者inout需要写readFromParcel(Parcel reply)方法; 注意Java的bean类的包名必须和aidl的包名一致)
public class Bean implements Parcelable {
private String name;
private String password;
public Bean() {
}
public Bean(String name, String password) {
this.name = name;
this.password = password;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(this.name);
dest.writeString(this.password);
}
protected Bean(Parcel in) {
this.name = in.readString();
this.password = in.readString();
}
public static final Parcelable.Creator<Bean> CREATOR = new Parcelable.Creator<Bean>() {
@Override
public Bean createFromParcel(Parcel source) {
return new Bean(source);
}
@Override
public Bean[] newArray(int size) {
return new Bean[size];
}
};
/**
* adil 使用out 或者inout 需要写这个方法
*/
public void readFromParcel(Parcel reply) {
this.name = reply.readString();
this.password = reply.readString();
}
}
//下面写aidl接口
//使用AIDL需要注意下面几点
//1:同包也要导包
//2: 支持基础类型数据传递,自定义类需要实现parcelable序列化
//3:自定义的类名和包名必须和 AIDL的类名包名一致
//4:in 服务端 不能修改客服端的入参数数据(bean),但是可以获取参数数据
//5:out 服务端 能修改客服端的入参数据(bean),但是并不可以获取参数数据
//6:inout 服务 能修改客服端的入参数据(bean),也可以获取参数数据 ,但是消耗性能最大
//7:注意 使用out inout Java的bean对象需要写 readFromParcel(Parcel reply){}方法,在方法里面把字段读取出来
import cn.zdh.myaidl.Bean;
interface IMyAidlInterface {
void login(in Bean bean);
}
//Java对应service代码
/**
* 实现aidl接口方法
*/
public class AidlService extends Service {
@Override
public IBinder onBind(Intent intent) {
return iBinder;
}
private Handler handler = new Handler(Looper.getMainLooper()) {
@Override
public void handleMessage(Message msg) {
super.handleMessage(msg);
if (msg.what == 1) {
Toast.makeText(getApplicationContext(), "登录成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(), "登录失败", Toast.LENGTH_SHORT).show();
}
}
};
/**
* 获取aidl的binder对象
* 注意在子线程
*/
private IBinder iBinder = new IMyAidlInterface.Stub() {
@Override
public void login(Bean bean) throws RemoteException {
//判断用户账户是的正确
String name = bean.getName();
String password = bean.getPassword();
Message message = handler.obtainMessage();
if (name.equals("张三") && password.equals("123456")) {
message.what = 1;
handler.sendMessage(message);
} else {
Log.e("zdh", "------" + Thread.currentThread().getName());
message.what = 0;
handler.sendMessage(message);
}
}
};
}
//创建一个activity测试登录,代码如下,(注意 在mainfest添加process 新建个进程)
public class TextActivity extends AppCompatActivity {
private IMyAidlInterface iMyAidlInterface;
private ServiceConnection conn;
private EditText etName, etPassword;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_text);
etName = findViewById(R.id.et_name);
etPassword = findViewById(R.id.et_password);
//bindService启动服务
Intent intent = new Intent();
intent.setComponent(new ComponentName("cn.zdh.myaidl", "cn.zdh.myaidl.AidlService"));
conn = new MyServiceConnection();
bindService(intent, conn, BIND_AUTO_CREATE);
}
@Override
protected void onDestroy() {
super.onDestroy();
//解除服务绑定
unbindService(conn);
}
//登录
public void load(View view) {
Bean bean = new Bean();
bean.setName(etName.getText().toString());
bean.setPassword(etPassword.getText().toString());
try {
//添加数据
iMyAidlInterface.login(bean);
} catch (Exception e) {
e.printStackTrace();
}
}
private class MyServiceConnection implements ServiceConnection {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//获取aidl接口对象
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
}
@Override
public void onServiceDisconnected(ComponentName name) {
}
}
}
//mainfest代码
//注意 process 需要使用双引号 :
<activity android:name=".TextActivity" android:process=":t"/>
//不要忘记注册服务
<service android:name=".AidlService" />
代码运行效果如下
总结:使用aidl需要注意的
//1:同包也要导包
//2: 支持基础类型数据传递,自定义类需要实现parcelable序列化
//3:自定义的类名和包名必须和 AIDL的类名包名一致
//4:in 服务端 不能修改客服端的入参数数据(bean),但是可以获取参数数据
//5:out 服务端 能修改客服端的入参数据(bean),但是并不可以获取参数数据
//6:inout 服务 能修改客服端的入参数据(bean),也可以获取参数数据 ,但是消耗性能最大
//7:注意 使用out inout Java的bean对象需要写 readFromParcel(Parcel reply){}方法,在方法里面把字段读取出来
//8:Java是service 是在子线程
源码地址 https://github.com/zhudaihao/MyAIDL
注意如果服务端和客户端是两个项目,需要在注册的service添加
android:exported="true",
<service android:name=".ViewAidlService"
android:exported="true">
</service>