用于生成可以在Android设备上两个进程之间进行进程间通信。
1.基本类型:int、char、boolean、double、float、byte、long、string) 但不支持short
2.String、CharSequence.
3.List和Map(注意List和Map里面的数据类型必须是AIDL支持的)
4.序列化的对象(Parcelable)
1.建一个工程,在main创建aidl包,然后创建IMyService.aidl
,Student.aidl
,Student.java
三个文件,三个文件放在同一个文件加下如图:
2.Student.java必须序列化,里面就有一个name
package com.example.cb.test.aidl;
import android.os.Parcel;
import android.os.Parcelable;
public class Student implements Parcelable {
public String name;
protected Student(Parcel in) {
name = in.readString();
}
public Student() {
}
public static final Creator CREATOR = new Creator() {
@Override
public Student createFromParcel(Parcel in) {
return new Student(in);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
}
}
3.student.aidl
// Student.aidl
//注意这个地方的包名必须和Student.java的包名一样
package com.example.cb.test.aidl;
parcelable Student;
4.IMyService.aidl
// IMyService.aidl
package com.example.cb.test.aidl;
import com.example.cb.test.aidl.Student;
interface IMyService {
List getStudent();
void addStudent(in Student student);
}
注意:其他类型必须标识其方向:到底是输入还是输出抑或两者兼之,用in,out或者inout来表示,上面的代码我用in标记,因为它是输入型参数。
5.创建IStudentService.java,在main/java/xxxxx/xxx/下创建就可以不需要和aidl文件在同一目录
package com.example.cb.test.service;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import com.example.cb.test.aidl.IMyService;
import com.example.cb.test.aidl.Student;
import java.util.ArrayList;
import java.util.List;
import androidx.annotation.Nullable;
import cb.xlibrary.utils.XLogUtils;
public class IStudentService extends Service {
private List mList = new ArrayList<>();
private boolean mCanRun = true;
private final IMyService.Stub stub = new IMyService.Stub() {
@Override
public List getStudent() {
synchronized (mList) {
return mList;
}
}
@Override
public void addStudent(Student student) {
synchronized (mList) {
if (!mList.contains(student)) {
mList.add(student);
}
}
}
};
@Override
public void onCreate() {
super.onCreate();
Thread thread = new Thread(null, new ServiceWork(), "testThread");
thread.start();
synchronized (mList) {
for (int i = 1; i < 6; i++) {
Student student = new Student();
student.name = "student#" + i;
mList.add(student);
}
}
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return stub;
}
class ServiceWork implements Runnable {
long count = 0;
@Override
public void run() {
while (mCanRun) {
XLogUtils.d("线程 " + count);
count++;
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
@Override
public void onDestroy() {
mCanRun = false;
super.onDestroy();
}
}
IMyService.Stub stub是个Binder对象,Binder对象在跨进程通信尤其重要,有兴趣的可以去看看点我;只是简单的使用AIDL我们并不需要知道其工作原理。
6.在manifest注册我们写的IStudentService
android:process=":remote"
指定当前service是运行在其他进程中的,具体可以看其他博客
点我;这里service相当于AIDL的服务端。
7.接下来我们写客户端代码,就在这个工程下。
package com.example.cb.test.ui;
import android.content.ComponentName;
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;
import com.example.cb.test.R;
import com.example.cb.test.aidl.IMyService;
import com.example.cb.test.aidl.Student;
import com.example.cb.test.base.BaseActivity;
import com.example.cb.test.service.IStudentService;
public class TestActivity extends BaseActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intentService = new Intent(TestActivity.this, IStudentService.class);
bindService(intentService, mServiceConnection, BIND_AUTO_CREATE);
}
});
}
private IMyService mIMyService;
private ServiceConnection mServiceConnection = new ServiceConnection() {
@Override
public void onServiceDisconnected(ComponentName name) {
mIMyService = null;
}
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
//通过服务端onBind方法返回的binder对象得到IMyService的实例,得到实例就可以调用它的方法了
mIMyService = IMyService.Stub.asInterface(service);
try {
Student student = mIMyService.getStudent().get(0);
Log.d("aaa ", student.name);
} catch (RemoteException e) {
e.printStackTrace();
}
}
};
}
@Override
protected void onDestroy() {
super.onDestroy();
if (mIMyService != null) {
unbindService(mServiceConnection);
}
}
别忘了unbindService()
养成好习惯
8.来看下日志
remote代表另一个进程打印的日志,也就是IStudentService
,到此一个简单的夸进程通信就完了。我也是看了任玉刚的博客跟着敲了一遍就了解了,还是要自己动手敲一遍才能记住任玉刚博客