android进程间通讯流程分析:使用 Binder和AIDL

参照该文章进行总结:http://blog.csdn.net/saintswordsman/article/details/5130947

今天想研究下android的锁屏机制是怎么实现的,听说和桌面launcher是异步的。在看Framework代码的时候, 发现android的policy调用了一个IKeyguardService.aidl。发现它存放在fromwork/base/core目录下,而不是android的java代码下。

原来aidl就是android interface definition language 。是binder机制用到的文件。我简单说下我的理解:

1.android系统会根据aidl文件,生成同名的java文件。app项目,生成的java在gen文件夹下。(参照http://bbs.csdn.net/topics/390130973,系统编译出来的在out目录下,我还以为在framework下,搜了半天没搜到。。)

如:

out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IMediaScannerService.java
out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IMediaScannerListener.java

2.这个java文件主要是自动设计了一个Stub类。apk的xxxActivity.java通过bindService,startService与xxxService.java的onBind, onStart通讯。其中onBind实际是返回了一个mBinder,这个binder在xxxService.java里创建并初始化,这个mBinder就是Stub类如下:

  •     @Override  
  •     public IBinder onBind(Intent t) {  
  •         Log("service on bind");  
  •         return mBinder;  
  •     } 


    private final forService.Stub mBinder = new forService.Stub() {  


  •         @Override  
  •         public void invokCallBack() throws RemoteException  
  •         {  
  •             callback.performAction();  
  •               
  •         }  
  •         @Override  
  •         public void registerTestCall(forActivity cb) throws RemoteException  
  •         {  
  •             callback = cb;  
  •               
  •         }  
  •           
  •     }; 
    3.Stub类是一个抽象类,它继承了android.os.binder,并实现了forService或者forActivity(自定义的aidl接口名称)的接口,如下:

    文件forService.java中定义了Stub类和Proxy类,如下(forActivity也一样定义了这两个类):

  • public interface forService extends android.os.IInterface  
  • {   
  •     public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forService  
  •    {  
  •        private static final java.lang.String DESCRIPTOR = "com.styleflying.AIDL.forService";  
  •  
  •        public Stub()  
  •      {  
  •         this.attachInterface(this, DESCRIPTOR);  
  •      }

  •  ........

  •  
  •    private static class Proxy implements com.styleflying.AIDL.forService  
  •    {  
  •       private android.os.IBinder mRemote;  
  •       Proxy(android.os.IBinder remote)  
  •       {  
  •        mRemote = remote;  
  •        }
  •     ..........
  • }

     
    对比,forService.aidl全部代码:

    1. package com.styleflying.AIDL;  
    2. import com.styleflying.AIDL.forActivity;  
    3. interface forService {  
    4.     void registerTestCall(forActivity cb);  
    5.     void invokCallBack();  

    小结:系统自动根据forService.aidl生成了forService.java,主要是实现了Stub抽象类。forActiviy.aidl同理。


    4. 另外,Stub在哪里会调用呢?先提醒下,forService.java和forActivity.java都定义了一个Stub(存根,如第3点所述)。到这里先区分下几个文件,forService定义的是接口,而开发者会在自定义的xxService.java中调用这个文件的接口。forActivity同理。

    如第二点所述,forService的Stub在app的后台服务Service中调用。而forActiviy的Stub在app的Activiy中调用,如下:

    Activiy文件中定义

    private forActivity mCallback = new forActivity.Stub() {  


  •         public void performAction() throws RemoteException  
  •         {  
  •             Toast.makeText(mAIDLActivity.this"this toast is called from service"1).show();  
  •         }  
  •         }; 
    小结:顾名思义,forActiviy定义的接口类,都是给Activiy用的。forService同理。Activiy的Stub初始化为mCallBack,在mConnection中注册


    forService mService;

     private ServiceConnection mConnection = new ServiceConnection() {  


  •         public void onServiceConnected(ComponentName className,  
  •                 IBinder service) {  
  •             mService = forService.Stub.asInterface(service);  
  •             try {  
  •                 mService.registerTestCall(mCallback);}  
  •             catch (RemoteException e) {  
  •                   
  •             }  
  •             }  
  •         public void onServiceDisconnected(ComponentName className) {  
  •             Log("disconnect service");  
  •             mService = null;  
  •             }  
  •         }; 
    bindService的时候会调用这个mConnection:

  • btnOk.setOnClickListener(new OnClickListener() { 
  •             public void onClick(View v) {  
  •                 Bundle args = new Bundle();  
  •                 Intent intent = new Intent(mAIDLActivity.this, mAIDLService.class);  
  •                 intent.putExtras(args);  
  •                 bindService(intent, mConnection, Context.BIND_AUTO_CREATE);  
  •                 startService(intent);  
  •                 }  
  •             });

    这个注册的mCallback(回调)会被Service使用,如第2点提到的mBinder下的代码:

     callback.performAction(); 


    总结: Activiy和Service是android的四大组件之二,每个实例对应一个进程,需要使用进程间通讯Binder机制。android为了实现这个功能,通过aidl文件定义接口,然后通过系统把aidl接口文件转化为java文件,实现了IInterface接口(可能是binder机制的,我还没研究),该“java接口文件“自定为开发者定义了两个重要的类:Stub和Proxy。这两个类都implement(实现)了aidl接口。但是这两个类只是完成了IInterface需要的参数和函数设计,如asInterface等函数,并没实现具体的实现函数。

    到这里,底层的Binder机制的接口配置已经完成,于是,组件Activity和Service需要调用Stub类来通讯,而上面提到的四点,就是Stub类通讯的过程和相关函数。重新整理Android的Binder调用流程如下:

    Acitviy中

    1.初始化mConnection。

    2.通过函数bindService(intent,mConnection,Contxt.xxxx)促发Service的onBind

    3.实现mCallBack中的performAction()接口,这是核心部分,Service在适当条件下,就会调用该函数。第1个Stub,forActivity的接口实现类.注册到mConnection后,被Service调用即)。

    Service中

    4.onBind响应,返回mBinder(获得forService的Stub)。这时产生第2个Stub实例,会被下面的流程调用.


    回到Activiy中

    5.这时mConnection中的onServiceConnect响应,获得第3步产生的forService.Stub接口mService,并把mCallback注册到该接口(mCallback是forActiviy.Stub类)。这时,Service就可以通过mService获得Activiy的Stub接口了。


    到这里,Service已经可以和Activity互相通讯了,即双向通道已经打通。Service会根据不同的条件,调用mCallback(forActiviy的Stub)的实现函数,通知Activity做出相应的View操作。

  • 下面用时序图来表示,第一次画时序图,工具功能少,不太专业:


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值