您的位置:首页 > 移动开发 > Android开发

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

2014-07-25 15:41 453 查看
参照该文章进行总结: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全部代码:

package com.styleflying.AIDL;
import com.styleflying.AIDL.forActivity;
interface forService {
void registerTestCall(forActivity cb);
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操作。

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

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: