`
w0rchid
  • 浏览: 12000 次
  • 性别: Icon_minigender_1
  • 来自: 南京
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

AIDL介绍

 
阅读更多
感谢分享,原创地址:
http://blog.csdn.net/saintswordsman/archive/2010/01/04/5130947.aspx
欢迎阅读本文,你能关注本文,你知道你需要进程间通信、需要AIDL(以及Binder),那么可以默认你对这些概念已经有了一些了解,你(大致)知道它们是什么,它们有什么用,所以为了节约大家的眼力和时间,在此我不复制粘贴网上泛滥的博客或者翻译冗长的android文档。
关于AIDL的介绍在文档:docs/guide/developing/tools/aidl.html
关于IBinder的介绍在文档:docs/reference/android/os/IBinder.html
以及Binder:docs/reference/android/os/Binder.html
在后文中,我将以我自己的理解向你介绍相关的概念。以我目前粗浅的经验,应用程序使用AIDL的地方,几乎都和Service有关,所以你也需要知道一些关于Service的知识。日后得闲我也会继续写一些关于Service的贴。
本文将以一个例子来和你分享使用AIDL的基础技能,这个例子里有:
1、一个类mAIDLActivity,继承Activity。里面有三个按钮,text分别为StartService,StopService,CallbackTest。
2、一个类mAIDLService,继承Service。为了充分展示ADIL的功能,它做以下工作:当用户点击CallbackTest按钮时,从mAIDLActivity调用mAIDLService中的Stub对象的一个方法invokCallBack(),而这个方法又会调用mAIDLActivity中Stub 对象的一个方法performAction(),这个方法在屏幕上显示一个toast。没什么意义,只是展示一下AIDL如何使用。
3、两个AIDL文件:forService.aidl和forActivity.aidl。对应名字,在Service和Activity中分别有对象需要用到它们定义的接口。
4、相关XML文件,略过。关于manifest中Service的语法,见docs/guide/topics/manifest/service-element.html。你也可以简单地在<application></application>中加入
<service android:name=”.mAIDLService” android:process=”:remote”> </service>
开发环境为Eclipse。
拣重要的先说,来看看aidl文件的内容:
文件:forActivity.aidl
view plaincopy to clipboardprint?
1. package com.styleflying.AIDL;
2. interface ITaskCallback {
3. void performAction();
文件:forService.aidl
view plaincopy to clipboardprint?
1. package com.styleflying.AIDL;
2. import com.styleflying.AIDL.forActivity;
3. interface ITaskBinder {
4. void registerTestCall(ITaskCallback tc);
5. void invokCallBack();
6. }
这两个文件和Java文件放置的地方一样,看包名。
在Eclipse中它们将被自动编译为forActivity.java和forService.java,它们存放在gen目录下。为了方便手头无法演练的读者,代码贴上,不用细看。
文件forActivity.java:
view plaincopy to clipboardprint?
1. /*
2. * This file is auto-generated.  DO NOT MODIFY.
3. * Original file: D:\\workspace\\AIDLTest\\src\\com\\styleflying\\AIDL\\forActivity.aidl
4. */
5. package com.styleflying.AIDL;
6. import java.lang.String;
7. import android.os.RemoteException;
8. import android.os.IBinder;
9. import android.os.IInterface;
10. import android.os.Binder;
11. import android.os.Parcel;
12. public interface forActivity extends android.os.IInterface
13. {
14. /** Local-side IPC implementation stub class. */
15. public static abstract class Stub extends android.os.Binder implements com.styleflying.AIDL.forActivity
16. {
17. private static final java.lang.String DESCRIPTOR = ”com.styleflying.AIDL.forActivity”;
18. /** Construct the stub at attach it to the interface. */
19. public Stub()
20. {
21. this.attachInterface(this, DESCRIPTOR);
22. }
23. /**
24. * Cast an IBinder object into an forActivity interface,
25. * generating a proxy if needed.
26. */
27. public static com.styleflying.AIDL.forActivity asInterface(android.os.IBinder obj)
28. {
29. if ((obj==null)) {
30. return null;
31. }
32. android.os.IInterface iin = (android.os.IInterface)obj.queryLocalInterface(DESCRIPTOR);
33. if (((iin!=null)&&(iin instanceof com.styleflying.AIDL.forActivity))) {
34. return ((com.styleflying.AIDL.forActivity)iin);
35. }
36. return new com.styleflying.AIDL.forActivity.Stub.Proxy(obj);
37. }
38. public android.os.IBinder asBinder()
39. {
40. return this;
41. }
42. @Override public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException
43. {
44. switch (code)
45. {
46. case INTERFACE_TRANSACTION:
47. {
48. reply.writeString(DESCRIPTOR);
49. return true;
50. }
51. case TRANSACTION_performAction:
52. {
53. data.enforceInterface(DESCRIPTOR);
54. this.performAction();
55. reply.writeNoException();
56. return true;
57. }
58. }
59. return super.onTransact(code, data, reply, flags);
60. }
61. private static class Proxy implements com.styleflying.AIDL.forActivity
62. {
63. private android.os.IBinder mRemote;
64. Proxy(android.os.IBinder remote)
65. {
66. mRemote = remote;
67. }
68. public android.os.IBinder asBinder()
69. {
70. return mRemote;
71. }
72. public java.lang.String getInterfaceDescriptor()
73. {
74. return DESCRIPTOR;
75. }
76. public void performAction() throws android.os.RemoteException
77. {
78. android.os.Parcel _data = android.os.Parcel.obtain();
79. android.os.Parcel _reply = android.os.Parcel.obtain();
80. try {
81. _data.writeInterfaceToken(DESCRIPTOR);
82. mRemote.transact(Stub.TRANSACTION_performAction, _data, _reply, 0);
83. _reply.readException();
84. }
85. finally {
86. _reply.recycle();
87. _data.recycle();
88. }
89. }
90. }
91. static final int TRANSACTION_performAction = (IBinder.FIRST_CALL_TRANSACTION + 0);
92. }
93. public void performAction() throws android.os.RemoteException;
94. }
文件forService.java:
+ expand sourceview plaincopy to clipboardprint?
•••••••••10••••••••20••••••••30••••••••40••••••••50••••••••60••••••••70••••••••80••••••••90••••••••100•••••••110•••••••120•••••••130•••••••140•••••••150
两段代码差不多,前面基本一样,从后面看,最后跟着我们在AIDL中自定义的方法,没有实现。两个文件各定义一个了接口,这两个接口分别会在Activity和Service中使用,在那里我们将实现自定义的方法。两个接口中都定义了一个抽象类Stub,实现所在的接口。Stub中又有一个类Proxy。Stub中有一个static的asInterface()方法,里面有很多return语句,在mAIDLActivity中调用它时,它返回一个新创建的内部类Proxy对象。
这个Stub对我们来说很有用,它继承了Binder。Binder有什么用呢?一个类,继承了Binder,那么它的对象就可以被远程的进程使用了(前提是远程进程获取了这个类的对象【对象的引用】,至于如如何获得看下文),在本例中就是说,如果一个Service中有一个继承了Stub的类的对象,那么这个对象中的方法就可以在Activity中使用,对Activity也是这样。至于Binder的细节,网上有很多贴介绍,看不明白也不影响我们完成这个例子。
再看mAIDLActivity.java:
view plaincopy to clipboardprint?
1. package com.styleflying.AIDL;
2. import android.app.Activity;
3. import android.content.ComponentName;
4. import android.content.Context;
5. import android.content.Intent;
6. import android.content.ServiceConnection;
7. import android.os.Bundle;
8. import android.os.IBinder;
9. import android.os.RemoteException;
10. import android.util.Log;
11. import android.view.View;
12. import android.view.View.OnClickListener;
13. import android.widget.Button;
14. import android.widget.Toast;
15. public class mAIDLActivity extends Activity {
16. private static final String TAG = ”AIDLActivity”;
17. private Button btnOk;
18. private Button btnCancel;
19. private Button btnCallBack;
20. private void Log(String str) {
21. Log.d(TAG, ”—— ” + str + ”——”);
22. }
23. private forActivity mCallback = new forActivity.Stub() {
24. public void performAction() throws RemoteException
25. {
26. Toast.makeText(mAIDLActivity.this, ”this toast is called from service”, 1).show();
27. }
28. };
29. forService mService;
30. private ServiceConnection mConnection = new ServiceConnection() {
31. public void onServiceConnected(ComponentName className,
32. IBinder service) {
33. mService = forService.Stub.asInterface(service);
34. try {
35. mService.registerTestCall(mCallback);}
36. catch (RemoteException e) {
37. }
38. }
39. public void onServiceDisconnected(ComponentName className) {
40. Log(“disconnect service”);
41. mService = null;
42. }
43. };
44. @Override
45. public void onCreate(Bundle icicle) {
46. super.onCreate(icicle);
47. setContentView(R.layout.main);
48. btnOk = (Button)findViewById(R.id.btn_ok);
49. btnCancel = (Button)findViewById(R.id.btn_cancel);
50. btnCallBack = (Button)findViewById(R.id.btn_callback);
51. btnOk.setOnClickListener(new OnClickListener() {
52. public void onClick(View v) {
53. Bundle args = new Bundle();
54. Intent intent = new Intent(mAIDLActivity.this, mAIDLService.class);
55. intent.putExtras(args);
56. bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
57. startService(intent);
58. }
59. });
60. btnCancel.setOnClickListener(new OnClickListener() {
61. public void onClick(View v) {
62. unbindService(mConnection);
63. //stopService(intent);
64. }
65. });
66. btnCallBack.setOnClickListener(new OnClickListener() {
67. @Override
68. public void onClick(View v)
69. {
70. try
71. {
72. mService.invokCallBack();
73. } catch (RemoteException e)
74. {
75. // TODO Auto-generated catch block
76. e.printStackTrace();
77. }
78. }
79. });
80. }
81. }
很短,相信大家很容易看明白。注意mConnection,它的onServiceConnected()中有一句mService = forService.Stub.asInterface(service);给mService赋值了,这个mService是一个forService,而service是onServiceConnected()传进来的参数,onServiceConnected()会在连接Service的时候被系统调用,这个service参数的值来自哪里呢?看mAIDLService.java:
view plaincopy to clipboardprint?
1. package com.styleflying.AIDL;
2. import android.app.Service;
3. import android.content.Intent;
4. import android.os.IBinder;
5. import android.os.RemoteCallbackList;
6. import android.os.RemoteException;
7. import android.util.Log;
8. public class mAIDLService extends Service {
9. private static final String TAG = ”AIDLService”;
10. private forActivity callback;
11. private void Log(String str) {
12. Log.d(TAG, ”—— ” + str + ”——”);
13. }
14. @Override
15. public void onCreate() {
16. Log(“service create”);
17. }
18. @Override
19. public void onStart(Intent intent, int startId) {
20. Log(“service start id=” + startId);
21. }
22. @Override
23. public IBinder onBind(Intent t) {
24. Log(“service on bind”);
25. return mBinder;
26. }
27. @Override
28. public void onDestroy() {
29. Log(“service on destroy”);
30. super.onDestroy();
31. }
32. @Override
33. public boolean onUnbind(Intent intent) {
34. Log(“service on unbind”);
35. return super.onUnbind(intent);
36. }
37. public void onRebind(Intent intent) {
38. Log(“service on rebind”);
39. super.onRebind(intent);
40. }
41. private final forService.Stub mBinder = new forService.Stub() {
42. @Override
43. public void invokCallBack() throws RemoteException
44. {
45. callback.performAction();
46. }
47. @Override
48. public void registerTestCall(forActivity cb) throws RemoteException
49. {
50. callback = cb;
51. }
52. };
53. }
注意onBind(),它的返回类型为IBinder,返回了一个mBinder,看看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;
}
};
它是实现了我们在AIDL中定义的方法,这个mBinder最终返回给了mAIDLActivity中的mService,于是在mAIDLActivity中可以使用mBinder中的方法了。在mAIDLActivity中也有一个类似mBinder的对象,看看定义:
private forActivity mCallback = new forActivity.Stub()
{
public void performAction() throws RemoteException
{
Toast.makeText(mAIDLActivity.this, “this toast is called from service”, 1).show();
}
};
我们要在界面上显示一个toast,就是在这里实现的。这个对象,在mConnection的onServiceConnected()被调用时,通过调用mService(也就是远程的mAIDLService中的mBinder)的registerTestCall(),传递给了mAIDLService,于是在mAIDLService中可以调用performAction()了。
很啰嗦,只为了能把这个细节说清楚。请大家认真看,我尽量避免错别字、混乱的大小写和逻辑不清的语法,相信你会看明白。是不是很简单?再啰嗦一下,做一个大致总结,我们使用AIDL是要做什么呢:
让Acticity(或者说一个进程/一个类?)和Service(或者说远端进程/远端类/对象?)获取对方的一个Stub对象,这个对象在定义时实现了我们在AIDL中定义的方法,于是这些远程对象中的方法可以在本地使用了。如果这种使用(通信)是单向的,比如只是Activity需要通知Service做什么,那么只要Service中有一个Stub对象,并且传给Acticity就够了。
至于如何获得远程的Stub,参看上面的代码,看mConnection、registerTestCall、onRebind,它们展示了一种方法。
另外,有时候我们可能在一个类中有多个Stub对象,它们都要给远程交互的类的实例,这个时候可以考虑使用RemoteCallbackList<>(docs/reference/android/os/RemoteCallbackList.html)。

分享到:
评论

相关推荐

    AidlDemo(简单aidl的例子).zip

    1. **AIDL介绍**:AIDL是Android中处理进程间通信的一种方式,它允许服务(Service)在不同的进程中暴露接口给其他组件调用,即使这些组件在不同的应用程序中。AIDL文件定义了服务端提供的接口和方法,客户端通过...

    Android的IPC与AIDL

    AIDL介绍:** AIDL是一种用于定义进程间通信接口的语言。使用AIDL可以定义一个接口文件(通常以.aidl为后缀),这个文件描述了远程接口的行为,包括参数类型和返回值类型。AIDL编译器会根据该文件生成相应的Java...

    安卓Service和AIDL使用示例代码

    4. **AIDL介绍** - AIDL允许定义接口,使得不同进程间可以通过Binder机制通信。它生成Java代码,这些代码处理跨进程的数据转换和回调。 5. **创建AIDL接口** - 创建一个.aidl文件,定义接口和方法,比如: ```...

    android 基于aidl实现的守护进程

    **一、AIDL介绍** AIDL是Android提供的一种工具,它允许开发者在不同的进程中定义和实现接口,使得服务可以被其他应用调用,即使这些应用运行在不同的进程中。通过AIDL,我们可以定义方法签名、数据类型和参数,使得...

    android笔记--Service与AIDL

    AIDL介绍: 1. AIDL是Android中用于跨进程通信的关键技术,它允许不同进程间的组件互相调用方法,就像是在同一个进程中一样。 2. AIDL文件定义了一个接口,包含了一系列方法和参数类型。Android编译器会根据AIDL生成...

    AndroidAIDL

    本文将详细介绍AIDL的工作原理、使用步骤以及相关知识点。 **1. AIDL基础概念** AIDL是一种接口定义语言,类似于Java中的接口,但它专门用于定义跨进程通信的接口。通过AIDL,开发者可以创建一个接口,该接口在...

    利用AIDL进程间传输图片例子

    本示例“利用AIDL进程间传输图片”将详细介绍如何在Android Studio 1.5环境下,通过AIDL实现两个进程间传输图片。 首先,我们需要理解AIDL的基本概念。AIDL是一种简单的接口定义语言,它可以让我们定义一个接口,该...

    android aidl 不同进程间通信

    下面将详细介绍Aidl在不同进程间通信中的应用及其工作原理。 **1. Android进程通信的重要性** Android系统设计时,每个应用运行在自己的进程中,为了保护应用间的隔离性和安全性。但有时我们需要让一个应用调用另一...

    Aidl服务详细介绍,包括使用方法和分析。

    AIDL(Android Interface Definition Language)是Android系统提供的一种机制,用于处理进程间的通信(IPC,Inter-Process Communication)。当一个应用程序需要与另一个运行在不同进程的应用进行数据交换时,AIDL就...

    Android AIDL用法介绍

    Android AIDL用法介绍, 可以简单了解AIDL的实现机制,应用到实际项目中。

    Android AIDL使用介绍(2)自定义数据类型的传递

    默认情况下,AIDL只支持下列数据类型: Java八种基础数据类型(如 int、long、char、boolean 等); String字符串; CharSequence字符序列; List列表,List中的所有元素须是前面提到的数据类型,或者是Parcelable...

    wps for android AIDL调用

    本文将详细介绍如何使用AIDL调用WPS for Android,并涉及相关的jar文件。 首先,`moffice-aidl.jar`和`moffice-event-interface.jar`是WPS Office为开发者提供的API库,它们包含了与WPS进行通信所需的方法和事件...

    AIDL简单使用Demo

    本Demo将深入浅出地介绍AIDL的基本使用步骤。 1. **创建AIDL文件** 在项目中新建一个AIDL文件,例如`IAIDLService.aidl`。在该文件中定义服务提供的接口,如: ```aidl package com.example.aidldemo; ...

    Android AIDL使用详解

    在上述博客链接中,作者详细介绍了AIDL的使用过程,包括创建、实现AIDL接口,以及客户端和服务端的交互。同时,可能还会涉及如何调试和优化AIDL相关的代码,以及与其他工具(如源码分析工具)的结合使用。 总之,...

    AIDL代码实例

    **Android Interface Definition Language (AIDL) 介绍** AIDL(Android Interface Definition Language)是Android系统提供的一种接口定义语言,用于处理进程间通信(IPC, Inter-Process Communication)。它允许...

    Android AIDL 服务端与客户端实现Demo

    本Demo将详细介绍如何通过AIDL在服务端和客户端之间实现通信。 首先,我们需要理解AIDL的基本概念。AIDL本质上是Android系统提供的一种接口定义语言,它允许开发者定义接口,这些接口可以在不同的Android进程间调用...

    清理缓存所需的aidl文件

    下面将详细介绍这三个关键的AIDL文件:IPackageDataObserver.aidl、IPackageStatsObserver.aidl和PackageStats.aidl。 1. IPackageDataObserver.aidl: 这个文件定义了一个接口,允许系统服务与应用之间的通信,...

    Aidl实现类似广播的功能

    本教程将详细介绍如何利用AIDL来实现类似广播的功能。 首先,我们要理解AIDL的基本概念。AIDL是一种接口定义语言,它允许开发者定义接口,这些接口可以在不同的Android进程中被调用。通过AIDL,我们可以创建一个...

    aidl简单示例

    本示例将通过"aidlclientdemo"和"aidlserverdemo"两个项目,详细介绍如何使用AIDL进行简单的IPC操作。 首先,我们来理解AIDL的基本概念。在AIDL文件中,我们可以定义服务端提供的接口以及接口中的方法,这些方法会...

    Android中aidl开发简单示例

    在`说明链接.txt`文件中,可能详细介绍了如何执行这些步骤,包括编写和配置AndroidManifest.xml文件,以及如何启动和连接服务等。 总的来说,这个示例旨在帮助开发者理解AIDL如何在Android应用中实现进程间通信,...

Global site tag (gtag.js) - Google Analytics