美文网首页
AIDL通信

AIDL通信

作者: 小河伴 | 来源:发表于2020-07-29 15:16 被阅读0次

    通过一个学生管理展示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<Student> CREATOR = new Creator<Student>() {
            @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<Student> 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<Student> 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<Student> CREATOR = new Creator<Student>() {
            @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<Student> 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<Student> getStudents() throws RemoteException {
                return students;
            }
        };
    }
    
    //AndroidManifest.xml 里面配置服务 
    <service android:name=".service.StudentService"
             android:enabled="true"
             android:process=":student_service">
                <intent-filter>
                    <action android:name="android.intent.action.StudentService"/>
                </intent-filter>
    </service>
    

    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<Student> 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通信

          本文链接:https://www.haomeiwen.com/subject/otyhrktx.html