AIDL通信

通过一个学生管理展示AIDL的使用

1.创建aidl文件

1.打开AndroidStudio,在工程目录右键New=>AIDL
(1)新建Student.aidl文件,相当于这是一个实体类,对应的在java侧要定义一个同名的类Student需要实现Parcelable接口,详见Parcelable的使用,需要删掉默认生成的interface Student改成parcelable Student,

// Student.aidl
package cc.funeay.sepprocesswebview;

// Declare any non-default types here with import statements
parcelable Student;

(2) 新建Student.java 在java目录下,注意Student.aidl和Sutdent.java包名要一样,

public class Student implements Parcelable {
    protected Student(Parcel in) {
    }

    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 parcel, int i) {
    }
}

(3)新建StudentManager.aidl接口来管理Student

// StudentManager.aidl
package cc.funeay.sepprocesswebview;

// Declare any non-default types here with import statements

interface StudentManager {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    void addStudent(Student s);//新增一个学生
    List getStudents();//获取学生列表
}

2.生成java文件

(1)编译的时候报:"Failed to resolve 'Student'" 需要在StudentManager.aidl里面把Student接口完整路径import进来

import cc.funeay.sepprocesswebview.aidl.Student;

编译还是报错:“'cc.funeay.sepprocesswebview.aidl.Student' can be an out type, so you must declare it as in, out, or inout.”,需要添加一个tag表示参数的方向,需要把Student.aidl修改如下

// StudentManager.aidl
package cc.funeay.sepprocesswebview.aidl;
import cc.funeay.sepprocesswebview.aidl.Student;

// Declare any non-default types here with import statements

interface StudentManager {
    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
    void addStudent(inout Student s);
    List getStudents();
}

发现报错:"错误: 找不到符号
符号: 方法 readFromParcel(Parcel)
位置: 类型为Student的变量 s",原来是需要Student实现readFromParcel方法,定义一下,调整Student代码如下

public class Student implements Parcelable {
    private int id;
    private String name;

    public Student(int id, String name) {
        this.id = id;
        this.name = name;
    }

    protected Student(Parcel in) {
        this.id = in.readInt();
        this.name = in.readString();
    }

    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 parcel, int i) {
        //读的顺序要和写的顺序一致
        parcel.writeInt(id);
        parcel.writeString(name);
    }

    public void readFromParcel(Parcel parcel) {
        this.id = parcel.readInt();
        this.name = parcel.readString();
    }

    @NonNull
    @Override
    public String toString() {
        return "id:" + id + " name:" + name;
    }
}

3.编写服务端代码

StudentService.java

public class StudentService extends Service {
    private List students = new ArrayList<>();

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return binder;
    }

    /**
     * 实现StudentManager接口
     */
    private StudentManager.Stub binder = new StudentManager.Stub() {
        @Override
        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {

        }

        @Override
        public void addStudent(Student s) throws RemoteException {
            students.add(s);
        }

        @Override
        public List getStudents() throws RemoteException {
            return students;
        }
    };
}
//AndroidManifest.xml 里面配置服务 

            
                
            

4.编写客户端代码

MainActivity.java

public class MainActivity extends AppCompatActivity {
    private static final String BOOK_SERVICE_ACTION = "android.intent.action.BookService";
    private Button btnStartService;
    private StudentManager studentManager;//从service进程获取的实例

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        initViews();
    }

    private void initViews() {
        findViewById(R.id.tv_go_webview).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                goWebView();
            }
        });
        btnStartService = findViewById(R.id.btn_start_service);
        btnStartService.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                tryStartService();
            }
        });
        findViewById(R.id.btn_add_book).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (studentManager != null) {
                    try {
                        Student student = new Student(1, "Student-" + System.currentTimeMillis());
                        studentManager.addStudent(student);
                        disPlayStudents(studentManager.getStudents());
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    private void disPlayStudents(List students) {
        StringBuffer sbf = new StringBuffer("学生列表:");
        if (students != null) {
            int size = students.size();
            for (int i = 0; i < size; i++) {
                sbf.append(" student --- ");
                sbf.append(students.get(i).getName());
            }
        }
        Log.d("disPlayStudents ", sbf.toString());
    }

    @Override
    protected void onDestroy() {
        stopService();
        super.onDestroy();
    }

    private void tryStartService() {
        String isConnected = btnStartService.getTag() != null ? btnStartService.getTag().toString() : "0";
        if ("0".equals(isConnected)) {
            //未连接
            startService();
        }
    }

    /**
     * 启动service
     */
    private void startService() {
        Intent intent = new Intent();
        intent.setAction(BOOK_SERVICE_ACTION);
        intent.setPackage(getPackageName());//Android 5.0开始不再支持 隐式启动service 需要写成包名
        bindService(intent, connection, Context.BIND_AUTO_CREATE);
    }

    /**
     * 停止/解绑service
     */
    private void stopService() {
        unbindService(connection);
    }

    private void goWebView() {
        Intent intent = new Intent();
        intent.setClass(MainActivity.this, WebViewActivity.class);
        startActivity(intent);
    }

    private ServiceConnection connection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            studentManager = StudentManager.Stub.asInterface(iBinder);
            updateBtnStart();
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
            //异常的时候才会回调
            studentManager = null;
            updateBtnStart();
        }
    };

    private void updateBtnStart() {
        btnStartService.setTag(studentManager != null ? "1" : "0");
        btnStartService.setText(studentManager != null ? "已连接" : "未连接");
    }
}


你可能感兴趣的:(AIDL通信)