欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Aidl进阶 ----- 自定义类型传输

程序员文章站 2022-03-25 08:22:48
2020.8.7 第一次编辑。。。未完待续。。。package com.zhouxi.client;import androidx.appcompat.app.AppCompatActivity;import android.content.ComponentName;import android.content.Context;import android.content.Intent;import android.content.ServiceConnection;import a....

2020.8.7 第一次编辑。。。未完待续。。。 

2020.8.11 第二次编辑。。。未完待续。。。

2020.8.12 第三次编辑。。。未完待续。。。

本片文章的目录结构如下:

AidlParcelableDemo
   |--client                                    
   |     |--src
   |     |   |--main
   |     |        |--aidl
   |     |        |    |--com.zhouxi.client
   |     |        |            |--IAidlService.aidl------------------------(1)
   |     |        |            |--ParcelableInfo.aidl----------------------(2)
   |     |        |--java
   |     |        |    |--com.zhouxi.client
   |     |        |            |--MainActivity.java------------------------(3)
   |     |        |            |--ParcelableInfo.java----------------------(4)
   |     
   |--aidlservice
   |     |--src
   |     |   |--main
   |     |        |--aidl
   |     |        |    |--com.zhouxi.client
   |     |        |            |--IAidlService.aidl-----------------------(5)
   |     |        |            |--ParcelableInfo.aidl---------------------(6)
   |     |        |--java
   |     |        |    |--com.zhouxi.client
   |     |        |            |--AidlService.java------------------------(7)
   |     |        |            |--ParcelableInfo.java---------------------(8)

                              AidlParcelableDemo目录结构

上一篇文章介绍了 AIDL的基础知识,通过样例代码展示了AIDL的执行过程----两个apk之间通过AIDL接口传递数据,也就是通信,但是上文中传递的数据主要是基本数据类型。实际上AIDL也支持传递其他数据类型,例如自定义数据类型,本片文章主要聚焦在自定义数据类型的传递(中间不过度的说明AIDL的原理,不理解的可以先看上一篇文章),先上client的代码。

package com.zhouxi.client;

import androidx.appcompat.app.AppCompatActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
import android.view.View;

public class MainActivity extends AppCompatActivity implements View.OnClickListener {
    public static final String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        findViewById(R.id.bindAidlService).setOnClickListener(this);
        findViewById(R.id.unbindAidlService).setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        if (v.getId() == R.id.bindAidlService) {
            Intent intent = new Intent();
            intent.setAction("com.zhouxi.service.AidlService");
            intent.setPackage("com.zhouxi.service");
            bindService(intent, aidlServiceConnection, Context.BIND_AUTO_CREATE);
        } else if (v.getId() == R.id.unbindAidlService) {
            Log.e(TAG, "onClick: unbindAidlService");
            unbindService(aidlServiceConnection);
        }
    }

    public ServiceConnection aidlServiceConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            ParcelableInfo inParcelableInfo = new ParcelableInfo("这是一条传入的自定义类型");
            Log.e(TAG, "onServiceConnected: bind AidlService success.");
            IAidlService aidlService = IAidlService.Stub.asInterface(service);
            try {
                Log.e(TAG, "onServiceConnected: the info of AidlService: " + aidlService.getServiceInfo(inParcelableInfo).getInfo());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            Log.e(TAG, "onServiceConnected: bind AidlService fail.");
        }
    };
}

该apk定义了两个按钮用来绑定和解绑AidlService,在绑定成功后,AidlService会返回自身的代理类,也就是 

IAidlService aidlService = IAidlService.Stub.asInterface(service);

 获取到代理类后就可以通过AIDL接口访问AidlService中的数据了(具体还要看接口实现),查看aidl文件,IAidlService定义了getServiceInfo方法,传入ParcelableInfo的自定义数据类型,返回值也是该类型,在这先把这个数据类型想象看基本数据类型来理解。

// IAidlService.aidl
package com.zhouxi.client;

import com.zhouxi.client.ParcelableInfo;

interface IAidlService {
    ParcelableInfo getServiceInfo(in ParcelableInfo inParcelableInfo);
}

查看AidlService中对于这个接口的具体实现 

package com.zhouxi.client;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import androidx.annotation.Nullable;

public class AidlService extends Service {
    private static final String TAG = AidlService.class.getSimpleName();

    @Override
    public void onCreate() {
        Log.e(TAG, "onCreate: AidlService is onCreate.");
        super.onCreate();
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.e(TAG, "onStartCommand: AidlService is onStartCommand.");
        return super.onStartCommand(intent, flags, startId);
    }

    @Override
    public void onDestroy() {
        Log.e(TAG, "onDestroy: AidlService is onDestroy.");
        super.onDestroy();
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        Log.e(TAG, "onBind: AidlService is onBind.");
        return new AidlBinder();
    }

    @Override
    public boolean onUnbind(Intent intent) {
        Log.e(TAG, "onUnbind: AidlService is onUnbind.");
        return super.onUnbind(intent);
    }

    class AidlBinder extends IAidlService.Stub {
        @Override
        public ParcelableInfo getServiceInfo(ParcelableInfo inParcelbleInfo) {
            Log.e(TAG, "the inParcelbleInfo is: " + inParcelbleInfo.getInfo());
            inParcelbleInfo.setInfo("这是一条传出的自定义类型");
            return inParcelbleInfo;
        }
    }
}

可以看出,AidlService中实现了IAidlService的接口方法,将入参inParcelbleInfo的字段修改成别的信息并输出,整个apk间的调用关系就结束了,接下来聚焦如何实现自定义类型通过AIDL接口传递

首先新建自定义类型ParcelableInfo同时实现Parcelable接口,IDE会自动提示实现并覆盖Parcelable接口的方法

设置ParcelableInfo所需要的字段和方法即可

从上面可以看出,用来AIDL接口传递的自定义类型生成很简单,新建类--实现类中的功能--实现Parcelable接口--Alter+Enter自动实现接口方法即可

package com.zhouxi.client;

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

public class ParcelableInfo implements Parcelable {
    private String info;

    public ParcelableInfo(String info) {
        this.info = info;
    }

    protected ParcelableInfo(Parcel in) {
        info = in.readString();
    }

    public void setInfo(String info) {
        this.info = info;
    }

    public String getInfo() {
        return info;
    }

    /**
     * 反序列化
     */
    public static final Creator<ParcelableInfo> CREATOR = new Creator<ParcelableInfo>() {
        @Override
        public ParcelableInfo createFromParcel(Parcel in) {
            return new ParcelableInfo(in);
        }
        @Override
        public ParcelableInfo[] newArray(int size) {
            return new ParcelableInfo[size];
        }
    };

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

    /**
     * 序列化过程
     *
     * @param dest
     * @param flags
     */
    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(info);
    }
}

对于自定义类型,还需要与之相对应的aidl文件来声明,具体如下,只需要简单的声明声明parcelable类型以及自定义类型名字ParcelableInfo即可,两个aidl文件都需要放置在aidl文件夹下面,同时要保证client和service的包名保持一致。

// ParcelableInfo.aidl
package com.zhouxi.client;

// Declare any non-default types here with import statements

parcelable ParcelableInfo;

需要了解更多的,可以之前写的aidl入门文章

 

 

 

本文地址:https://blog.csdn.net/weixin_48968045/article/details/107853418