boundService-AIDL

前面已经写了两篇文章介绍了bound service 的两种方式,现在再来说说第三种方式-aidl。

AIDL



Android 远程接口调用语言和其他远程接口调用语言类似。允许你定义 client-servver 的语言接口来满足两者之间的进程通信(IPC)。在 Android 世界里一个进程通常情况下不能正常的访问另一个进程的内存。如果要访问,你需要将对象分解成最原始的数据以便系统能理解并传递对象穿越进程边界。其中实现的代码是复杂的,所以 Android 使用 AIDL 来为你实现。简单的说,aidl 是为了开发者实现跨进程通信提供的一套规则和工具,自动建 基于 Binder 通信的跨进程交换标准模块

注意:基于 aidl 实现的跨进程通信,再多个客户端同时请求 server 服务时,server 的处理是多线程 并发处理的; 而在前面介绍的 Messenger 实现的 boud service 不是多线程处理的,最终其实走的 handler 的方式。



在你开始设计你的AIDL接口之前,你要意识到AIDL接口是直接的方法调用。在哪个线程处理完全取决于调用是来自本地还是远程。具体如下:

*来自本地的调用,执行过程发生在同一个线程里。如果调用发生在UI主线程,则AIDL接口执行也是在主线程。如果调用发生在另一个线程,则AIDL接口的执就在那个线程里。所以如果是本地线程访问service,你完全可以掌控事那个线程在执行(但是这种情况,其实就可以不必使用AIDL了,使用 Binder 获取 service 就行了)。

*调用来自远程进程。如果同时发生多个请求,你无法得知是哪个线程(服务进程中有一个线程池,专门用来处理并发请求的),也就是说AIDL接口必须确保线程安全。
*调用来自远程且实用 oneway关键字,远程调用将不会阻塞,发生transaction data数据之后方法立即返回。如果本地进程调用,oneway关机中无效。

实用AIDL创建bounded service的步骤:


  • 创建一饿.aidl文件

 在文件中使用java语法定义接口。

  • 实现接口。

 android SDK 工具会根据.aidl文件生产一个java接口,这个接口包含Stub ,Stub继承自Binder并且实现了这个接口。

  • 暴露接口给客户端程序

实现你的 service 并且在你的onBind()方法中返回一个Stub的之类对象。
注意:当你的AIDL接口改变时,确保向前兼容,因为你的AIDL已经向客户端程序发放,确保之前的是可用的。

1 来看看怎么创建.aidl文件
 AIDL使用简单的语法使你能够定义接口。参数支持的类型有
*所有java语言的原始数据类型。
*String
*CharSequence
*List,list的元素必须是AIDL支持的数据类型
*HashMap,元素必须是AIDL支持的数据类型
.aidl文件样例:

// IRemoteService.aidl
package com.example.android;
// Declare any non-de;fault types here with import statements
/** Example service interface */
interface IRemoteService {
    /** Request the process ID of this service, to do evil things with it. */
    int getPid();
    /** Demonstrates some basic types that you can use as parameters
     * and return values in AIDL.
     */
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat,
            double aDouble, String aString);
}

保存到项目src路径下,将自动生成对应的java文件到gen目录下。自动生成的java文件里面有个Stub类,这个类继承Binder且实现了这个接口,其中有几个重要的实现方法asInterface(),asBinder()等。

2 实现接口

实现AIDl文件里面定义的接口,即实现Stub里面的方法。

private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
    public int getPid(){
        return Process.myPid();
    }
    public void basicTypes(int anInt, long aLong, boolean aBoolean,
        float aFloat, double aDouble, String aString) {
        // Does nothing
    }
};

mBinder 也就是我们的 service 用来 RPC 的 Binder。

注意:
*调用方不保证来自主线程,你要考虑多线程调用的情况,且确保你的service服务方法是线程安全的。
*如果你知道你使用的服务会耗时,你应该避免在主线程调用。
*不要向调用方抛异常。

3 暴露接口给客户端

你需要通过一个service,在 service 的 onBind()方法中将你的 IRemoteService.Stub 实例返回出去,达到将服务接口暴露给客户端的目的。例如:

public class RemoteService extends Service {
    @Override
    public void onCreate() {
        super.onCreate();
    }

    @Override
    public IBinder onBind(Intent intent) {
        // Return the interface
        return mBinder;
    }

    private final IRemoteService.Stub mBinder = new IRemoteService.Stub() {
        public int getPid(){
            return Process.myPid();
        }
        public void basicTypes(int anInt, long aLong, boolean aBoolean,
            float aFloat, double aDouble, String aString) {
            // Does nothing
        }
    };
}

现在,当客户端(一个activity)调用bindService(),客户端的onServiceConnected()回调方法中将受到一个mBinder实例。客户端为了能调用方法,必须保存一份server端发放的.aidl文件在相同目录下,android 工具也会自动生成一份对应的java文件。 通过YourServiceInterface.Stub.asInterface(mBinder),转化成你所要使用的服务接口的实例。例如:

IRemoteService mIRemoteService;
private ServiceConnection mConnection = new ServiceConnection() {
    // Called when the connection with the service is established
    public void onServiceConnected(ComponentName className, IBinder service) {
        // Following the example above for an AIDL interface,
        // this gets an instance of the IRemoteInterface, which we can use to call on the service
        mIRemoteService = IRemoteService.Stub.asInterface(service);
    }

    // Called when the connection with the service disconnects unexpectedly
    public void onServiceDisconnected(ComponentName className) {
        Log.e(TAG, "Service has unexpectedly disconnected");
        mIRemoteService = null;
    }
};

到此为止,你已经知道怎么使用 aidl 来实现服务接口、客户端怎么获得服务远程代理然后如何调用服务端接口了,后续有时间提供一个 demo。然后再深入研究 Binder 是如何传递数据的、aidl 背后的架构。 

时间: 2024-08-18 02:20:22

boundService-AIDL的相关文章

Android远程service aidl的用法

AIDL即android 接口定义语言,概念不多说,网上有太多的帖子介绍概念.本文只想说明一下aidl的用法.由于最近开发一个播放器的项目使用了aidl.aidl是解决进程间通信用的.在本例中就是Activity(即client端)与Service(即服务端)的通信. 首先,定义Aidl文件,如Service中暴露给Activity的接口可以定义在aidl文件中,反之也一样.本文中,Service给Activity使用接口文件是ServiceAidl.aidl而Activity给Service回

Android:Service之AIDL传递系统基本类型数据

  什么是AIDL? 先来回顾一下,Android在本地的Service中如何与其它组件进行交互的,首先Service必须实现其onBind()方法,然后在onBind方法传递一个IBinder接口的实现,而在其它组件中使用bindService()绑定一个服务,再通过其中的参数ServiceConnection对象获取到Service中定义的IBinder接口的实现.那么与Service进行数据交互,其实就是传递一个IBinder,通过这个IBinder进行交互. 而现在就碰到一个问题,在同一

Android:Service之AIDL传递复杂对象

  AIDL传递复杂类型对象的特殊处理 前面已经介绍了通过AIDL接口在进程间传递系统允许的数据,如果需要传递一个复杂类型的对象,就没那么简单了,需要额外做一些处理.如下: 定义数据接口的AIDL文件中,使用parcelable关键字,例如:parcelable Message; 在其数据实现类中实现Parcelable接口,并实现对应的方法. 在业务接口的AIDL文件中,使用import引入数据接口AIDL的包名. 例如:Message.aidl 1 parcelable Message; 例

Android-使用AIDL进程间通信

对于客户端和服务之间通信,虽然可以通过Ibinder实现,但需要共享业务实现,如果在进程间通信的haunted,需要使用AIDL(Android Interface Definition Language)进行. AIDL是一种接口定义语言,用于约束两个进程间的通讯规则,编译器生成代码,实现Android设备上的两个进程间通信(IPC),AIDL的IPC机制和EJB所采用的CORBA很类似,进程之间的通信信息,首先会被转换成AIDL协议消息,然后发送给对方,对方收到AIDL协议消息后在转换成相应

android studio-Android Studio1.4版本无法在MainActivty中创建AIDL接口对象,rebuild提示aidl.exe出错,该如何解决?

问题描述 Android Studio1.4版本无法在MainActivty中创建AIDL接口对象,rebuild提示aidl.exe出错,该如何解决? Android Studio1.4版本无法在MainActivty中创建AIDL接口对象,rebuild提示aidl.exe出错,该如何解决? 解决方案 Android Studio中创建AIDL Service

非ROOT实现静默安装的一些思考与体会,AIDL获取IPackageManager,反射ServiceManager,系统签名

非ROOT实现静默安装的一些思考与体会,AIDL获取IPackageManager,反射ServiceManager,系统签名 最近自家的系统要做一个升级服务,里面有三个功能,第一个是系统升级,也就是下载OTA包推送到recovery里升级的,而第二个是MCU升级,这就涉及到我们自家系统的一些情况了,而第三个就是应用升级了,领导要求不要骚扰用户,于是我就想到了静默安装了,因为我们的系统是在wifi环境下工作的,所以不担心流量哈,而且我们系统是没有ROOT的,所以我们肯定野不能使用RunTime方

aidl使用问题,有点乱!!!

问题描述 aidl使用问题,有点乱!!! 很多博文说复制aidl文件到客户端时,包名不能改变,但是我写了Demo,证明改了包名也是没有问题的,只要自动生成的.java里DESCRIPTOR字段和服务器端自动生成的一样就没问题,不一样就会报错.但是我们公司有两个项目,包名和DESCRIPTOR字段都和服务器不一样,但是也没问题,晕了,,,不知道怎么回事,请大神赐教! 解决方案 http://blog.csdn.net/stonecao/article/details/6425019

Android AIDL实现进程间通信探索_Android

前言:       前面总结了程序间共享数据,可以使用ContentProvider也可以使用SharedPreference,那么进程间怎么共享内存呢?Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信.       为了使其他的应用程序也可以访问本应用程序提供的服务,Android系统采用了远程过程调用(Remote Procedure Call,RPC)方式来实现.与很多其他的基于RPC的解决方案一样,Android使用一种接口定义语言(Inter

aidl-Android studio写AIDL时报错:Execution failed for task,

问题描述 Android studio写AIDL时报错:Execution failed for task, 我用的是Android Studio 1.4 第二张图compile sdk version那里只能选api level 23. 在aidl包下我写了2个aidl文件,另外MainActivity那个包中的MyParcelClass,这3个和aidl有关.下面贴下代码: MyParcelClass.java public class MyParcelableClass implement

android跨进程通信(IPC):使用AIDL

AIDL的作用 AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在Android设备上两个进程之间进行进程间通信(interprocess communication, IPC)的代码.如果在一个进程中(例如Activity)要调用另一个进程中(例如Service)对象的操作,就可以使用AIDL生成可序列化的参数. AIDL IPC机制是面向接口的,像COM或Corba一样,但是更加轻量级.它是使用代理类在客户端和实现端传