1. 程式人生 > >AIDL在Android原始碼中的使用

AIDL在Android原始碼中的使用

一:AIDL,Android Interface definition language的縮寫,它是一種android內部程序通訊介面的描述語言,通過它我們可以定義程序間的通訊介面。最近看了下AIDL在Android系統中的用法,在網上看到很多初學的朋友不太明白AIDL的實際作用,android提供了很多程序間通訊的元件,像action、broadcast、contentprovide都可以實現程序間的通訊,為什麼還要用AIDL這個東西呢?

有開發過藍芽或者WIFI應用的朋友肯定都知道,要去操作它必須先獲得一個管理類,比如WIFI的管理類是WifiManager,通過getSystemService(Context.WIFI_SERVICE)就可以得到wifi的管理許可權,這個提供了很多的方法可以讓使用者去操作它,比如開啟wifi可以呼叫setWifiEnabled(true)方法。那這個Manager到底做了什麼工作呢?是怎樣實現開啟wifi的呢?其實這個Manager只是一個管理類,真正幹活的另有其人,是一個叫WifiService的系統服務。在Android系統中有很多的Manager,wifi的管理類叫WifiManager,藍芽的管理類叫BluetoothManager,但是,只要有xxxManager.java,就會有Ixxx.aidl,並且有xxxService.java。這個aidl類就是實現Manager和Service通訊的橋樑。

下面我們以原始碼中的WIFI為例來講述一下AIDL在原始碼中的使用:

首先在這個目錄下是已定義好的一個AIDL檔案

frameworks/base/wifi/java/android/net/wifi/IWifiManager.aidl

關於AIDL的語言規範我就不多說了,其實和Java寫介面差不多(它本來就是一種介面語言)。

然後在frameworks/base/Android.mk中新增一句:wifi/java/android/net/wifi/IWifiManager.aidl。android系統的編譯目標是通過Android.mk來指定的,在這裡加上自定義的aidl檔案系統才會把這個檔案編譯進去,最終生成一個叫IWifiManager

.java的檔案。這一部分用eclipse可以很直觀的看到,在專案添加了aidl檔案後eclipse會自動編譯此aidl,生成的檔案存放在gen目錄下。

AIDL新增好了後,定義了一個service繼承IWifiManager這個aidl並實現了其中的方法。

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiServiceImpl.java

然後在下面這個類中包裝了一下

frameworks/opt/net/wifi/service/java/com/android/server/wifi/WifiService.java

然後在frameworks/base/core/java/android/content/Context.java檔案中加入一個靜態字串:

public static final String WIFI_SERVICE = "wifi";

最後這個服務在SystemServer中啟動

frameworks/base/services/java/com/android/server/SystemServer.java

private static final String WIFI_SERVICE_CLASS =
        "com.android.server.wifi.WifiService";
mSystemServiceManager.startService(WIFI_SERVICE_CLASS);

SystemService是android系統跑起來之後就會呼叫的,這裡的意思是把WifiService新增到系統服務中去,並取名字叫Context.WIFI_SERVICE,也就是wifi。這樣看起來是不是很熟悉呢?每個開發人員在開發過程中肯定會呼叫系統服務的,比如電源管理服務:getSystemService(Context.POWER_SERVICE),這個Service也是在這裡新增進去的。android有很多的系統服務,這裡就不一一例舉了,有興趣的朋友可以自行看看這個檔案。

現在aidl添加了,service也添加了,並且新增進了系統服務,那麼還少一個Manager,可以讓第三方程式呼叫的Manager。

frameworks/base/wifi/java/android/net/wifi/WifiManager.java

/**
 * Create a new WifiManager instance.
 * Applications will almost always want to use
 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
 * the standard {@link android.content.Context#WIFI_SERVICE Context.WIFI_SERVICE}.
 * @param context the application context
 * @param service the Binder interface
 * @hide - hide this because it takes in a parameter of type IWifiManager, which
 * is a system private class.
 */
public WifiManager(Context context, IWifiManager service, Looper looper) {
    mContext = context;
    mService = service;
    mLooper = looper;
    mTargetSdkVersion = context.getApplicationInfo().targetSdkVersion;
}

這個Manager的例項化是通過下面的方法實現的

(WifiManager) context.getSystemService(Context.WIFI_SERVICE)

這個系統的方法和通過aidl的Stub獲取service是相通的,然後在這裡去呼叫這個service的方法,以操作service,這就是aidl的作用。

二:原始碼編譯AIDL Android.mk的寫法:

LOCAL_SRC_FILES := $(call all-java-files-under)

LOCAL_SRC_FILES += \
src/com/asus/cnfindphone/service/persistentdata/IDataBlockService.aidl