`
Rainbow702
  • 浏览: 1077950 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类

Android Service 之三(Bind Service,使用 AIDL)

阅读更多

前面写了 Bind Service 的两种实现方式,接下来转一篇贴子来简述一下最后一种实现方式
第三种:使用 AIDL

前面讲的使用 Messenger 技术,其实是基于 AIDL架构的,但是 Messenger 使用一个队列来处理所有的请求,这样一来,就无法进行多线程的并发了。所以,如果你想同时接受并处理多个 client 的请求,那么请使用 AIDL 来实现,但这样的话,你需要小心地进行同步处理了哦~
默认情况下,一个应用不管有多少个 Activity、Service 或其他组件,它们都是运行在一个进程上,但是我们可以安排 Service 运行一个新的进程上,但是不同进程之间应该如何通信呢?当需要在不同的进程之间传递对象时,应该怎么做呢?AIDL(Android Interface Definition Language) 便是解决这一问题的钥匙。
使用 AIDL 并不是难事,但是比较繁琐,并且一不小心容易出错。好在 Android Dev Guide 的 "AIDL" 章节(在 "Dev Guide " 左侧列表的最下面)对这个问题讲解非常详细,再结合 Android APIDemo 中的 Remote Service Binding 给出了的示例,这都给了开发者提供了非常到位的帮助。以下内容就是我结合二者,整理出来的笔记,力求真理,但能力有限,差错难免,请读者坚持自己的判断力,本文只供参考,且不可尽信。

一、使用 AIDL 实现 IPC
面对问题,应统揽全局,归纳阶段,划定步骤,共得出四大步,分列如下:
① 创建.aidl 文件
    在这个文件里定义 method 和 field
② 把 .aidl 文件加入到 makefile 中去
    如果使用 Eclipse 则 ADT 会帮你管理
③ 实现接口方法
    AIDL 编译器会根据接口生成一个用 Java 语言编写的interface,这个 interface 有一个抽象的内部类,名字为 Stub,你必须创建一个类,继承于它,并且实现 .adil 文件中所声明的方法
④ 公开接口给客户端
    如果创建的是 service,则应该继承自 Service,并且重载 Service.onBind() 返回实现接口的类的实例

这四个步骤在 Remote Service Binding 中均有所呈现,以下分开阐述。Remote Service Binding 共包含有两个 .java 文件,三个 .aidl 文件,物理结构比较简单,但是逻辑结构就不那么简单,以下用 Class Diagram 来展示其中的关系。



 

1、创建.aidl 文件
AIDL 语法简单,用来声明接口,其中的方法接收参数和返回值,但是参数和返回值的类型是有约束的,且有些类型是需要 import,另外一些则无需这样做。
AIDL 支持的数据类型划分为四类,第一类是 Java 编程语言中的基本类型,第二类包括 String、List、Map 和 CharSequence,第三类是其他 AIDL 生成的 interface,第四类是实现了 Parcelable 接口的自定义类。
其中,除了第一类外,其他三类在使用时均需要特别小心。
使用第二类时,首先需要明白这些类不需要 import,是内嵌的。其次注意在使用 List 和 Map 此二者容器类时,需注意其元素必须得是 AIDL 支持的数据类型,List 可支持泛型,但是 Map 不支持,同时另外一端负责接收的具体的类里则必须是 ArrayList 和 HashMap。
使用第三、四类时,需要留意它们都是需要 import 的,但是前者传递时,传递的是 reference,而后者则是 value。

在创建 .aidl 文件的过程中,应该注意一旦 method 有参数,则需注意在前面加上 in, out 或 inout,它们被称为 directional tag,但是对于基本类型的参数,默认就是 in,并且不能为其他值。

Remote Service Binding 共包括了三个 .aidl 文件,分别是IRemoteService.aidl、IRemoteServiceCallback.aidl、ISecondary.aidl,通过它们可以看到如何使用第一类和第三类的数据类型,稀罕的是,看不到第二类、第四类数据类型的使用,也没有看到 directional tag。

 

2、实现 Interface
AIDL 为你生成一个 interface 文件,文件名称和 .aidl 文件相同。如果使用 Eclipse 插件,则 AIDL 会在构建过程中自动运行,如果不使用插件,则需要先使用 AIDL。
生成的 interface 会包含一个抽象内部类 Stub,它声明了在 .aidl 文件里的所有方法。要想实现你在 .aidl 文件里定义的接口,就必须实现这个Stub类,如下:

/**
 * This implementation is used to receive callbacks from the remote
 * service.
 */
private IRemoteServiceCallback mCallback = new IRemoteServiceCallback.Stub() {
	/**
	 * This is called by the remote service regularly to tell us about
	 * new values.  Note that IPC calls are dispatched through a thread
	 * pool running in each process, so the code executing here will
	 * NOT be running in our main thread like most other things -- so,
	 * to update the UI, we need to use a Handler to hop over there.
	 */
	public void valueChanged(int value) {
		mHandler.sendMessage(mHandler.obtainMessage(BUMP_MSG, value, 0));
	}
};

 

Stub 也定义了一些帮助方法,比较常用的有 asInterface(),其接收一个 IBinder 作为参数,并且返回一个 interface 的实例用来调用IPC方法。

private static INotificationManager sService;
 
static private INotificationManager getService()
{
	if (sService != null) {
		return sService;
	}
	sService = INotificationManager.Stub.asInterface(ServiceManager.getService("notification"));
	return sService;
}

 

 要实现 interface,需要继承 Stub,实现其方法,这在 RemoteService 和 RemoteServiceBinding 都可以找到相关代码。

这个环节是重中之重,需要特别小心的有两点,其一是抛出的所有异常均不会发给调用者;其二是IPC调用是同步的,这意味IPC服务一旦花费较长时间完成的话,就会引起ANR,应该将这样的操作放在单独的线程里。

 

3、向客户端公开 Interface
独乐乐不如众乐乐,需要将服务公开出去,要达成这个目的,须得创建一个 Service 的子类,并且实现 Service.onBind(Intent),通过这个方法将实现了接口的类的实例返回回来。通过查看 RemoteService 一目了然。

 

@Override
public IBinder onBind(Intent intent) {
	// Select the interface to return.  If your service only implements
	// a single interface, you can just return it here without checking
	// the Intent.
	if (IRemoteService.class.getName().equals(intent.getAction())) {
		return mBinder;
	}
	if (ISecondary.class.getName().equals(intent.getAction())) {
		return mSecondaryBinder;
	}
	return null;
}

 

其中的 mBinder 和 mSecondaryBinder 分别是实现了 IRemoteService 和 ISecondary 接口的类的实例。

4、使用Parcelables传值
前文中提到 Remote Servcie Binding 没有使用第四类数据类型作为参数,这是示例的不足,要想让一个类变成第四类,需要遵照以下步骤:

① 引入 Parcelable 接口
② 实现 writeToParcel(Parcel out)
③ 增加一个静态的field,其实现 Parcelable.Creator 接口
④ 创建一个 .aidl 文件,用以声明你的 parcelables 类
在 "AIDL" 中,类 Rect 是一个不错的示例,弥补了 Remote Service Binding 的不足。

 

二、调用 IPC 方法
万事俱备,只欠东风,IPC 备妥,只待调用。在 Remote Service Binding 中,RemoteServiceBinding 正是 IPC 的调用者,既然要使用接口,那就先声明 interface 类型的变量

// The primary interface we will be calling on the service. 
IRemoteService mService = null; 
// Another interface we use on the service. 
ISecondary mSecondaryService = null; 

 

实现 ServiceConnection,在 onServiceConnected(ComponentName className, IBinder service) 中完成对 mService 和 mSecondaryService 的赋值。

 

private ServiceConnection mConnection = new ServiceConnection() {
	public void onServiceConnected(ComponentName className,
			IBinder service) {
		mService = IRemoteService.Stub.asInterface(service);
		// ... 以下省略
	}
}

 

接着别忘了调用 Context.bindService(),完成任务以后,调用 Context.unbindService()。如果在 connection 中断的情况下,调用 IPC 方法,你会遇到 DeadObjectException,这是 remote method 能抛出的唯一异常。

 

原文地址: http://www.poemcode.net/2010/05/aidl-ipc/

  • 大小: 79.3 KB
分享到:
评论

相关推荐

    aidl.rar_AIDL_AIDL.rar_android AIDL service_android service_andr

    AIDL(Android Interface Definition Language)是Android系统提供的一种接口定义语言,用于在不同进程间进行通信,特别是当服务(Service)需要与客户端(如Activity)跨进程交互时。AIDL帮助开发者定义接口,使得...

    Android Service讲解 和 aidl 实现

    在Android应用开发中,`Service`和`AIDL(Android Interface Definition Language)`是两个非常重要的组件,它们分别用于后台长时间运行的任务和服务间通信。本文将深入探讨这两个概念以及如何通过`AIDL`来实现服务...

    使用AIDL实现Service与Client绑定后的双向调用

    有时,我们可能需要在Service和另一个应用组件之间进行更复杂的通信,例如双向交互,这时可以利用Android Interface Definition Language(AIDL)来实现。本文将深入探讨如何使用AIDL在Service与Client之间实现绑定...

    AndroidAIDL

    **Android AIDL(Android Interface Definition Language)详解** 在Android系统中,进程间的通信(IPC, Inter-Process Communication)是...掌握AIDL的使用,对于开发大型的、需要多进程协作的Android应用至关重要。

    wps for android AIDL调用

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

    AIDL_AidlService_android_

    总的来说,AIDL是Android平台中进行进程间通信的关键技术,理解并熟练使用AIDL,能够帮助开发者构建更加健壮和高效的Android应用。通过不断的实践和学习,开发者可以更好地掌握AIDL的精髓,提高应用的可扩展性和复用...

    Android service aidl编写示例(Android Studio/eclipse)

    在Android应用开发中,Service和AIDL(Android Interface Definition Language)是两个重要的组件。Service用于在后台执行长时间运行的任务,而AIDL则用于进程间通信(IPC, Inter-Process Communication)。下面将...

    Android AIDL使用例子

    在这个"Android AIDL使用例子"中,`MyBinderService`很可能包含了上述所有步骤的实现,展示了如何创建、实现AIDL接口以及在客户端和服务端之间进行通信。通过这个例子,开发者可以更深入地理解Android进程间通信的...

    Android RemoteService AIDL 方式实现

    现在,我们来详细探讨如何通过AIDL在Android中实现RemoteService。 首先,让我们理解AIDL的基本概念。AIDL本质上是一个接口定义语言,它允许你在Android应用中定义一套接口,这些接口可以被其他应用所调用。当你...

    Android使用AIDL实现进程间通信

    本篇文章将深入探讨如何在Android中使用AIDL来实现进程间通信。 首先,理解AIDL的基本概念。AIDL是一种接口定义语言,类似于Java中的接口,但它的目的是跨越进程边界。通过AIDL,我们可以定义一个接口,该接口会被...

    android aidl service

    本示例“android aidl service”是一个演示如何使用AIDL进行数据交换的实践项目,它包括两个部分:AIDLServer(服务端)和AIDLClient(客户端)。通过这两个组件,我们可以深入理解AIDL的工作原理及其在实际应用中的...

    Activity和Service生命周期及使用AIDL通信实例备份

    本篇将深入探讨Activity和Service的生命周期以及如何利用Android Interface Definition Language (AIDL)进行进程间通信。 Activity是Android应用程序的用户界面,它负责与用户交互。Activity的生命周期分为几个关键...

    Android Service学习之AIDL, Parcelable和远程服务

    本篇文章将深入探讨如何使用AIDL(Android Interface Definition Language)、Parcelable接口以及如何实现远程服务,这些都是Android Service开发中的关键知识点。 首先,我们来谈谈AIDL。AIDL是Android系统提供的...

    android aidl 复杂数据类型 传图片service

    总结起来,使用AIDL在Service中传递复杂类型如图片,需要对Android IPC机制有深入理解,包括AIDL接口定义、数据类型转换以及Service的生命周期管理。这是一个涉及到多方面技术的综合问题,需要开发者具备扎实的...

    Android AIDL使用详解

    2. 在服务(Service)的onBind方法中返回IMyService的Binder实例。 客户端使用: 1. 客户端通过bindService方法连接到服务,获取到IBinder对象。 2. 将IBinder转换为IMyService的接口实例,然后就可以调用远程服务...

    Service AIDL实例

    - 压缩包中的`ServiceAIDL`可能包含了一个完整的示例项目,包括服务端的`IService.aidl`、`MyService.java`,以及客户端的连接和调用代码。通过分析和运行这个项目,你可以更深入地理解AIDL的工作原理和应用场景。 ...

    Android startService bindService Aidl service基础全

    在Android开发中,服务(Service)是四大组件之一,它在后台执行长时间运行的操作而不会与用户界面交互。本文将深入探讨"Android startService, bindService, Aidl service基础全"这一主题,按照学习顺序依次讲解`...

    android开发使用aidl进行跨进程通信demo

    本教程将深入讲解如何使用AIDL在Android开发中构建一个简单的跨进程通信DEMO。 首先,我们需要理解AIDL的基本概念。AIDL是一种基于文本的接口定义语言,类似于Java或C++的接口定义。通过AIDL,我们可以定义服务端...

    android service、aidl教学

    本教程将详细讲解如何实现Android Service以及使用AIDL来创建远程服务。 首先,让我们深入了解Android的Service。Service是一种在后台运行的组件,即使用户没有直接与应用交互,它也能执行任务。Service可以用于...

    Android Aidl

    在Android系统中,AIDL(Android Interface Definition Language)是一种接口定义语言,用于实现不同进程间的通信,即远程进程通讯。AIDL使得服务(Service)和活动(Activity)这两个独立的APK之间能够相互通信,...

Global site tag (gtag.js) - Google Analytics