AIDL 实现 IPC(进程间通信)

来源:互联网 发布:测试工具 python 编辑:程序博客网 时间:2024/06/06 04:33

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.aidlpackage com.example.i_jinliangshan.aidl_server;// Declare any non-default types here with import statementsimport 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
原创粉丝点击