AIDL 实现 IPC(进程间通信)

1 篇文章 0 订阅
1 篇文章 0 订阅

AIDL


AIDL 即安卓接口定义语言,其语法类似 java,用于定义一些特殊的接口。


由来

就以 service 为例:
android 常以 service 提供一些服务和数据,acticity 通过 binder 与service 进行数据交换(如 get 和 set )。然而,有时候 acticity 需要访问远程的 service (如别的应用程序提供的 service),之前的方案就不再适用。为了解决这种跨进程通信的需求,android 引入了 AIDL 机制。


使用


说明

由于安卓中不同进程的内存是不共享的,在 onBind() 中我们不再像原来那样返回 Binder 的子类,而是返回 AIDL 的接口类。
这里给的例子是 C- S 模式,Server 和 Client 是两个不同的 app,不能共享内存。
Server 端运行一个 Service 播放音乐,对外提供 AIDL 接口 play() 和 pause();
Client 端通过调用它来和 Service 交互(控制音乐)。


服务端 server

  • 新建一个 .aidl 文件(IMusicService.aidl),定义一些访问 service 的接口,如 get,set,或者别的什么操作:
// IMusicService.aidl
package com.example.i_jinliangshan.aidl_server;

// Declare any non-default types here with import statements
import com.example.i_jinliangshan.aidl_server.Music;

interface IMusicService {
    void play();
    void pause();
    Music getMusic(); //对于自定义类,还得进行序列化
}


  • 编译一下 app (build -> make),编译器会自动生成对应的 IMusicService.java,
    也就是 java 版本的接口。

  • 在 Service 中,弄一个类实现这个接口,并在 onBind 中返回。

   // Stub 是编译器自动生成的,点进去可以看到,它 implements 了 IMusicService 的接口
   public class AIDLBinder extends IMusicService.Stub {
       @Override
       public void play() throws RemoteException {
           MusicService.this.play();
       }

       @Override
       public void pause() throws RemoteException {
           MusicService.this.pause();
       }

       @Override
       public Music getMusic() throws RemoteException {
           return music;
       }
   }
   //--------------------------
       @Override
    public IBinder onBind(Intent intent) {
        Log.d(TAG, "onBind");
        String mod = intent.getStringExtra("bind_mod");
        Log.d("intent mod:", mod);
        if(mod.equals("local"))
            return new LocalBinder();    // 这个 LocalBinder 是原来的方式
        else if(mod.equals("remote"))
            return new AIDLBinder();     // AIDL 的方式
        return null;
    }


客户端 Client

由于 Client 在另一个 app 里,必须将 Server 端定义的 AIDL 接口统统复制过来,才能使用。


  • 用隐式 intent 的方式绑定服务端的 service,在 onServiceConnected() 中获取 AIDL 接口实例
    // 绑定 service 
    // 服务端 AndroidManifest.xml 中的 intent-filter action 声明的字符串
    public static final String ACTION = "com.example.i_jinliangshan.aidl_server.MusicService";
    @Override
    protected void onStart() {
        super.onStart();
        intent = new Intent(ACTION);
        intent.putExtra("bind_mod", "remote");
        bindService(intent, sc, BIND_AUTO_CREATE);
    }

    // 获取 binder
    private IMusicService binder;
    private ServiceConnection sc = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName componentName, IBinder iBinder) {
            binder = IMusicService.Stub.asInterface(iBinder);
        }

        @Override
        public void onServiceDisconnected(ComponentName componentName) {
        }
    };


  • 用 binder.play() 和 binder.pause() 控制远程的音乐播放服务。

总结

总的来说,AIDL 以面向接口的方式实现了跨进程调用的需求,客户端和服务端各司其职,有利于模块间的分离。
PS:AIDL 默认的是同步调用,如果调用 Server 端的耗时任务,不应在 Client 端的 UI 线程中,而应另起一个线程。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值