Android AIDL的基本使用

最近被公司调到了其他组,帮忙了一段时间Flutter,Android的东西落下了不少,还是打算继续从Framework方面继续学习。关于Android的IPC,之前也了解过,Binder的机制也可以说是研究过,但是由于不经常用,忘得也差不多了,现在连AIDL的基本使用都快忘了,更不用或Binder。所以这篇文章主要来介绍一下AIDL的基本使用。

一、服务端

服务端,也就是数据的提供方

第一步:创建一个实体类Book,要注意,Book要进行序列化的操作,也就是实现Parcelable接口

public class Book implements Parcelable {
    private int bookId;
    private String bookName;
    private double bookPrice;
    private List<String>bookShops;

    public Book(int bookId,String bookName,double bookPrice,List<String>bookShops){
        this.bookId = bookId;
        this.bookName = bookName;
        this.bookPrice = bookPrice;
        this.bookShops = bookShops;
    }

    protected Book(Parcel in) {
        bookId = in.readInt();
        bookName = in.readString();
        bookPrice = in.readDouble();
        bookShops = in.createStringArrayList();
    }

    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.writeInt(bookId);
        dest.writeString(bookName);
        dest.writeDouble(bookPrice);
        dest.writeStringList(bookShops);
    }

    public void readFromParcel(Parcel in){
        bookId = in.readInt();
        bookName = in.readString();
        bookPrice = in.readDouble();
        bookShops = in.createStringArrayList();
    }
}

第二步:创建两个AIDL文件:IBook和IBookManager。

IBook用于实体类Book的序列化声明,如下

// IBook.aidl
package com.example.bindertest;

parcelable Book;

IBookManager提供通信接口,用于通信代码的生成,注意:我们需要导入IBook这个类,如下:

// IBookManager.aidl
package com.example.bindertest;

import com.example.bindertest.IBook;

interface IBookManager {
    List<Book>getBookList();
    void addBook(in Book book);
}

第三步:创建服务Service

在创建Service之前,我们先进行项目的Build操作,Android Studio会根据aidl文件IBookManager.aidl生成对应的java类IBookManager.java,然后创建IBookManager.Stub对象,也就是Service中onBind方法需要的IBinder对象,Service的代码如下:

public class BookService extends Service {
    private List<Book> bookList;

    private final IBookManager.Stub stub = new IBookManager.Stub() {
        @Override
        public List<Book> getBookList() throws RemoteException {
            return bookList;
        }

        @Override
        public void addBook(Book book) throws RemoteException {
            if(book!=null){
                bookList.add(book);
            }else{
                Toast.makeText(BookService.this.getApplicationContext(), "数据异常", Toast.LENGTH_SHORT).show();
            }
        }
    };
    @Override
    public void onCreate() {
        super.onCreate();
        bookList = new ArrayList<>();
        initData();
    }

    private void initData(){
        List<String>bookShops = new ArrayList<>();
        bookShops.add("新华书店");
        bookShops.add("图灵书店");

        Book book1 = new Book(0,"《活着》",26f,bookShops);
        Book book2 = new Book(1,"《时间管理》",32f,bookShops);
        Book book3 = new Book(2,"《狼道》",45f,bookShops);

        bookList.add(book1);
        bookList.add(book2);
        bookList.add(book3);
    }

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

}

当然不要忘了在清单文件中对Service进行注册,如下

        <service
            android:name=".BookService"
            android:enabled="true"
            android:exported="true">
        </service>

第四步:启动Service

千万不要忘记启动Service,我使用了最简单的启动方法,在MainActivity中启动了服务:

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        startService(new Intent(this,BookService.class));
    }
}

二、客户端

第一步:进行相关文件的拷贝

我们重新创建一个项目或者Module作为客户端,将服务端的IBook.aidl,IBookManager.aidl,Book.java这三类拷入到客户端,要注意的是:路径一定要和服务端的路径一样,如下图所示

红框所示为服务端包名路径,而蓝框为客服端的包名路径,不要弄错了

 第二步:客户端进行连接,服务端数据的获取和修改,如下

public class MainActivity extends AppCompatActivity {
    private IBookManager bookManager;
    private boolean connected;

    private ServiceConnection serviceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            Toast.makeText(MainActivity.this, "服务链接成功", Toast.LENGTH_SHORT).show();
            bookManager = IBookManager.Stub.asInterface(service);
            connected = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Toast.makeText(MainActivity.this, "服务断开", Toast.LENGTH_SHORT).show();
            connected = false;
        }
    };

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

        //服务链接
        findViewById(R.id.service_con_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent();
                //第一种方法
                intent.setClassName("com.example.bindertest","com.example.bindertest.BookService");
                //第二种方法
//                intent.setComponent(new ComponentName("com.example.bindertest","com.example.bindertest.BookService"));
                getApplicationContext().bindService(intent,serviceConnection, Context.BIND_AUTO_CREATE);
            }
        });
        //解绑
        findViewById(R.id.service_discon_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                getApplicationContext().unbindService(serviceConnection);
            }
        });
        //从服务端获取数据
        findViewById(R.id.get_book_list_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                try {
                    List<Book> bookList = bookManager.getBookList();
                    for (Book book : bookList) {
                        Log.i("TAG",book.toString());
                    }
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
        //修改服务端数据
        findViewById(R.id.add_book_btn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Book book = new Book(4,"《红人经济》",45,new ArrayList<>());
                try {
                    bookManager.addBook(book);
                } catch (RemoteException e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

要注意:进行服务连接时,要指定包名和类名

三、其他

aidl文件中有三个关键字:in,out,inout,这三个关键字,建议大家看这篇文章,说的很清楚,而我要说的是自己踩得坑:

如果在AIDL文件中的参数为in,则重写实体类中Parcelable的writeToParcel

如果在AIDL文件中的参数为out,则重写实体类中的readFromParcel

如果在AIDL文件中的参数为inout,以上两个方法都要重写

当然,默认是in,所以实现Parcelable接口就行了;而out和inout要额外注意一下

以上就是AIDL的基本使用

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在 Android 应用程序中使用 AIDL,您需要执行以下步骤: 1. 创建 AIDL 接口文件 AIDL 接口文件定义了客户端和服务端之间的通信接口。在在 Android Studio 的 app 目录下创建一个名为 aidl 的文件夹,然后在该文件夹下创建一个 .aidl 文件。例如,我们可以创建一个名为 IMyAidlInterface.aidl 的文件。 2. 定义 AIDL 接口 在 IMyAidlInterface.aidl 文件中,我们可以定义客户端和服务端之间需要交换的数据类型和方法。例如: ``` // IMyAidlInterface.aidl package com.example.myaidl; // Declare any non-default types here with import statements interface IMyAidlInterface { int add(int a, int b); } ``` 在上面的例子中,我们定义了一个名为 IMyAidlInterface 的接口,该接口包含一个 add(int a, int b) 方法,用于计算两个整数的和。 3. 实现 AIDL 接口 在服务端应用程序中,我们需要实现上述定义的 AIDL 接口。在服务端应用程序的 Java 代码中,我们需要实现 IMyAidlInterface.Stub 类,它是一个抽象类,继承自 Binder 类。在 IMyAidlInterface.Stub 类中,我们需要实现 add(int a, int b) 方法。例如: ``` public class MyAidlService extends Service { private final IMyAidlInterface.Stub mBinder = new IMyAidlInterface.Stub() { @Override public int add(int a, int b) throws RemoteException { return a + b; } }; @Nullable @Override public IBinder onBind(Intent intent) { return mBinder; } } ``` 在上面的例子中,我们实现了 add(int a, int b) 方法,该方法计算两个整数的和,并返回结果。 4. 在客户端应用程序中调用 AIDL 接口 在客户端应用程序中,我们需要绑定服务,以获取服务端的实例。然后,我们可以调用服务端的方法。例如: ``` public class MainActivity extends AppCompatActivity { private IMyAidlInterface mIMyAidlInterface; private ServiceConnection mConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { mIMyAidlInterface = IMyAidlInterface.Stub.asInterface(service); } @Override public void onServiceDisconnected(ComponentName name) { mIMyAidlInterface = null; } }; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Intent intent = new Intent(); intent.setComponent(new ComponentName("com.example.myaidl", "com.example.myaidl.MyAidlService")); bindService(intent, mConnection, Context.BIND_AUTO_CREATE); int result = mIMyAidlInterface.add(1, 2); Log.d("MainActivity", "Result: " + result); } } ``` 在上面的例子中,我们绑定服务,以获取服务端的实例。然后,我们调用服务端的 add(int a, int b) 方法,计算两个整数的和,并输出结果。 以上就是使用 AIDL 在不同的应用程序之间进行通信的基本步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值