安卓接口語言 Android Interface Definition Language (AIDL)

翻譯作者地址:http://su1216.iteye.com/%20http://blog.csdn.net/su1216/

AIDL一般都用在需要比較複雜的跨進程/線程通信場合。比如自己的程序需要用一個Service去處理各種事務,而又需要跟Service能相互調用的場合。要注意的是AIDL不是線程安全的,如有這方面需要的話就要自己處理好臨界情況。

使用AIDL只有在你允許來自不同應用的客戶端跨進程通信訪問你的service,並且想要在你的service種處理多線程的時候纔是必要的。 如果你不需要執行不同應用之間的IPC併發,你應該通過實現Binder建立你的接口,或者如果你想執行IPC,但是不需要處理多線程。那麼使用Messenger實現你的接口 不管怎樣,確保你在實現一個AIDL之前理解了Bound Service

下面以客戶端A應用調用B應用爲例

1.定義一個AIDL接口

創建一個以.aidl結尾的文件。打開創建的文件,使用java語言定義一個接口,接口只包含接口聲明和方法簽名。如下
// IRemoteService.aidl
package com.example.android;
/** Example service interface */
interface IRemoteService {
   //接口聲明
    int getPid();
    //方法聲明(方法可以接收0或多個參數,並且有返回值或者返回void)
    void basicTypes(int anInt, long aLong, boolean aBoolean, float aFloat);
}

保存.aidl文件在src目錄下

2.實現接口

當你編譯你的應用時,Android SDK工具生成一個.java接口文件用你的.aidl文件命名 生成的接口包含一個名字爲Stub的子類(比如YourInterface.Stub),這是一個它父類的抽象實現,並且聲明瞭.aidl中所有的方法

//IRemoteService.Stu是IBinder的子類
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
    }
};

3.暴露接口給客戶端

一旦你爲service實現了接口,你需要把它暴露給客戶端,這樣他們才能綁定到上面 爲了給你的service暴露接口,繼承Service並且實現onBind()方法返回一個你實現生成的Stub類(像我們在上一結討論的那樣) 這有一個service暴露IRemoteService接口給客戶端的例子

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) {
            // Do something(執行邏輯)
        }
    };
}

在B應用的manifes中,service的相關配置片段

<service android:name="com.zhangxikai.RemoteService">
            <intent-filter >
                <action android:name="com.zahngxikai.aidl"/>
            </intent-filter>
</service>

通過以上三步我們完成了被調用端B的工作。

現在,當一個客戶端(比如一個activity)調用bindService()來連接到這個service,這個客戶端的onServiceConnected()回調函數接收service中onBind()方法返回的mBinder實例

客戶端必須可以訪問接口類,所以如果客戶端和服務端在不同的應用中,那麼客戶端所在的應用必須有一份.aidl文件的副本在其src目錄下(生成android.os.Binder接口,提供客戶端訪問AIDL方法都在這個目錄下)

當客戶端在onServiceConnected()回調方法中接收到IBinder時,它必須調用你的ServiceInterface.Stub.asInterface(service)來把返回參數映射到你的ServiceInterface類型上。例如:

IRemoteService mIRemoteService;
private ServiceConnection mConnection = new ServiceConnection() {
    public void onServiceConnected(ComponentName className, IBinder service) {
    //獲取接口
        mIRemoteService = IRemoteService.Stub.asInterface(service);
    }
    public void onServiceDisconnected(ComponentName className) {
        Log.e(TAG, "Service has unexpectedly disconnected");
        mIRemoteService = null;
    }
};
在A應用中調用B應用的basicTypes方法
Intent intent = new Intent();
intent.setAction("com.zahngxikai.aidl");
bindService(intent,mConnection,BIND_AUTO_CREATE);
//調用B應用中的相關函數(最終目的)
mIRemoteService.basicTypes(....參數);

Android中文api原文地址:這裏寫鏈接內容

發佈了27 篇原創文章 · 獲贊 11 · 訪問量 2萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章