[Android AIDL系列 3] Parcelable在不同语言中的差异

如果在AIDL接口中传递自定义的类型,需要实现Parcelable接口,传输时可以序列号/反序列化对象,目标进程就可以还原对象了。

Java类型需要实现android.os.Parcelable接口

public interface Parcelable {
    int CONTENTS_FILE_DESCRIPTOR = 1;
    int PARCELABLE_WRITE_RETURN_VALUE = 1;

    int describeContents();

    void writeToParcel(Parcel var1, int var2);

    public interface Creator<T> {
        T createFromParcel(Parcel var1);

        T[] newArray(int var1);
    }

    public interface ClassLoaderCreator<T> extends Creator<T> {
        T createFromParcel(Parcel var1, ClassLoader var2);
    }
}

// A Java Parcelable sample
class MyData implements Parcelable {
    private String name;

    protected MyData(Parcel in) {
        name = in.readString();
    }

    public static final Creator<MyData> CREATOR = new Creator<MyData>() {
        @Override
        public MyData createFromParcel(Parcel in) {
            return new MyData(in);
        }

        @Override
        public MyData[] newArray(int size) {
            return new MyData[size];
        }
    };

    @Override
    public int describeContents() {
        return 0;
    }

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

C++需要继承Parcelable(binder/Parcelable.h)

class Parcelable {
public:
    virtual ~Parcelable() = default;

    Parcelable() = default;
    Parcelable(const Parcelable&) = default;

    // Write |this| parcelable to the given |parcel|.  Keep in mind that
    // implementations of writeToParcel must be manually kept in sync
    // with readFromParcel and the Java equivalent versions of these methods.
    //
    // Returns android::OK on success and an appropriate error otherwise.
    virtual status_t writeToParcel(Parcel* parcel) const = 0;

    // Read data from the given |parcel| into |this|.  After readFromParcel
    // completes, |this| should have equivalent state to the object that
    // wrote itself to the parcel.
    //
    // Returns android::OK on success and an appropriate error otherwise.
    virtual status_t readFromParcel(const Parcel* parcel) = 0;
};  // class Parcelable

使用Java Parcelable的例子

aidl文件内容:

// IMyServiceInterface.aidl
package com.my.pkg;

interface IMyServiceInterface {
    void setJava(in com.my.pkg.JavaParcelable data);
    // void setCpp(in com.my.pkg.CppParcelable data);
}
// JavaParcelable.aidl
package com.my.pkg;
parcelable JavaParcelable;

编译aidl文件:

$ aidl -I aidl/ -o java aidl/com/my/pkg/IMyServiceInterface.aidl 

在java/com/my/pkg目录下生成IMyServiceInterface.java接口文件。
关于aidl命令行编译可参考:Android AIDL系列 1 - 手动编译aidl文件

注意:没有JavaParcelable.java源文件就可以生成接口文件。C++不是这样。

使用C++ Parcelable的例子

aidl文件内容

// IMyServiceInterface.aidl
package com.my.pkg;

interface IMyServiceInterface {
    // void setJava(in com.my.pkg.JavaParcelable data);
    void setCpp(in com.my.pkg.CppParcelable data);
}
// CppParcelable.aidl
package com.my.pkg;
parcelable CppParcelable cpp_header "CppParcelable.h";
// CppParcelable.h,空文件即可

编译aidl文件生成c++接口文件:

$ aidl -I aidl/ -h cpp_parcel -o cpp_parcel --lang=cpp aidl/com/my/pkg/IMyServiceInterface.aidl

.h和.cpp文件生成在cpp_parcel/com/my/pkg目录下。
在生成c++接口时,对应的parcel文件中,aidl文件定义中需要用cpp_header关键字指定对应类型的头文件。
实际试验aidl编译过程不校验头文件的内容,哪怕是空文件也可以正常编译通过,生成所需头文件和源码文件。
关于aidl命令行编译可参考:Android AIDL系列 1 - 手动编译aidl文件

你可能感兴趣的:(Android开发技术专栏,android,java,开发语言)