Android Studio 的AIDL详解记录
先看效果图及解释
上面的信息是点击开始的从服务端获取的信息,下面的是服务店回调到客户端的信息。
一、客户端与服务端的目录对比
相关说明分析
1、aidl的包名一定要一样
2、Student类的包名一定也需要一样
3、在右侧点击相应module的的build可以建立aidl的文件,目录在如下图所示
二、服务端各个文件详解
1、服务端最主要的是Service类,Student类是自己的测试类。
2、在aidl文件中IMyAidlInterface.aidl是供客户端向服务端调用的方法;IMyAidlInterfaceCallBackListener.aidl是从服务端
回调的方法。Student.aidl是序列化的写法。
下面来看每个文件的内容和解释
Student.java
package com.example.myservice;
import android.os.Parcel;
import android.os.Parcelable;
public class Student implements Parcelable{//实现Parcelable接口
private int _id;
private String name;
private int age;
public Student() {
}
public Student(int _id,String name, int age) {
this._id = _id;
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
@Override
public String toString() {
return "Student{" +
"_id=" + _id +
", name='" + name + '\'' +
", age=" + age +
'}';
}
public void setAge(int age) {
this.age = age;
}
public int get_id() {
return _id;
}
public void set_id(int _id) {
this._id = _id;
}
@Override
public int describeContents() {//暂时return 为0就好
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {//序列化的操作
dest.writeInt(_id);
dest.writeString(name);
dest.writeInt(age);
}
public static final Creator<Student> CREATOR = new Creator<Student>(){//反序列化的操作
@Override
public Student createFromParcel(Parcel source) {
int _id = source.readInt();
String name = source.readString();
int age = source.readInt();
return new Student(_id,name,age);
}
@Override
public Student[] newArray(int size) {
return new Student[size];
}
};
}
Student.aidl文件
// Student.aidl
package com.example.myservice;
parcelable Student;
IMyAidlInterface.aidl文件
// IMyAidlInterface.aidl
package com.example.myservice;
// Declare any non-default types here with import statements
import com.example.myservice.Student;
import com.example.myservice.IMyAidlInterfaceCallBackListener;
interface IMyAidlInterface {
void registerListener(IMyAidlInterfaceCallBackListener listener);//注册回调监听
void unregisterListener(IMyAidlInterfaceCallBackListener listener);//取消注册回调监听
String getMessage();
List<Student> getStudentList();
}
IMyAidlInterfaceCallBackListener.aidl文件
// IMyAidlInterfaceCallBackListener.aidl
package com.example.myservice;
import com.example.myservice.Student;
interface IMyAidlInterfaceCallBackListener {
void getNewStudentArrive(in Student student);//从服务端回调的函数
}
最后来MyService.java文件
package com.example.myservice;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteCallbackList;
import android.os.RemoteException;
import android.os.SystemClock;
import android.util.Log;
import java.util.ArrayList;
import java.util.List;
public class MyService extends Service {
private static final String TAG = MyService.class.getSimpleName();
public MyService() {
}
@Override
public IBinder onBind(Intent intent) {
// TODO: Return the communication channel to the service.
return new IMyService();
}
private RemoteCallbackList<IMyAidlInterfaceCallBackListener> remoteCallbackList = new RemoteCallbackList<>();//存储监听器的类
private IMyAidlInterfaceCallBackListener listeners;//从客户端传过来的监听
public class IMyService extends IMyAidlInterface.Stub{
@Override
public void registerListener(IMyAidlInterfaceCallBackListener listener) throws RemoteException {
listeners = listener;
remoteCallbackList.register(listener);//把监听器放到队列里
}
@Override
public void unregisterListener(IMyAidlInterfaceCallBackListener listener) throws RemoteException {
listeners = null;
remoteCallbackList.unregister(listener);//取消注册
}
@Override
public String getMessage() throws RemoteException {
Log.e(TAG, "getMessage: "+Thread.currentThread().getName());
return "得到啦";
}
@Override
public List<Student> getStudentList() throws RemoteException {
List<Student> list = new ArrayList<>();
Student student = new Student(0,"小花",20);
Student student1 = new Student(1,"小明",21);
Student student2 = new Student(2,"小逃",22);
list.add(student);
list.add(student1);
list.add(student2);
new Thread(new Runnable() {//我这里是为了测试回调10s后才回调
@Override
public void run() {
SystemClock.sleep(10000);
try {
listeners.getNewStudentArrive(new Student(10,"小哥",29));//这里就是通过传递过来的监听器来进行回调
} catch (RemoteException e) {
e.printStackTrace();
}
}
}).start();
return list;
}
}
}
三、客户端的各个文件的分析详解
.aidl的文件和服务端是一样的,编译生成的aidl文件也是在相同的位置。
主要是说一下Student.java文件的路径,要保证在客户端的该类的包名与服务端的一致。
主要是看MainActivity.java的方法
package com.example.myaidlclient;
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.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.example.myservice.IMyAidlInterface;
import com.example.myservice.IMyAidlInterfaceCallBackListener;
import com.example.myservice.Student;
import java.util.List;
import static com.example.myservice.IMyAidlInterfaceCallBackListener.*;
public class MainActivity extends AppCompatActivity {
private static final String TAG = MainActivity.class.getSimpleName();
private TextView tv;
private TextView tv2;
private Button btn;
private String message;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
tv = findViewById(R.id.tv);//用来显示getStudentList()方法;
tv2 = findViewById(R.id.tv2);//用来显示服务端延时10s后回调的数据
btn = findViewById(R.id.btn);
Intent intent = new Intent("com.example.myservice.MyService");
intent.setPackage("com.example.myservice");//记得加包名
bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);//通过绑定的方式启动MyService服务
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
tv.setText(message);
try {
List<Student> studentList = iMyAidlInterface.getStudentList();//主动获取数据的方法
tv.setText(studentList.toString());
} catch (RemoteException e) {
e.printStackTrace();
}
}
});
}
private IMyAidlInterfaceCallBackListener listener = new IMyAidlInterfaceCallBackListener.Stub() {//注册的监听会在这里回调
@Override
public void getNewStudentArrive(final Student student) throws RemoteException {
Log.e(TAG, "getNewStudentArrive: "+Thread.currentThread().getName());//这里不是主线程,是bind线程池里面的线程
runOnUiThread(new Runnable() {
@Override
public void run() {
tv2.setText(student.toString());//数据展示
}
});
}
};
private IMyAidlInterface iMyAidlInterface;
private ServiceConnection serviceConnection = new ServiceConnection() {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {//绑定服务成功的时候
Log.e(TAG, "onServiceConnected: "+Thread.currentThread().getName());
iMyAidlInterface = IMyAidlInterface.Stub.asInterface(service);
Log.e(TAG, "onServiceConnected: "+iMyAidlInterface);
try {
iMyAidlInterface.registerListener(listener);//去注册回调函数的监听
} catch (RemoteException e) {
e.printStackTrace();
}
try {
message = iMyAidlInterface.getMessage();//简单方法的调用
Log.e(TAG, "onServiceConnected: "+ message);
} catch (RemoteException e) {
e.printStackTrace();
}
}
@Override
public void onServiceDisconnected(ComponentName name) {//失去连接之后可以在这里做相应操作
Log.e(TAG, "onServiceDisconnected: ");
iMyAidlInterface = null;
}
};
@Override
protected void onDestroy() {//在这里做取消监听和取消绑定服务
try {
iMyAidlInterface.unregisterListener(listener);
unbindService(serviceConnection);
} catch (RemoteException e) {
e.printStackTrace();
}
super.onDestroy();
}
}
最后附上代码下载地址: