前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Android AIDL 跨进程通信

Android AIDL 跨进程通信

作者头像
萬物並作吾以觀復
发布2019-08-12 15:15:16
4390
发布2019-08-12 15:15:16
举报
文章被收录于专栏:指尖下的Android指尖下的Android

安卓 IPC 跨进程通信有很多种方式,我们可以用 Bundle传递数据,通过 Intent 意图去打电话,在 Uri 里面传递电话号码

 //手动拨号将Intent.ACTION_CALL改为Intent.ACTION_DIAL
        Intent intent = new Intent(Intent.ACTION_CALL);
        Uri data = Uri.parse("tel:" + phoneNum);
        intent.setData(data);
        startActivity(intent);

ContentProvider 通过数据共享来获取另一个应用的数据,Socket 也可以用来进程通信,Messenger 支持一对多的串行实时通信, Linux 下特有的进程通信方式 pipe 。ContentProvider 、 Socket 以及 pipe 都没有一套严格的权限管理,以及他们需要拷贝内存两次,Messenger 是简化版的 AIDL,AIDL 只需要拷贝一次内存,并且对访问的进程做了严格的管理控制。如果我们在 AIDL 中需要传递自定义数据类型,那就必须有一个实现序列化的实体类,基本数据类型除了 Short 外,AIDL 都支持,List、Map也同样支持,前提是他们装载的元素是 AIDL 支持的。 1、首先编写我们的 aidl 实体类

Book 实体类

2、Book 实现序列化

package demo.rzj.com.androiddemo.aidl;

import android.os.Parcel;
import android.os.Parcelable;

public class Book implements Parcelable {

    private String name;

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Book() {}

    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;
    }

    public String readFromParcel(Parcel parcel){
        return parcel.readString();
    }

    @Override
    public void writeToParcel(Parcel parcel, int i) {
        parcel.writeString(name);
    }
}

3、编写实体类 Book的 AIDL 映射

Android Studio 下自动生成 AIDL 文件的方式

Book 的 AIDL 映射文件包名路径必须跟实体类的路径一致

Book.aidl 的实现

// Book.aidl
package demo.rzj.com.androiddemo.aidl;

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

然后编写 AIDL 的通信方法

// IBookManager.aidl
package demo.rzj.com.androiddemo;
import demo.rzj.com.androiddemo.aidl.Book;

interface IBookManager {
   Book getMyBook();
   void addBookInOut(inout Book book);
   void addBookIn(in Book book);
   void addBookOut(out Book book);

这里注意一点,即使是同一个包名,也必须手动 import aidl 的映射 然后我们再手动的 build project,切换到 project 模式可以看到 Android Studio 会自动生成一个实际的跨进程通信 AIDL 实现类

AIDL 跨进程通信的实现类

4、Service 的实现

public class DemoIpcService extends Service {
    private Book mBook;
    private String processId;

    private IBinder binder = new IBookManager.Stub() {
        @Override
        public Book getMyBook() throws RemoteException {
            return mBook;
        }

        @Override
        public void addBookInOut(Book book) throws RemoteException {
            if(null != book && !TextUtils.isEmpty(book.getName())){
                Log.e("addBookInOut", book.getName());
            }
            book.setName("addBookInOut");
            mBook = book;
        }

        @Override
        public void addBookIn(Book book) throws RemoteException {
            if(null != book && !TextUtils.isEmpty(book.getName())){
                Log.e("addBookIn", book.getName());
            }
            book.setName("addBookIn");
            mBook = book;
        }

        @Override
        public void addBookOut(Book book) throws RemoteException {
            if(null == book || TextUtils.isEmpty(book.getName())){
                Log.e("addBookOut", "is null");
            }
            String str = null;
            if(null == book.getName()){
                str = "book name is null";
            }
            book.setName(str + "addBookOut");
            mBook = book;
        }
    };

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        processId = String.valueOf(android.os.Process.myPid());
        return binder;
    }
}

这里我偷懒了一下,没有新建两个安卓工程,只是把这个 Service 设置到另一个进程运行,如果是两个应用要通信,只需要把相关的实体类和 AIDL 映射及通讯的 AIDL 拷贝就行,切记服务端和客户端实体类和 AIDL 包名路径要保持一致,就是说客户端的 Book 实体类包名路径是 demo.rzj.com.androiddemo.aidl ,那么服务端也必须是这个包名路径,这里简单说一下 AIDL 定向 Tag 的作用。 in 表示客户端传递数据给服务端,然后就不管了,没有声明默认也是这种 out 表示即使客户端传递了一个非空的对象给服务端,服务端依然会自己实例化一个空对象(里面的参数没有值而已) inout 这个修饰符有争议,很多博客上写当服务端修改客户端传递的数据后会把这个修改同步到移动端,但是经过我的反复测试,数据是不会同步的,查阅了安卓官方文档,里面也没有对这三种定向 Tag 的具体用法和含义做具体的说明,不过一般用 in 就行了

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019.08.11 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
文件存储
文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档