編輯:關於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不斷的監聽這些狀態的變化去控制網絡,又比如電源管理,控制屏幕的亮度等等,復雜的是其中繁多的狀態變化。
文章寫的比較淺顯,希望大家多多指教。
手機高德地圖怎麼看街景呢?高德地圖查看街景方法是什麼呢?下面,小編來教教大家如何利用手機高德地圖來看街景。高德地圖app查看街景方法第一步、打開手機版【高德
目前針對公司Android端的SDK進行實際測試,反映出存在網絡加載資源緩慢的問題,在知曉目前CDN的可能存在不穩定的情況下,針對sdk本身的網絡模塊進行了相應的分析,整
Android使用GridView實現日歷功能示例,代碼有點多,發個圖先:如果懶得往下看的,可以直接下載源碼吧,最近一直有人要,由於時間太久了,懶得找出來整理,今天又看到
Toast吐司Toast吐司是我們經常用到的一個控件,Toast是AndroidOS用來顯示消息的一種機制,它與Dialog不同,Toast不會獲取到焦點,通常顯示一段時