`
liujianguangaaa
  • 浏览: 235171 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
社区版块
存档分类
最新评论

从 Remote Service Binding 学习 AIDL 与 IPC

阅读更多

默认情况下,一个应用不管有多少个 Activity、Service 或其他组件,它们都是运行在一个进程上,但是我们可以安排 Service 运行一个新的进程上,但是不同进程之间应该如何通信呢?当需要在不同的进程之间传递对象时,应该怎么做呢?AIDL(Android Interface Definition Language) 便是解决这一问题的钥匙。

使用 AIDL 并不是难事,但是比较繁琐,并且一不小心容易出错。好在 Android Dev Guide 的 Designing a Remote Interface Using AIDL 对这个问题讲解非常详细,再结合 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 来展示其中的关系。

Remote Service Binding

Remote Service Binding

1、创建.aidl 文件

AIDL 语法简单,用来声明接口,其中的方法接收参数和返回值,但是参数和返回值的类型是有约束的,且有些类型是需要 import,另外一些则无需这样做。

AIDL 支持的数据类型划分为四类,第一类是 Java 编程语言中的基本类型,第二类包括 String、List、Map 和 CharSequence,第三类是其他 AIDL 生成的 interface,第四类是实现了 Parcelable protocol 的自定义类。
其中,除了第一类外,其他三类在使用时均需要特别小心。

使用第二类时,首先需要明白这些类不需要 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 文件里的所有方法。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 没有使用第四类数据类型作为参数,这是示例的不足,要想让一个类变成第四类,需要遵照以下步骤:

  1. 引入 Parcelable 接口
  2. 实现 writeToParcel(Parcel out)
  3. 增加一个静态的field,其实现 Parcelable.Creator 接口
  4. 创建一个 .aidl 文件,用以声明你的 parcelables 类

在 Designing a Remote Interface Using 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 能抛出的唯一异常。

分享到:
评论

相关推荐

    AIDLDemo.rar

    在Android系统中,进程间通信(IPC,Inter-Process Communication)是实现不同应用程序之间数据交换的关键技术。AIDL(Android Interface Definition Language)是Android提供的一种强大的工具,它使得跨进程调用...

    Android AIDL demo (Android Studio)

    在Android开发中,AIDL(Android Interface Definition Language)是一种用于实现进程间通信(IPC, Inter-Process Communication)的工具。本教程将详细讲解如何在Android Studio中创建并使用AIDL,以便不同进程间的...

    AidlDemo.zip

    4. **绑定服务(Binding Service)**:客户端通过`bindService()`方法与服务建立连接。一旦连接成功,客户端可以通过返回的IBinder对象(在本例中是IAidlService的实例)来调用服务的方法。 5. **进程间通信(IPC)...

    Android AIDL Demo

    在Android开发中,AIDL(Android Interface Definition Language)是一种用于跨进程通信(IPC,Inter-Process Communication)的技术,使得一个应用程序能够与另一个应用程序进行数据交换。`Android AIDL Demo`是一...

    WPF Binding 学习笔记

    【WPF Binding 学习笔记】 WPF (Windows Presentation Foundation) 的数据绑定是其核心特性之一,它使得UI层和业务逻辑层之间的数据交互变得简单而直观。在WPF中,数据绑定允许UI控件(目标)动态地显示或响应数据...

    WPF Binding绑定 Command命令基础学习源码

    在WPF(Windows Presentation Foundation)开发中,数据绑定和命令是两个非常重要的概念,它们能够实现界面(View)与业务逻辑(ViewModel)之间的松耦合。让我们深入探讨这两个主题。 **WPF数据绑定(Binding)** ...

    C#应用BindingSource实现数据同步的方法

    这样,`BindingSource`就与数据源建立了连接,可以开始处理数据的绑定和同步。 为了实现数据同步,我们通常会将控件的`DataSource`属性设置为`BindingSource`实例。在示例中,`dataGridView1`、`textBox1`和`...

    WPF Binding转换与校验

    ### WPF Binding转换与校验 #### 一、概述 WPF(Windows Presentation Foundation)作为Microsoft推出的用于构建桌面应用程序的框架之一,提供了丰富的特性和工具来帮助开发者构建高性能且美观的应用程序。其中,...

    web service入门学习笔记

    Web Service入门学习笔记 Web Service是一种基于互联网的、平台无关的通信协议,它允许不同系统间的应用程序通过网络互相调用,实现数据交换和服务共享。在本文中,我们将深入探讨Web Service的基本概念,以及如何...

    3GPP标准协议中英文对照版-BSF服务-29521-g10(Binding Support Management Service).docx

    3GPP 标准协议中英文对照版 - BSF 服务 - 29521-g10(Binding Support Management Service) Binding Support Management Service 是 3GPP 标准协议中的一部分,它属于 5G 系统中的 BSF(Binding Support Function...

    基于BindingSource的WinForm开发

    在Windows Forms应用开发中,`BindingSource`组件扮演着至关重要的角色,它是连接数据源与UI控件的关键组件。本文将深入探讨`BindingSource`在WinForm开发中的使用,包括其基本概念、功能、以及如何实现主细表绑定、...

    WPF的binding代码实例

    在Windows Presentation Foundation (WPF) 中,数据绑定是一种强大的机制,它允许UI元素与应用程序的数据模型进行联动。在这个“WPF的binding代码实例”中,我们将深入探讨几个基础的绑定用法,帮助开发者更好地理解...

    win32-ia-32-48_binding.node插件去掉node不报错

    win32-ia-32-48_binding.node插件去掉node不报错win32-ia-32-48_binding.node插件去掉node不报错win32-ia-32-48_binding.node插件去掉node不报错win32-ia-32-48_binding.node插件去掉node不报错win32-ia-32-48_...

    MVVM+ViewBinding+Kotlin入门

    在实际项目中,MVVM与ViewBinding结合使用,可以构建出高效、可测试的Android应用。首先,你需要在项目中引入必要的依赖,如MVVM框架(如Jetpack的LiveData和Room)和ViewBinding库。然后,创建ViewModel类,用于...

    wpf binding 的两种方法

    在Windows Presentation Foundation (WPF) 中,数据绑定是将用户界面元素与数据源连接的关键机制,使得UI元素的属性能够动态地反映数据源的变化。标题和描述提到了两种WPF数据绑定的方法,这里我们将深入探讨这两种...

    自定义android开发MVP+ViewBinding架构Demo

    在Android应用开发中,MVP(Model-View-Presenter)架构模式是一种常用的设计模式,它有助于保持代码的...通过学习这个Demo,开发者可以更好地理解和实践MVP+ViewBinding在实际项目中的应用,提升开发效率和代码质量。

    win32-x64-51-57-59-64-67-72-79-83-binding.node多版本.zip

    `binding.node`在IT行业中,特别是Node.js的上下文中,是一个关键的概念,它是Node.js原生模块(C++扩展)与JavaScript交互的桥梁。这些版本号(如51、57、59等)分别对应于不同的Node.js版本,表明这个压缩包提供了...

    EFI Howto:Driver binding的实质

    EFI驱动模型与Windows驱动模型的比较和Driver Binding的实现 本文主要介绍了EFI驱动模型的概念,特别是Driver Binding的实现过程,同时借鉴了Windows驱动模型的一些概念,以便更好地理解EFI驱动模型。 首先,我们...

    win32-x64-64_binding.node下载

    标题中的“win32-x64-64_binding.node”是Node.js的二进制扩展模块,它通常与Node.js的C++绑定有关。这里的“win32”代表操作系统是Windows,“x64”表示64位架构,而“binding”则意味着这是一个用于JavaScript和...

Global site tag (gtag.js) - Google Analytics