理解 Java 调用 Native 服务

146 阅读3分钟

通俗易懂地讲解这篇文章的内容:


用打电话理解 Java 调用 Native 服务

​背景故事​
假设你(Java 程序)想找一位会说 C++ 的专家(Native 服务)帮你算一道数学题,但你们不在同一个房间(不同进程)。这时你们需要一个“电话系统”(Binder 机制)来沟通。


临时方案:直接“打电话”

(对应文章的第一种方法)

  1. ​查电话号码本​
    你翻开电话本(ServiceManager),找到专家的名字(服务名 "IHello"),记下他的电话号码(IBinder对象)。
  2. ​准备纸条​
    你拿一张纸条(Parcel data),用约定的暗号写上问题(writeInterfaceToken)。再准备一张空白纸条(Parcel reply)等待答案。
  3. ​拨打电话​
    拨通电话(binder.transact),把问题纸条传过去。专家在电话那头计算答案,把结果写在空白纸条上传回来。
  4. ​读答案​
    你收到回复纸条(replay.readInt()),看到结果是 0,虽然正确但不够直观(直接操作 Parcel 比较原始)。

​缺点​​:就像每次都要手写纸条、记暗号,容易出错,代码维护困难。


标准方案:用“智能翻译电话”

(对应文章的 AIDL 方法)

  1. ​定义共通语言​
    你和专家约定一套标准的对话模板(AIDL 文件),比如:

    aidl
    Copy
    interface IHello {
      void hello();
      int sum(int a, int b);
    }
    
  2. ​自动生成翻译器​
    系统会根据模板自动生成“翻译器”(IHello.java),把 Java 的调用翻译成纸条(Parcel),反之亦然。

  3. ​优雅的通话​
    现在你只需要像普通方法一样调用:

    java
    Copy
    IHello svr = IHello.Stub.asInterface(binder); // 获取智能电话
    svr.hello(); // 直接说“你好”
    int result = svr.sum(3, 4); // 直接问“3+4等于几”
    

    背后的翻译器自动帮你处理纸条的读写,就像同声传译。

​优点​​:代码简洁,就像用智能手机直接语音对话,不用操心纸条怎么写。


关键技术点

  • ​电话本​​(ServiceManager):系统服务登记处,通过名字(如 "IHello")查找服务。
  • ​电话线​​(IBinder):通信通道,实际类型是 BinderProxy(代理对象)。
  • ​纸条​​(Parcel):跨进程传递数据的容器,支持基本类型和复杂对象。
  • ​智能翻译​​(AIDL):自动生成代码,隐藏 Parcel 操作细节,让调用像本地方法一样简单。

为什么推荐标准方案?

就像现代人更愿意用微信语音而不是发电报,AIDL 生成的代码:

  1. ​更安全​​:自动处理接口校验(DESCRIPTOR)。
  2. ​更易维护​​:接口修改时只需更新 AIDL 文件。
  3. ​更直观​​:直接调用方法,无需手动读写 Parcel。

总结

文章教了两种“打电话”方式:
1️⃣ 原始方式:手写纸条,适合临时测试。
2️⃣ 标准方式:用智能翻译电话,适合正式项目。
掌握这两种方法,就能让 Java 和 C++ 服务像“打电话”一样轻松沟通!

(注:实际开发中推荐使用 AIDL 标准方案,就像我们现在更习惯用智能手机而非电报机😉)