Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> AIDL在android系統中的作用

AIDL在android系統中的作用

編輯:關於Android編程

AIDL,Android Interface definition language的縮寫,它是一種android內部進程通信接口的描述語言,通過它我們可以定義進程間的通信接口。最近看了下AIDL在Android系統中的用法,在網上看到很多初學的朋友不太明白AIDL的實際作用,android提供了很多進程間通信的組件,像action、broadcast、contentprovide都可以實現進程間的通信,為什麼還要用AIDL這個東西呢?我在android源碼中實現了一個自己寫的AIDL例子,用以簡單解釋下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通信的橋梁。

下面看我加的一個例子:

首先在android源碼中的frameworks/base/core/java/android/os/目錄下加入一個IMyTestService.aidl,一般系統的AIDL文件都放在這個目錄下。

package android.os;

/** {@hide} */
interface IMyTestService
{
    void open();
    void close();
}

關於AIDL的語言規范我就不多說了,其實和Java寫接口差不多(它本來就是一種接口語言)。裡面只定義兩個簡單的方法,open和close。

然後在frameworks/base/Android.mk中添加一句:core/java/android/os/IMyTestService.aidl。android系統的編譯目標是通過Android.mk來指定的,在這裡加上自定義的aidl文件系統才會把這個文件編譯進去,最終生成一個叫IMyTestService.java的文件。這一部分用eclipse可以很直觀的看到,在項目添加了aidl文件後eclipse會自動編譯此aidl,生成的文件存放在gen目錄下。

AIDL添加好了後,在frameworks/base/services/java/com/android/server/目錄下添加一個MyTestService.java,繼承IMytestService這個aidl。

package com.android.server;

import android.net.wifi.WifiManager;
import android.content.Context;
import android.os.IMyTestService;
import android.util.Log;

public class MyTestService extends IMyTestService.Stub {

    private static final String TAG = "MyTestService";
    private Context mContext;
    private WifiManager mWifiManager;

    public MyTestService(Context context/*,WindowManagerService wm*/) {
        super();
        mWifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
    }

    /* close wifi */
    public void close() {
        mWifiManager.setWifiEnabled(false);
    }

    /* open wifi */
    public void open() {
        mWifiManager.setWifiEnabled(true);
    }
}

實現aidl文件中定義的open和close方法,我這裡很簡單,open就是去打開wifi,close就去關閉wifi,當然,你也可以實現你自定義的功能,這個沒有限制。

然後在frameworks/base/core/java/android/content/Context.java文件中加入一個靜態字符串:public static final String MY_TEST_SERVICE ="my_test_service";

最後把這個服務添加到系統服務中去,在frameworks/base/services/java/com/android/server/SystemServer.java中Thread的run方法中添加下面代碼:


try {
                 Slog.i(TAG, "My Test Service");
                 myService = new MyTestService(context);
                 ServiceManager.addService(Context.MY_TEST_SERVICE, myService);
             } catch (Throwable e) {
                 reportWtf("starting my test Service", e);
             }

myService需要在前面聲明一下。

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


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

在frameworks/base/core/java/android/device/目錄下添加MyTestManager.java文件:


package android.device;
import android.util.Log;
import android.content.Context;
import android.os.RemoteException;
import android.os.IMyTestService;
import android.os.ServiceManager;

public class MyTestManager {

private static final String TAG = "MyTestManager";
private IMyTestService mTestService;

    public MyTestManager() {
        IMyTestService mService = IMyTestService.Stub
                .asInterface(ServiceManager.getService(Context.MY_TEST_SERVICE));
        mTestService = mService;
    }
    /**
     * Return true if open succeed
     * @see #open my Function()
     */
    public boolean openScanner() {
        try {
            mTestService.open();
        } catch (android.os.RemoteException e) {
            return false;
        }
        return true;
    }
    /**
     * Return true if close succeed
     * @see #close my Function()
     */
     public boolean closeScanner() {
         try {
              mTestService.close();
         } catch (android.os.RemoteException e) {
              return false;
         }
         return true;
    }
}

這個Manager通過aidl的Stub獲取了剛才添加的那個系統級別的service,然後在這裡去調用這個service的方法,以操作service,這就是aidl的作用。

然後我們可以寫一個第三方程序,獲取一個MyTestManager,調用這個管理類的openScanner和closeScanner方法去實現自己在service中定義的功能。

AndroidManifest中必須要添加權限,否則報錯,沒有研究這個權限起的什麼作用,有懂得的朋友分享一下吧。

import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.app.Activity;
import android.device.MyTestManager;

public class MainActivity extends Activity {
    private Button open, close;
    private MyTestManager mTestManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mTestManager = new MyTestManager();
        open = (Button) findViewById(R.id.btn1);
        open.setText("打開Wifi");
        close = (Button) findViewById(R.id.btn2);
        close.setText("關閉Wifi");

        open.setOnClickListener(new OnClickListener() {

           @Override
            public void onClick(View v) {
                // TODO Auto-generated method stub
                mTestManager.openScanner();
            }
       });

        close.setOnClickListener(new OnClickListener() {

           @Override
            public void onClick(View v) {
               // TODO Auto-generated method stub
               mTestManager.closeScanner();
            }
        });
    }
}

這也就實現了Android誇進程通信了。

這裡只是一個很簡單的例子,以便不理解這一塊的朋友管中窺豹,其實AIDL和系統級服務的配合使用遠沒這麼簡單,但是大致原理是這樣的,比如Android的網絡服務,google定義了很多的狀態,通過後台的Service不斷的監聽這些狀態的變化去控制網絡,又比如電源管理,控制屏幕的亮度等等,復雜的是其中繁多的狀態變化。

文章寫的比較淺顯,希望大家多多指教。


  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved