Android接口定义语言(AIDL)

最近有使用商米v2的打印机功能,涉及到AIDL,所以这篇简单讲解下 AIDL ,最后附上打印机代码。

顾名思义AIDL全称是Android Interface Definition Language

Android中一个进程通常无法访问另一个进程的内存,这时候可以利用它定义客户端与服务使用进程间通信 (IPC) 进行相互通信时都认可的编程接口. 当然AIDL的目的不仅仅是为了实现进程间通信,尤其是在涉及多进程并发情况下的进程间通信

服务端部分

1:创建.aidl文件

创建服务端项目后,在main下新建aidl文件夹,用于存放我们用到的aidl文件。
这里以Android studio为例:
我们可以直接右键新建aidl文件如下:
在这里插入图片描述
新建的aidl文件,会默认添加个方法用于演示一些基本数据类型,如下图所示:
在这里插入图片描述
AIDL 使用简单语法,使您能通过可带参数和返回值的一个或多个方法来声明接口。 参数和返回值可以是任意类型,甚至可以是其他 AIDL 生成的接口。
每个 .aidl 文件都必须定义单个接口,并且只需包含接口声明和方法签名。

默认情况下,AIDL 支持下列数据类型:
1:Java 编程语言中的所有原语类型(如 int、long、char、boolean 等等)
2:String
3:CharSequence
4:List
List 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 可选择将 List 用作“通用”类(例如,List)。另一端实际接收的具体类始终是 ArrayList,但生成的方法使用的是 List 接口。
5:Map
Map 中的所有元素都必须是以上列表中支持的数据类型、其他 AIDL 生成的接口或您声明的可打包类型。 不支持通用 Map(如 Map<String,Integer> 形式的 Map)。 另一端实际接收的具体类始终是 HashMap,但生成的方法使用的是 Map 接口。

除了以上列出的类型外,我们必须为每个附加类型加入一个 import 语句,即使这些类型是在与接口相同的软件包中定义。

另外定义接口时,我们需要注意以下几点:

1:方法可带零个或多个参数,返回值或空值。
2:所有非上述类型的参数都需要指示数据走向的方向标记。可以是 in、out 或 inout。
上述参数默认为 in,不能是其他方向。
3:.aidl 文件中包括的所有代码注释都包含在生成的 IBinder 接口中(import 和 package 语句之前的注释除外)
4:只支持方法;不能公开 AIDL 中的静态字段。

非原参类型定义方法,即我们通常定义的bean类,
创建java文件定义参数,实现Parcelable接口,自动导入对应的接口方法。

package com.zh.server;

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

/**
 * create by zj on 2019/6/4
 */
public class People implements Parcelable {

    public int sno;
    public String name;
    public int sex;
    public int age;

    protected People(Parcel in) {
        sno = in.readInt();
        name = in.readString();
        sex = in.readInt();
        age = in.readInt();
    }

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

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeInt(sno);
        dest.writeString(name);
        dest.writeInt(sex);
        dest.writeInt(age);
    }


}

接着在aidl文件夹下生产同名的people.aidl文件。
内容十分简单:

package com.zh.server;

parcelable People;

注意:parcelable 是小写

package com.zh.server;

// Declare any non-default types here with import statements
import com.zh.server.People;
interface IMyAidlInterface {


    /**
     * Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);

    List<People> getPeople();
    void addPeople(in People people);
}

添加自定义的类型参数,import必须导入全路径。
添加获取对象集合以及添加对象的方法

2:实现接口

添加java文件继承service;

package com.zh.server;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.support.annotation.Nullable;
import java.util.ArrayList;
import java.util.List;

/**
 * create by zj on 2019/6/4
 */
public class MyService extends Service {

    private List<People> peopleList = new ArrayList<People>();
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    private IMyAidlInterface.Stub mBinder=new IMyAidlInterface.Stub() {

        public void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
                               double aDouble, String aString){

        }

        @Override
        public List<People> getPeople() throws RemoteException {
            synchronized (peopleList) {
                return peopleList;
            }
        }

        @Override
        public void addPeople(People people) throws RemoteException {
            synchronized (peopleList) {
                if (!peopleList.contains(people)) {
                    peopleList.add(people);
                }
            }
        }
    };
}

3:Service定义

 <service android:name=".MyService" >
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />
                <action android:name="com.zh.server.MyService" />
            </intent-filter>
        </service>

截止这里服务端的代码已经完成,接下来我们可以编写调用的代码了。

客户端代码

1:拷贝aidl文件

将服务端的aidl连同文件目录拷贝到main的aidl目录下。
当然,因为有自定义对象参数的问题,所以我们需要复制bean类,
aidl中bean的导入路径也需要修改。

2:调用相关

首先定义ServiceConnection:

  private ServiceConnection serviceConnection=new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            myAidlInterface=IMyAidlInterface.Stub.asInterface(service);
            try {
                List<People> list=myAidlInterface.getPeople();
                StringBuilder sb=new StringBuilder();
                for (int i=0;i<list.size();i++){
                    sb.append(list.get(i).name+"\n");
                }
                //数据展示
                binding.tvInfo.setText(sb.toString());
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            myAidlInterface=null;
        }
    };

接着就是bindservice

 Intent intentService = new Intent();
intentService.setPackage("com.zh.server");
intentService.setAction("com.zh.server.MyService");
MainActivity.this.bindService(intentService, serviceConnection, BIND_AUTO_CREATE);

看下效果:
在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值