关于android:Android进程间通信之bindService篇

42次阅读

共计 2880 个字符,预计需要花费 8 分钟才能阅读完成。

背景概述

在 Android 中 binder 是一种十分重要的过程间通信形式。基于 binder 实现的过程间通信状态十分多,其中 Android 的四大组件之一 Service,能够用来和 binder 机制联合,来实现跨过程通信。这种形式就是 bindservice,在 bindservice 这个场景外面,Service 作为一个服务端,给调用端也就是 client 端提供接口。这种形式个别用于 Java 端和 Java 端的跨过程通信。上面来具体解说一下这种实现形式。

Service 的创立

首先,咱们须要创立一个 service,这个 service 是用来给 client 端提供接口的。创立 service 的形式有三种:

扩大 binder 类

这种形式是当服务端和客户端在同一个过程时应用。因而,这种形式并不具备跨过程的能力,本文就不具体讲述了。

应用 Messenger

这种形式可能实现跨过程通信。次要特点是,它将申请放入一个队列中,服务端不须要进行线程平安设计。这种形式其实在我的项目开发中应用的并不多。本文也不具体讲述了。

备注:
对于上述两种形式具体能够参考:developer.android.com/guide/compo…

应用 AIDL

AIDL 是 Android 提供的一种不便让开发者基于 binder 来实现跨过程通信的一种工具。它的特点是反对客户端同时并发拜访,所以如果你的服务设计为 AIDL 的形式,那么你须要思考线程平安的设计。上面来具体说下这种形式:

创立.aidl 文件

.aidl 文件须要开发者本人依照语法规定来定义。提供服务的服务端和绑定服务的客户端都须要蕴含.aidl 源码文件。一般来说会定义两个 aidl 文件,一个是给 client 调用 service 提供接口定义,另外一个是给 service 回调 client 提供接口定义。

实现 AIDL 中定义的接口

AIDL 定义的接口,必须在 service 端给出每个接口的具体实现。

向 client 端公开接口

将实现了 AIDL 接口的实例,通过 onBind() 接口返回给 client 端,这样 client 端能力通过这个实例调用 AIDL 的接口实现。

备注:
具体实现代码参考:client 端源码 github.com/jiantengfei… service 端源码 github.com/jiantengfei…
相干文章参考:developer.android.com/guide/compo…

应用 AIDL 的技术要点

通过 IPC 调用传递 objects

在 IPC 调用中,须要传递函数型参给对端。在 AIDL 中,反对以下数据类型的传递:
Java 语言中的原语类型(int、long、char、boolean 等)
String、CharSequence、List(对端的接收数据是 ArrayList)、Map(对端的接收数据是 HashMap)
另外还反对自定义对象的 IPC 传输,然而开发者必须本人实现自定义对象的序列化。在 AIDL 中是将自定义对象实现 Parcelable 接口,并给出接口实现,来实现对象的序列化的。
在 Android 10 以上的版本,能够间接在 AIDL 中定义 Parcelable 对象。AIDL 工具在编译时能够帮忙开发者主动生成对应的对象的序列化代码。参考如下:

package android.graphics;

// Declare Rect so AIDL can find it and knows that it implements
// the parcelable protocol.
parcelable Rect {
    int left;
    int top;
    int right;
    int bottom;
}
复制代码 

如果想要本人来实现的话,首先新增一个 Rect.aidl 文件

package android.graphics;

// Declare Rect so AIDL can find it and knows that it implements
// the parcelable protocol.
parcelable Rect;
复制代码 

再定义 Rect 这个类的具体实现:

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

public final class Rect implements Parcelable {
    public int left;
    public int top;
    public int right;
    public int bottom;

    public static final Parcelable.Creator<Rect> CREATOR = new Parcelable.Creator<Rect>() {public Rect createFromParcel(Parcel in) {return new Rect(in);
        }

        public Rect[] newArray(int size) {return new Rect[size];
        }
    };

    public Rect() {}

    private Rect(Parcel in) {readFromParcel(in);
    }

    public void writeToParcel(Parcel out, int flags) {out.writeInt(left);
        out.writeInt(top);
        out.writeInt(right);
        out.writeInt(bottom);
    }

    public void readFromParcel(Parcel in) {left = in.readInt();
        top = in.readInt();
        right = in.readInt();
        bottom = in.readInt();}

    public int describeContents() {return 0;}
}
复制代码 

办法中带有 Bundle 类型参数

// IRectInsideBundle.aidl
package com.example.android;

/** Example service interface */
interface IRectInsideBundle {
    /** Rect parcelable is stored in the bundle with key "rect" */
    void saveRect(in Bundle bundle);
}
复制代码 

在 service 端解析 Bundle 之前,须要显示在 Bundle 中 setClassLoader。

private final IRectInsideBundle.Stub binder = new IRectInsideBundle.Stub() {public void saveRect(Bundle bundle){bundle.setClassLoader(getClass().getClassLoader());
        Rect rect = bundle.getParcelable("rect");
        process(rect); // Do more with the parcelable.
    }
};
复制代码 

总结

本文次要介绍了 Android 中,应用 binder 和 binderservice 这种形式,来实现 Java 端和 Java 端跨过程通信的形式。并简略介绍了下应用 AIDL 工具的关键技术点。

正文完
 0