以MediaPlayer 服务为例
在Android 平台里,上层应用程序的service 与底层的系统service 有很大的
区别,只是许多人都将它们混在一起了。例如,在Android 里著名的MediaPlayer
范例,许多人都知道其结构为:
其中有两个service:
1、应用程序开发者所写的myPlayerService.java 类别。这是属于一般所称的SDK service。
2、Android 已经提供的MediaPlayerService.cpp 类别。这是属于一般所称的系统service。
主要的系统service 都是在Android 系统启动时,就会先逐一登记到
BD(Binder Driver)里,随时准备为SDK 应用程序进行服务。
天字第一号的系统server 就是ServiceManager。当Android 系统启动时,就
会优先将之登记到BD(Binder Driver)里,如下图:
让其它组件能透过IBinder 接口(可转型为IServiceManager 接口)而远距呼叫
ServiceManager 的服务。于是陆续会有更多的系统service 呼叫ServiceManager
的addService()函数而登记到BD 里成为可远距呼叫的系统service。例如,基于
上述途径,ActivityManagerService 就会登记为可远距呼叫的系统service。再如,
MediaPlayerService 也继续登记为基本的系统service,于是MediaPlayerService
也具有IBinder 接口了。
当Android 系统启动完成之后,就可以执行应用程序了。
执行应用程序时,就由ActivityManagerService 来将SDK service(如
myPlayerService.java 类别)也会登记到Binder Driver 里,于是应用程序里的
Activity 等类别就能使用bindService 里系结(bind)到myPlayerService,然后透过
IBinder 接口而远程呼叫到myPlayerService。
之后,myPlayerService 再透过图1 的结构而呼叫到MediaPlayerService,进而
呼叫到OpenCode 组件了。
两层服务的对应关系
Binder.java 是Android 应用框架里的重要组件,由于它提供了IBinder 接口,
让Activity 等组件能透过IBinder 接口而远程呼叫应用程序里的Service 组件。对
于Binder.java 类别,我们可以从不同角度来看它所扮演的角色。
从应用程序的Service 组件来看,Binder.java 就扮演Service 的接口对象角
色。当Activity 类别想呼叫远程的Service 类别之函数时,可要求Service 类别诞
生一个Binder.java 类别的对象,由它提供IBinder 接口给Activity 组件,就搭起
Activity 与Service 组件之间的沟通桥梁了。
从IPC(Inter-Process Communication)角度来看,上述的沟通桥梁是跨进程的
IPC 沟通机制。Binder.java 会透过JNI 接口与本地(Native)的底层Binder 服务沟
通合作。在Activity 和Service 所在的进程之间建立Proxy/Stub 机制,以完成
Activity 与Service 之间的连结(Connection)。一旦完成连结之后,Activity 就能透
过IBinder 接口而呼叫Service 的函数,Proxy/Stub 机制还会进行跨进程的
Marshalling 动作,协助Activity 与Service 之间跨进程的数据交换。
从框架(Framework)的角度来看,他只是Android 里的BBinder.cpp 类别在Java
层的一个代表者,它以父类别(Superclass)形式出现,提供给Java 层的应用类别(如
myBinder.java)来继承,协助底层的Binder System(设计在先)能取得应用类别(设
计在后)的客制化部分的信息。例如有了Binder.java 的协助,Binder System 得以
从呼叫Service 的onBind()函数而得知如何呼叫myBinder.java 所客制化的
onTransact()函数,如此让Android 框架幕后的Binder System 能与目前的
myBinder.java 应用类别结合起来,而达到框架的目的了。
表面上,myActivity.java 类别(Activity.java 的子类别)呼叫
myBinder.java(Binder.java 的子类别)的transact()函数及onTransact()函数,在实践
机制里,myActivity.java 是透过Connection 对象去与BBinder.cpp 沟通,然后
BBinder.cpp 才返向呼叫myBinder.java 里的transact()和execTransact()等函数。由
于myActivity.java 与myService.java 之呼叫是透过BBinder.java 等底层对象来达
成的,它们之间进行数据交换时,底层就有机会进行Marshalling 动作,而达成
IPC 沟通了。请看下述程序代码:
// myActivity.java
public class myActivity extends Activity implements OnClickListener {
……..
public void onCreate(Bundle icicle) {
……..
startService(new Intent("com.misoo.pk01.REMOTE_SERVICE"));
……..
}
}}
// myService.java
public class myService extends Service {
private IBinder mb = null;
………..
@Override public void onStart() {
mb = new myBinder();
}
}
当myActivity 呼叫startService()时,就呼叫Service.onStart()函数,执行到指令:
mb = new myBinder()
接着,呼叫myBinder()建构式(Constructor);进而呼叫父类别Binder()建构式,转而
呼叫Native 的init()函数。如下图:
继续看下述的程序代码:
// myActivity.java
public class myActivity extends Activity implements OnClickListener {
IBinder mb = null;
……..
public void onCreate(Bundle icicle) {
……..
startService(new Intent("com.misoo.pk01.REMOTE_SERVICE"));
bindService(new Intent("com.misoo.pk01.REMOTE_SERVICE"),
mConnection, Context.BIND_AUTO_CREATE);
……..
}
private ServiceConnection mConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder
ibinder) {
mb = ibinder;
}
};
…….
public void onClick(View v) {
……
mb.transact(…);
……
}
}}
// myService.java
public class myService extends Service {
private IBinder mb = null;
………..
@Override public void onStart() {
mb = new myBinder();
}
@Override public IBinder onBind(Intent intent) {
return mb;
}
}
当myActivity 继续呼叫bindService()时,如果找到该服务,且它尚未被任
何Client 所绑定的话,就会呼叫myService 的onBind()函数。此时,执行到指
令:
return mb;
也就建立出一个连结(Connection),如下图:
Activity 透过Connection 而呼叫到myBinder 里的onTransact()函数。
我们可以将C++的BBinder 和JavaBBinder 类别视为引擎;将Java 层的
Binder 父类别视为轮盘;并且将myBinder 子类别视为轮胎。从上述汽车之比
喻,可更清楚理解Android 架构之重要意义:实现强龙与地头蛇分工合作的美
好商业模式。在此商业模式里,地头蛇的获利空间很大,愿意尽力服务客户,
大力维护 强龙的利益。