转载自:http://www.cnblogs.com/allin/archive/2010/05/15/1736462.html
通常每个应用程序都在它自己的进程内运行,但有时需要在进程间传递对象,你可以通过应用程序UI的方式写个运行在一个不同的进程中的service。在android平台中,一个进程通常不能访问其他进程中的内存区域。所以,他们需要把对象拆分成操作系统能理解的简单形式,以便伪装成对象跨越边界访问。编写这种伪装代码相当的枯燥乏味,好在android为我们提供了AIDL工具可以来做这件事。
AIDL(android接口描述语言)是一个IDL语言,它可以生成一段代码,可以使在一个android设备上运行的两个进程使用内部通信进程进行交互。如果你需要在一个进程中(例如:在一个Activity中)访问另一个进程中(例如:一个Service)某个对象的方法,你就可以使用AIDL来生成这样的代码来伪装传递各种参数。
要使用AIDL,Service需要以aidl文件的方式提供服务接口,AIDL工具将生成一个相应的java接口,并且在生成的服务接口中包含一个功能调用的stub服务桩类。Service的实现类需要去继承这个stub服务桩类。Service的onBind方法会返回实现类的对象,之后你就可以使用它了,参见下例:
先创建一个IMyRemoteService.aidl文件
1 |
package org.allin.android.remote; |
2 |
interface IMusicControlService{ |
如果你正在使用eclipse的Android插件,则它会根据这个aidl文件生成一个Java接口类。生成的接口类中会有一个内部类Stub类,你要做的事就是去继承该Stub类:
06 |
public class RemoteMusicService extends Service { |
08 |
private static final String TAG = "RemoteMusicService" ; |
09 |
private MediaPlayer mediaPlayer; |
17 |
public IBinder onBind(Intent intent) { |
21 |
private final IMusicControlServic<SCRIPT type=text/javascript><!--mce: 1 --></SCRIPT>e.Stub binder = new IMusicControlService.Stub() { |
24 |
public void stop() throws RemoteException { |
25 |
Log.d(TAG, "stop...." ); |
26 |
if (mediaPlayer != null ) { |
30 |
mediaPlayer.prepare(); |
31 |
} catch (IOException ex) { |
39 |
public void play() throws RemoteException { |
40 |
Log.d(TAG, "play...." ); |
41 |
if (mediaPlayer == null ) { |
42 |
mediaPlayer = MediaPlayer.create(RemoteMusicService. this , |
44 |
mediaPlayer.setLooping( false ); |
46 |
if (!mediaPlayer.isPlaying()) { |
52 |
public void pause() throws RemoteException { |
53 |
Log.d(TAG, "pause...." ); |
55 |
if (mediaPlayer != null && mediaPlayer.isPlaying()) { |
64 |
public void onDestroy() { |
67 |
Log.d(TAG, "onDestroy" ); |
68 |
if (mediaPlayer != null ){ |
70 |
mediaPlayer.release(); |
当客户端应用连接到这个Service时,onServiceConnected方法将被调用,客户端就可以获得IBinder对象。参看下面的客户端onServiceConnected方法:
01 |
private ServiceConnection sc = new ServiceConnection() { |
04 |
public void onServiceDisconnected(ComponentName name) { |
06 |
Log.d(TAG, "in onServiceDisconnected" ); |
10 |
public void onServiceConnected(ComponentName name, IBinder service) { |
11 |
musicService = IMusicControlService.Stub.asInterface(service); |
12 |
Log.d(TAG, "in onServiceConnected" ); |
启动后的界面如下
[源码下载]