• Android AIDL跨进程通信基础(多端情况)


    简介

    AIDL建议在来自不同的客户端访问你的服务并且需要处理多线程问题时你才必须使用AIDL,其他情况下你都可以选择其他方法,如使用 Messenger,也能跨进程通信。可见 AIDL 是处理多线程、多客户端并发访问的,而 Messenger 是单线程处理。
    下面介绍 AIDL 的使用方法。

    AIDL 文件可以分为两类。一类用来声明实现了 Parcelable 接口的数据类型,以供其他 AIDL 文件使用那些非默认支持的数据类型。还有一类是用来定义接口方法,声明要暴露哪些接口给客户端调用。在 AIDL 文件中需要明确标明引用到的数据类型所在的包名,即使两个文件处在同个包名下。

    默认情况下,AIDL 支持下列数据类型:

    • 八种基本数据类型:byte、char、short、int、long、float、double、boolean
      String,CharSequence

    • List类型。List承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

    • Map类型。Map承载的数据必须是AIDL支持的类型,或者是其它声明的AIDL对象

    服务端目录结构与相关代码

    在这里插入图片描述

    • 创建Book数据类,跨进程传递对象需将对象序列化处理
    package com.example.aidl_server.aidl;
    
    import android.os.Parcel;
    import android.os.Parcelable;
    
    public class Book implements Parcelable {
        private String name;
    
        protected Book(Parcel in) {
            name = in.readString();
        }
    
        public static final Creator<Book> CREATOR = new Creator<Book>() {
            @Override
            public Book createFromParcel(Parcel in) {
                return new Book(in);
            }
    
            @Override
            public Book[] newArray(int size) {
                return new Book[size];
            }
        };
    
        @Override
        public int describeContents() {
            return 0;
        }
    
        @Override
        public void writeToParcel(Parcel dest, int flags) {
            dest.writeString(name);
        }
    
        @Override
        public String toString() {
            return "Book{" +
                    "name='" + name + '\'' +
                    '}';
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • Book对应的AIDL文件代码内容
    package com.example.aidl_server.aidl;
    
    parcelable Book;
    
    • 1
    • 2
    • 3

    注意,这里Book.java与Book.aidl里package一定要一致,不然后面build时会报错,无法生成相关接口代码。

    • 对客户端提供接口方法的aidl代码,此文件与Book.aidl在同一路径下
    // IBookInterface.aidl
    package com.example.aidl_server.aidl;
    
    import com.example.aidl_server.aidl.Book;
    
    // Declare any non-default types here with import statements
    
    interface IBookInterface {
    
        void addBook(in Book book);
    
        List<Book> getBooks();
    
        /**
         * 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);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    创建完成后build一下代码,build成功的话可以在此路径下看见生成的java代码
    在这里插入图片描述

    • 创建服务BookService
    package com.example.aidl_server;
    
    import android.app.Service;
    import android.content.Intent;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.util.Log;
    
    import androidx.annotation.Nullable;
    
    import com.example.aidl_server.aidl.Book;
    import com.example.aidl_server.aidl.IBookInterface;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class BookService extends Service {
    
        private IBookInterface.Stub binder = new IBookInterface.Stub() {
    
            private List<Book> books = new ArrayList<>();
    
            @Override
            public void addBook(Book book) throws RemoteException {
                if (book != null) {
                    books.add(book);
                    Log.e("BookService", "添加书籍成功 ++++ " + book.toString());
                }
            }
    
            @Override
            public List<Book> getBooks() throws RemoteException {
                Log.e("BookService", "获取书籍,数目为 = " + books.size());
                return books;
            }
    
            @Override
            public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat, double aDouble, String aString) throws RemoteException {
    
            }
        };
    
        @Nullable
        @Override
        public IBinder onBind(Intent intent) {
            return binder;
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 服务端清单文件内注册此服务
    		<service
                android:name=".BookService"
                android:enabled="true"
                android:exported="true">
                <intent-filter>
                    <action android:name="com.example.aidl_server.jiao" />
                intent-filter>
            service>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    服务端准备工作完成,接下来看一下客户端如何操作

    客户端连接服务并且进行数据交互

    1. 先将服务端aidl文件夹完整的复制过来,包名要与服务端保持一致
    2. 将服务端Book文件复制到客户端,包名要与服务端一致
    3. build代码

    客户端目录结果如下图

    在这里插入图片描述

    • 创建连接并且绑定服务
    package com.example.aidl_client;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.content.ComponentName;
    import android.content.Context;
    import android.content.Intent;
    import android.content.ServiceConnection;
    import android.os.Bundle;
    import android.os.IBinder;
    import android.os.RemoteException;
    import android.view.View;
    import android.widget.TextView;
    import android.widget.Toast;
    
    import com.example.aidl_server.aidl.Book;
    import com.example.aidl_server.aidl.IBookInterface;
    
    import java.util.List;
    
    public class ClientActivity extends AppCompatActivity {
        private IBookInterface iBookInterface;
        private ServiceConnection connection = new ServiceConnection() {
    
            @Override
            public void onServiceConnected(ComponentName name, IBinder service) {
                iBookInterface = IBookInterface.Stub.asInterface(service);
            }
    
            @Override
            public void onServiceDisconnected(ComponentName name) {
    
            }
        };
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_client);
    
            // 绑定服务
            Intent intent = new Intent();
            intent.setAction("com.example.aidl_server.jiao");
            intent.setPackage("com.example.aidl_server");
            bindService(intent, connection, Context.BIND_AUTO_CREATE);
    
            TextView bookShow = findViewById(R.id.show_book_name);
    
            // 点击添加书籍
            findViewById(R.id.add_book).setOnClickListener(v -> {
                long millis = System.currentTimeMillis();
                Book book = new Book("书籍" + millis);
                try {
                    iBookInterface.addBook(book);
                    Toast
                            .makeText(getApplicationContext(), "添加成功", Toast.LENGTH_LONG)
                            .show();
                } catch (Exception e) {
                    e.printStackTrace();
                    Toast
                            .makeText(getApplicationContext(), "添加失败", Toast.LENGTH_LONG)
                            .show();
                }
            });
    
            // 点击显示书籍
            findViewById(R.id.get_book).setOnClickListener(v -> {
                try {
                    List<Book> books = iBookInterface.getBooks();
                    if (books != null) {
                        if (books.size() == 0) {
                            bookShow.setText("书记数目为0");
                        } else {
                            bookShow.setText(books.toString());
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            });
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            unbindService(connection);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    客户端布局相关代码

    
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".ClientActivity">
    
        <Button
            android:id="@+id/add_book"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="100dp"
            android:text="添加书籍" />
    
        <Button
            android:id="@+id/get_book"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="50dp"
            android:text="获取书籍" />
    
        <TextView
            android:id="@+id/show_book_name"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:layout_marginTop="50dp"
            android:text="显示书籍名称"
            android:textColor="@color/black" />
    
    LinearLayout>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 点击按钮进行操作服务端结果打印如下
      在这里插入图片描述
      end
  • 相关阅读:
    简单宿舍管理系统(springboot+vue)
    C#,骑士游历问题(Knight‘s Tour Problem)的恩斯多夫(Warnsdorff‘s Algorithm)算法与源代码
    5、设计模式之工厂模式
    热烈祝贺〖金融之路CapLab官方中文社群②群〗成员数突破1,600人!
    Python-- list(列表)的使用
    VS Code连接远程Linux服务器开发c++项目
    java与netty的类对应关系
    STM32 ADC介绍和应用
    正则表达式replaceAll()方法具有什么功能呢?
    5. 凸集和凸函数
  • 原文地址:https://blog.csdn.net/qq_44946212/article/details/128006813