IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Android AIDL使用之Parcelable对象

    FranzKafka95发表于 2023-07-25 14:58:53
    love 0
    Read Time:2 Minute, 12 Second

    parcel是安卓binder通信中的消息载体,通过IBinder进行传递。Parcel的源码实现为android.os.Parcel,继承自java.lang.object。涉及的相关源码为:

    base/core/java/android/os/Parcel.java  //java 实现
    frameworks/base/core/jni/android_os_Parcel.cpp //JNI实现
    frameworks/native/libs/binder/Parcel.cpp // C++实现
    frameworks/native/libs/binder/include/binder/Parcelable.h  //c++ 头文件

    有些时候我们需要在binder中传递自定义的数据类型或者类,此时需要使该类实现Parcelable接口,如果我们是在C++程序与Java程序中进行传递,那么C++与Java侧都需要实现Parcelable接口。支持Parcelbale接口十分重要,Android系统可通过该接口将对象分解成各进程支持的原生类型。这里需要注意的是,Parcel是实体类,而Parcelable是接口。

    自己实现Parcelable接口,根据后端语言的不同,具体实现上也存在差异。这里将分别以Java和C++两种后端语言给出示例。

    Java

    1.定义aidl文件,如myParcelable.aidl,这里其实有约定俗成的命名方式,不需要像定义接口那样以I开头,并且其内容如下:

    package android.com.example;
    parcelable myParcelable;

    2.实现Parcelable接口中的int describeContents()、void writeToParcel(Parcel dest,int flags)以及为myParcelable类添加CREATOR静态字段,实现Parcelable.Creator接口的对象,这里给出示例代码:

    import android.os.Parcel;
    import android.os.Parcelable;
    
    public final class myParcelable implements Parcelable {
        public int left;
        public int top;
        public int right;
        public int bottom;
        //实现Parcelable.Creator的接口
        public static final Parcelable.Creator<myParcelable> CREATOR = new 
        Parcelable.Creator<myParcelable>() {
            public myParcelable createFromParcel(Parcel in) {
                return new myParcelable(in);
            }
    
            public myParcelable[] newArray(int size) {
                return new myParcelable[size];
            }
        };
    
        public myParcelable() {
        }
    
        private myParcelable(Parcel in) {
            readFromParcel(in);
    }
    
        public void readFromParcel(Parcel in) {
            left = in.readInt();
            top = in.readInt();
            right = in.readInt();
            bottom = in.readInt();
        }
       //实现Parcelable接口 
        public void writeToParcel(Parcel out, int flags) {
            out.writeInt(left);
            out.writeInt(top);
            out.writeInt(right);
            out.writeInt(bottom);
        }
        public int describeContents() {
            return 0;
    }

    在使用时导入相应的Parcelable类即可。

    C++

    使用C++来实现Parcelable类相比于Java实现要复杂许多,大致包含如下几个步骤。

    1.定义aidl文件,如myParcelable.aidl,其内容如下:

    package android.com.example;
    parcelable myParcelable cpp_header “myParcelable.h”;

    2.添加对应的头文件与源码文件,如myParcelable.h与myParcelable.cpp,在头文件中声明类myParcelable并使其继承android::Parcelable,覆写virtual status_t writeToParcel(Parcel* parcel)与virtual status_t readFromParcel(const Parcel* parcel),并根据自身需要实现其他的方法即可,这里给出示例代码。

    myParcelable.h头文件:

    //myParcelable.h
    #ifndef __MY_PARCELABLE_H__
    #define __MY_PARCELABLE_H__
    
    #include <vector>
    #include <utils/Errors.h>
    #include <utils/String8.h>
    #include <utils/String16.h>
    #include <binder/Parcelable.h>
    #include <binder/Parcel.h>
    
    
    using namespace std;
    using android::Parcel;
    using android::Parcelable;
    using android::String16;
    using android::String8;
    
    
    class myPaecelable : public Parcelable
    {
    public:
      myPaecelable ();
      myPaecelable (int32_t messageId);
      ~myPaecelable ();
      virtual status_t writeToParcel(Parcel *parcel) const override;
      virtual status_t readFromParcel(const Parcel *parcel) override;
      void setMessageId(const int32_t messageId);
    
    public:
      int32_t messageId;
    };
    #endif

    myParcelable.cpp源文件

    include "myParcelable.h"
    
    myPaecelable ::myPaecelable () : messageId(0)
    {
    }
    
    myPaecelable ::~myPaecelable ()
    {
    }
    
    myPaecelable ::myPaecelable (int32_t messageId) : messageId(messageId)
    {
    }
    
    status_t myPaecelable ::writeToParcel(Parcel *parcel) const
    {
        if (parcel == nullptr)
        {
            LOGE("[myPaecelable ] parcel == nullptr");
            return BAD_VALUE;
        }
        status_t res = OK;
        res = parcel->writeInt32(messageId);
        if (res != OK)
        {
            LOGE("[myPaecelable ] writeInt32 failed, ret:[%d]", res);
            return res;
        }
        return OK;
    }
    
    status_t myPaecelable ::readFromParcel(const Parcel *parcel)
    {
        if (parcel == nullptr)
        {
            LOGE("[myPaecelable] parcel == nullptr");
            return BAD_VALUE;
        }
        status_t res = OK;
        res = parcel->readInt32(&messageId);
        if (res != OK)
        {
            LOGE("[myPaecelable] readInt32 failed, ret:[%d]", res);
            return res;
        }
        return OK;
    }
    
    void myPaecelable ::setMessageId(const int32_t messageId)
    {
        this->messageId = messageId;
    }

    在使用时导入相应的头文件即可。

    Happy
    Happy
    1 100 %
    Sad
    Sad
    0 0 %
    Excited
    Excited
    0 0 %
    Sleepy
    Sleepy
    0 0 %
    Angry
    Angry
    0 0 %
    Surprise
    Surprise
    0 0 %

    The post Android AIDL使用之Parcelable对象 first appeared on FranzKafka Blog.



沪ICP备19023445号-2号
友情链接