標籤:
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檔案都放在這個目錄下。
?
| 12345678 |
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。
?
| 12345678910111213141516171819202122232425262728 |
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方法中添加下面代碼:
?
| 1234567 |
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檔案:
?
| 12345678910 |
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"; |
?
| 1234567891011121314151617181920212223242526272829303132 |
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中必須要添加許可權,否則報錯,沒有研究這個許可權起的什麼作用,有懂得的朋友分享一下吧。
?
| 1234567891011121314151617181920212223242526272829303132333435363738394041 |
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不斷的監聽這些狀態的變化去控制網路,又比如電源管理,控制螢幕的亮度等等,複雜的是其中繁多的狀態變化。
文章寫的比較淺顯,希望大家多多指教。
推推族,免費得門票,遊景區:www.tuituizu.com
結伴旅遊,一個免費的交友網站:www.jieberu.com
AIDL在android系統中的作用