SystemUI之拓展篇(aidl的使用)

本文介绍了Android Interface Define Language (AIDL),一种用于处理不同进程间通信的技术。AIDL允许开发者将对象转换为操作系统可理解的形式,以实现跨进程对象访问。通过AIDL,可以定义接口,编译器会自动生成相关代码,实现进程间的通信。文章提到,虽然理论上AIDL支持传递Bundle,但在实际操作中可能会遇到挑战。此外,还提到了AIDL支持的基本数据类型,如int、String,以及List、Map和Parcelable。最后,文章通过SystemUI中的实际例子来展示AIDL的使用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1.首先解释下AIDL

全称是:Android Interface Define Language

在Android中, 每个应用程序都可以有自己的进程. 在写UI应用的时候, 经常要用到Service. 在不同的进程中, 怎样传递对象呢? 显然,Java中不允许跨进程内存共享.

 因此传递对象, 只能把对象拆分成操作系统能理解的简单形式, 以达到跨界对象访问的目的. 在J2EE中,采用RMI的方式, 可以通过序列化传递对象. 在Android中, 则

采用AIDL的方式. 理论上AIDL可以传递Bundle,实际上做起来却比较麻烦。

AIDL(AndRoid接口描述语言)是一种借口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要

在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用

这些参数组装成自己需要的对象.AIDL的IPC的机制和COM或CORBA类似, 是基于接口的,但它是轻量级的。它使用代理类在客户端和实现层间传递值. 如果要使用AIDL, 

需要完成2件事情: 1. 引入AIDL的相关类.; 2. 调用aidl产生的class.

AIDL的创建方法:

AIDL语法很简单,可以用来声明一个带一个或多个方法的接口,也可以传递参数和返回值。 由于远程调用的需要, 这些参数和返回值并不是任何类型.

下面是些AIDL支持的数据类型:

a. 不需要import声明的简单Java编程语言类型(int,boolean等)

b. String, CharSequence不需要特殊声明

c. List, Map和Parcelables类型, 这些类型内所包含的数据成员也只能是简单数据类型, String等其他比支持的类型.

(另外: 我没尝试Parcelables, 在Eclipse+ADT下编译不过, 或许以后会有所支持


2.举个在SystemUI里面的使用例子

NotificationManager.java里面调用 enqueueNotificationWithTag方法,该方法在INotificationManager.aidl里面申明,NotificationManagerService.java中实例化了INotificationManager.aidl。
路径:
framework/base/core/java/android/app/NotificationManager.java
framework/base/services/core/java/com/android/server/notification/NotificationManagerService.java
frameworks/base/core/java/android/app/INotificationManager.aidl
先看下该aidl的申明部分。进入 NotificationManagerService.java,new了一个aidl返回一个IBinder对象。
 private final IBinder mService = new INotificationManager.Stub()
注:这里的Stub()方法是在编译aidl文件后生成的Java文件里面。
参考:http://blog.youkuaiyun.com/saintswordsman/article/details/5130947
然后调用publishBinderService申明该IBind对象
public void onStart() {
。。。
 mArchive = new Archive(resources.getInteger(
                R.integer.config_notificationServiceArchiveSize));
publishBinderService(Context.NOTIFICATION_SERVICE, mService);
        publishLocalService(NotificationManagerInternal.class, mInternalService);
    }
Context.NOTIFICATION_SERVICE为mService的唯一标识,我们进到Context.java里面看到字段定义如下:
路径:frameworks/base/core/java/android/content/Context.java
  /**
     * Use with {@link #getSystemService} to retrieve a
     * {@link android.app.NotificationManager} for informing the user of
     * background events.
     *
     * @see #getSystemService
     * @see android.app.NotificationManager
     */
    public static final String NOTIFICATION_SERVICE = "notification";
我们接着回来看 publishBinderService()方法
  /**
     * Publish the service so it is accessible to other services and apps.
     */
    protected final void publishBinderService(String name, IBinder service) {
        publishBinderService(name, service, false); //NotificationManagerService.java继承自SystemService.java,该方法在父类中定义
    }
 /**
     * Publish the service so it is accessible to other services and apps.
     */
    protected final void publishBinderService(String name, IBinder service,
            boolean allowIsolated) {
        ServiceManager.addService(name, service, allowIsolated);
    }
把服务添加到ServiceManager里面。
路径:
frameworks/base/services/core/java/com/android/server/SystemService.java
frameworks/base/core/java/android/app/SearchManager.java
我们进到SearchManager.java看看,
/**
     * Place a new @a service called @a name into the service
     * manager.
     * 
     * @param name the name of the new service
     * @param service the service object
     */
    public static void addService(String name, IBinder service) {
        try {
            getIServiceManager().addService(name, service, false);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }


    /**
     * Place a new @a service called @a name into the service
     * manager.
     * 
     * @param name the name of the new service
     * @param service the service object
     * @param allowIsolated set to true to allow isolated sandboxed processes
     * to access this service
     */
    public static void addService(String name, IBinder service, boolean allowIsolated) {
        try {
            getIServiceManager().addService(name, service, allowIsolated);
        } catch (RemoteException e) {
            Log.e(TAG, "error in addService", e);
        }
    }
    这样就完整的添加到ServiceManager里。
补充:SystemService.java和Service.java的区别。我们来看下两个文件的定义:
路径:
frameworks/base/services/core/java/com/android/server/SystemService.java
frameworks/base/core/java/android/app/Service.java
public abstract class SystemService{};
public abstract class Service extends ContextWrapper implements ComponentCallbacks2 {}
可以很明显的看到,SystemService是我们自定义的一个方法,而Service是系统组件,和activity,BroadcastReciever这些类似。
一般Service是在app内部使用,跨app通信的话也可以用Bind,aidl来实现。

接着我们来看怎么调用这个aidl。先来看下NotificationManager.java里初始化INotificationManager.aidl的地方
路径:frameworks/base/core/java/android/app/NotificationManager.java
public void notifyAsUser(String tag, int id, Notification notification, UserHandle user)
    {
        int[] idOut = new int[1];
        INotificationManager service = getService();
        String pkg = mContext.getPackageName();
       。。。
    }
这里调用了getService()方法,进到方法看下
 /** @hide */
    static public INotificationManager getService()
    {
        if (sService != null) {
            return sService;
        }
        IBinder b = ServiceManager.getService("notification");
        sService = INotificationManager.Stub.asInterface(b);
        return sService;
    }
可以看到,通过“notification”从ServiceManager获取到IBinder对象,这样aidl从定义到客户端调用就已经完整实现了。

















评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值