乐趣区

关于android:AIDL-简单使用

AIDL

原理图:

语法
// 包名, 文件必须放在指定的目录
package com.your.package
// 定义接口
interface IRemoteService {// 定义方法 int getPid(int pid);}
创立 AIDL 文件,并生成 Java 接口类
  • 手动
  • 主动

手动

  • 创立与 java 同级的目录 aidl
  • 在这个目录下创立和 java 包下一样的包构造
  • 编写 aidl 文件
  • ~/Library/Android/sdk/build-tools/30.0.3/aidl(我本人电脑的门路)下的 aidl 命令生成 Java 接口文件

主动

  • 在 main 目录上点击右键
  • new -> AIDL : 会主动创立一个 aidl 文件
  • 点击 build -> Make Project 就会生成相应的 Java 接口文件(文件门路:YourProject/app/build/generated/aidl_source_output_dir/debug/out/cn/kk/myaidl/)

残缺操作步骤

  1. 创立 AIDL 文件
  2. 生成对应 Java 接口类
  3. 定义 Service, 并在 AndroidManifest.xml 中注册
  4. 在自定义的 Service 类中定义成员变量 Binder, 并且初始化(实现接口办法)
  5. 在自定义的 Service 类的 onBind() 办法中,返回步骤 4 定义的 Binder 对象。
  6. 新建客户端的 module, 将服务端的 aidl -> 包名 目录下的所有文件拷贝到客户端 aidl -> 包名(和服务端包名要一样)目录下
  7. 客户端绑定服务端
  8. 在客户端调用服务端定义的办法

3. 定义 Service 并注册

在 AndroidManifest.xml 中注册:

<service android:name=".MyCalculatorService"
 android:process=":remote"
 android:enabled="true"
 android:exported="true">
</service>

7. 客户端绑定服务端

步骤 6 操作完,Make Project(在客户端依据 aidl 定义的接口 生成 Java 类)。

// 客户端绑定服务端
Intent intent = new Intent();
String aidlPackageName = "cn.kk.myaidl"; // 近程 aidl 的包名
String aidlRemoteServiceName = "cn.kk.myaidl.MyCalculatorService"; // 要绑定的近程服务名
intent.setComponent(new ComponentName(aidlPackageName, aidlRemoteServiceName));
// Context.BIND_AUTO_CREATE 绑定后,服务主动启动
bindService(intent, conn, Context.BIND_AUTO_CREATE);

// 创立成员变量 ServiceConnection conn
private ServiceConnection conn = new ServiceConnection() {@Override public void onServiceConnected(ComponentName name, IBinder service) { }
 @Override public void onServiceDisconnected(ComponentName name) {}};
 
 // 定义成员变量:private IMyCalculatorService iMyCalculatorService;  
 // 在回调办法 onServiceConnected() 里, 初始化 iMyCalculatorService:
private ServiceConnection conn = new ServiceConnection() {

     @Override 
     public void onServiceConnected(ComponentName name, IBinder service) {iMyCalculatorService IMyCalculatorService.Stub.asInterface(service); 
       }
     @Override 
     public void onServiceDisconnected(ComponentName name) { 
        // 回收资源 
        iMyCalculatorService = null; 
     }
 };

默认反对的数据类型

  • 根本数据类型(不包含 short)
  • String, CharSequence
  • List, Map
  • Parcelable

创立自定义类型的数据(罕用)

服务端操作:

  1. 创立 Human.java 类。
  2. 序列化这个类
  3. 创立 Human.aidl 文件
  4. 在 AIDL 接口文件中,应用 Human 自定义类型
  5. Make Project
  6. 在服务端的 Service 外面实例化接口,重写接口办法, onBind() 外面返回这个实例化对象

2. 序列化这个类

  1. 实现接口:Parcelable
  2. 重写办法:describeContents() 和 writeToParcel(Parcel dest, int flags)
  3. writeToParcel() 办法重写:dest.writeString(name); dest.writeInt(age); ...
  4. 实例化变量:Creator<Human> CREATOR
  5. 创立 Human 新的构造方法:
4. 实例化变量:Creator<Human> CREATOR
 public static final Creator<Human> CREATOR = new Creator<Human>() {    
 
     @Override 
     public Human createFromParcel(Parcel source) {return new Human(source); 
     }
     @Override 
     public Human[] newArray(int size) {return new Human[0]; 
     } 
};
 
5. 创立 Human 新的构造方法:
 public Human(Parcel source) {// 这个操作程序肯定要和 writeToParcel() 的程序统一 
     this.name = source.readString(); 
     this.age = source.readInt();}

3. 创立 Human.aidl 文件

在 aidl 目录中,参照 Human.java 的包名,在对应的门路创立 Human.aidl 文件,内容如下:

package cn.kk.myaidl.bean;
parcelable Human;
4. 在 AIDL 接口文件中,应用 Human 自定义类型
  1. 导入自定义类:import cn.kk.myaidl.bean.Human;
  2. 定义方法,如:List<Human> addHuman(in Human h);
6. 在服务端的 Service 外面实例化接口,重写接口办法
 private IBinder iHumanBinder = new IHumanInterface.Stub() {
 
    @Override 
    public List<Human> addHuman(Human h) throws RemoteException {humanArrayList.add(h); 
         return humanArrayList; 
     }
 };

客户端操作:

  1. 将服务端新最新的 aidl 文件都复制过去
  2. 将服务端定义的类型:Human.java 连同包构造复制到客户端 src/main/java/ 下
  3. 在 Activity 中绑定服务的回调用,用 iHumanInterface(IHumanInterface 类型) 接管返回值:

    private ServiceConnection conn = new ServiceConnection() {
        @Override 
        public void onServiceConnected(ComponentName name, IBinder service) {iHumanInterface = IHumanInterface.Stub.asInterface(service); 
            Log.d(TAG, "onServiceConnected:"); 
        }
        @Override 
        public void onServiceDisconnected(ComponentName name) {
        // 回收资源
        //            iMyCaculatorService = null;
        iHumanInterface = null;
        Log.d(TAG, "onServiceDisconnected:"); 
        } 
      };  
  4. 新创建一个点击事件,在点击事件中操作新的接口:
 private List<Human> add(Human human) throws RemoteException {return iHumanInterface.addHuman(human); 
 } 
 
 btnAddHuman.setOnClickListener(v -> { 
     try {add(new Human("秦始皇",33));   
         add(new Human("汉武帝",53)); 
         add(new Human("唐太宗",55)); 
         List<Human> humans = add(new Human("宋太祖", 65));
         for (Human human : humans) {Log.d(TAG, "onClick:" + human.getName() + "," + human.getAge());
         } 
     } catch (RemoteException e) {e.printStackTrace(); 
     } 
 });
  1. 运行 (先启动服务端,再启动客户端) 后输入日志:
onClick: 秦始皇,33
onClick: 汉武帝,53
onClick: 唐太宗,55
onClick: 宋太祖,65

代码之后再上传。。。

退出移动版