2. ServiceManager启动与Binder上下文

任务说明

本案例目标:创建一个用于进程间通信的AIDL接口文件,通过Android Studio的构建机制自动生成对应的Java接口、Stub(服务端基类)与Proxy(客户端代理)类,并验证生成结果。

实现步骤

在Android Studio中新建项目(包名示例:com.example.aidlserver),按以下步骤操作:

  1. 在src/main/aidl/com/example/aidlserver/目录下创建AIDL文件;
  2. 定义接口方法(含自定义数据类型的传递);
  3. 执行Build → Make Project触发AIDL编译器;
  4. 在build/generated/aidl_source_output_dir/下检查生成的Java文件。

AIDL接口定义

创建文件 src/main/aidl/com/example/aidlserver/IWeatherService.aidl:

// IWeatherService.aidl
package com.example.aidlserver;

// 自定义数据类型必须显式import
import com.example.aidlserver.WeatherData;

interface IWeatherService {
    // 基础类型方法
    String getCityName();

    // 自定义Parcelable对象传递
    WeatherData getCurrentWeather();

    // 带输入输出参数的方法(in/out/inout方向)
    boolean updateWeather(in String city, inout WeatherData data);
}

由于AIDL支持自定义Parcelable对象,需在同目录创建 WeatherData.aidl:

// WeatherData.aidl
package com.example.aidlserver;
parcelable WeatherData;

对应的Java实现类 WeatherData.java(放在src/main/java/com/example/aidlserver/下)必须实现Parcelable接口:

package com.example.aidlserver;

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

public class WeatherData implements Parcelable {
    public String city;
    public float temperature;
    public String condition;

    public WeatherData(String city, float temperature, String condition) {
        this.city = city;
        this.temperature = temperature;
        this.condition = condition;
    }

    protected WeatherData(Parcel in) {
        city = in.readString();
        temperature = in.readFloat();
        condition = in.readString();
    }

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

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

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

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(city);
        dest.writeFloat(temperature);
        dest.writeString(condition);
    }
}

构建与生成验证

完成上述文件创建后,执行Build → Make Project。构建成功后,在项目视图切换到Project模式,展开目录:

app/build/generated/aidl_source_output_dir/debug/out/com/example/aidlserver/

预期生成以下三个Java文件(由AIDL编译器自动生成):

  • IWeatherService.java —— 接口定义,包含内部类Stub和Proxy;
  • IWeatherService.Stub —— 抽象静态类,服务端继承此类并实现接口方法;
  • IWeatherService.Stub.Proxy —— 客户端使用的代理类,封装transact()调用。

生成代码核心结构说明

自动生成的IWeatherService.java中关键组成如下(仅示意结构,实际代码由编译器生成):

public interface IWeatherService extends android.os.IInterface {
    // 从IBinder获取接口引用
    public static abstract class Stub extends android.os.Binder implements IWeatherService {
        // 服务端继承此类,实现业务方法
    }

    // 客户端通过Stub.asInterface()获得Proxy实例
    private static class Proxy implements IWeatherService {
        // 内部通过mRemote.transact()发送调用数据
    }
}

验证方法与判定标准

验证AIDL生成是否成功,按以下步骤操作:

  1. 构建检查:执行Make Project后,Build窗口显示BUILD SUCCESSFUL,无AIDL语法错误;
  2. 文件检查:在build/generated/aidl_source_output_dir/下能找到上述三个Java文件,且IWeatherService.java中同时包含Stub和Proxy内部类;
  3. 接口完整性:打开生成的IWeatherService.java,确认其中包含getCityName()、getCurrentWeather()、updateWeather()三个抽象方法,且方法签名与AIDL定义一致;
  4. 方向标记验证:在updateWeather()的transact代码中,能看到对in(写入Parcel)和out/inout(读取Parcel)参数的不同处理逻辑。

满足以上条件,即证明AIDL文件定义正确且自动生成流程完整可用。

AIDL 编译生成流程与产物结构 源码输入 IWeatherService.aidl WeatherData.aidl WeatherData.java (Parcelable) AIDL 编译器 aidl-cpp / build-tools Android Studio Make Project 触发 生成产物 IWeatherService.java ├─ interface IWeatherService ├─ Stub (Binder基类) └─ Stub.Proxy (客户端代理) 验证观测点 ① 构建成功 Build窗口显示 BUILD SUCCESSFUL 无AIDL语法/import错误 ② 文件生成位置 build/generated/aidl_source_output_dir/ debug/out/com/example/aidlserver/ ③ 接口完整性 包含 getCityName / getCurrentWeather / updateWeather 三个方法签名 ④ 方向标记处理 in参数写入Parcel,out/inout参数 从Parcel读取,代码逻辑可区分