A. 如何創建android系統服務
1、 撰寫一個aidl文件,定義服務的介面,將在編譯過程中通過aidl工具生成對應的java介面。一般系統服務的aidl文件都放在framework\base\core\java\android\os目錄中。
以我所寫的IMyTool.aidl為例。在.aidl中定義自己需要加入的方法,編寫規則和java介面差不多,這里不多說。
2、 將aidl文件名添加到frameworks\base\目錄下的Android.mk編譯腳本文件中。
如:
LOCAL_SRC_FILES += \
core/java/android/accessibilityservice/.aidl\
…\
core/java/android/os/IMyTool.aidl\
…
IMyTool.aidl即我加進去的aidl文件,加入後才能在make過程中編譯到,否則將在後面的SystemServer添加系統服務時會報錯提示找不到對應類。
3、 編寫真正工作的服務類,繼承IMyTool.Stub類(AIDL文件名.Stub,aidl生成的介面中的內部類,是一個Binder)。
服務類一般都放在framework\base\services\java\com\android\server目錄中。
例如:
public class MyToolService extends IMyTool.Stub {
實現IMyTool.aidl中定義的介面。
}
4、 將自定義服務注冊到SystemServer,使得開機過程中被添加。
在framework\base\services\java\com\android\server目錄中的SystemServer中啟動服務代碼處加入:
try {
Slog.i(TAG, "MyToolService");
ServiceManager.addService(Context.MY_TOOL_SERVICE,new MyToolService(context));// MyToolService構造函數自己定義,一般都會用到Context
} catch(Throwable e) {
Slog.e(TAG, "Failure startingMyToolService", e);
}
上面代碼中Context.MY_TOOL_SERVICE是自己在Context類中定義的常量,也就是給服務定義的名字,使用常量方便獲取服務,而不需要記住注冊服務時用的名字,且想換名字時只需改一個常量的值。
B. 如何在Android中使用AIDL設計遠程介面麻煩告訴我
在Android平台,一個進程通常不能訪問另一個進程的內存空間,所以要想對話,需要將對象分解成操作系統可以理解的基本單元,並且有序地通過進程邊界。
通過代碼來實現這個數據傳輸過程是冗長乏味的,Android提供了AIDL工具來處理這項工作。AIDL()是一種IDL語言,用於生成可以在Android設備上兩個進程之間進行進程間通信(IPC)的代碼。如果在一個進程中(例如Activity)要調用另一個進程中(例如Service)對象的操作,就可以使用AIDL生成可序列化的參數。AIDLIPC機制是面向介面的,像COM或Corba一樣,但是更加輕量級。它是使用代理類在客戶端和實現端傳遞數據。
一、使用AIDL實現IPC(ImplementingIPCUsingAIDL)
使用AIDL實現IPC服務的步驟是:第一,創建.aidl文件。該文件(YourInterface.aidl)定義客戶端可用的方法和數據介面。第二,在makefile文件中加入.aidl文件(Eclipse中的ADT插件提供管理功能)。Android包括名為AIDL的編譯器,位於tools/文件夾。第三,實現介面-AIDL編譯器從AIDL介面文件中利用Java語言創建介面。該介面有一個繼承的命名為Stub的內部抽象類(已實現一些IPC調用的附加方法),要做的就是創建一個繼承於YourInterface.Stub的類,並且實現在.aidl文件中聲明的方法。第四,向客戶端公開介面。如果是編寫服務,應該繼承Service並且重載Service.onBind(Intent)以返回實現了介面的對象實例。
二、創建.aidl文件(Createan.aidlFile)
AIDL使用簡單的語法來聲明介面,描述其方法以及方法的參數和返回值。這些參數和返回值可以是任何類型,甚至是其他AIDL生成的介面。需要注意的是,必須導入所有非內置類型。AIDL能支持的數據類型有以下幾類:第一,Java編程語言的主要類型(int,boolean等),不需要import語句。第二,通常引引用方式傳遞的其他AIDL生成的介面,必須要import語句聲明。第三,實現了Parcelableprotocol以及按值傳遞的自定義類,必須要import語句聲明。另外,還有一些不需要import語句,如String等。
三、實現介面(ImplementingtheInterface)
AIDL生成了與.aidl文件同名的介面,如果使用Eclipse插件,AIDL會作為編譯碰歷過程的一部分自動運行(不需要先運行AIDL再編譯項目);如果沒有插件,就要先運行AIDL。
生成的介麵包含一個名為Stub的抽象的內部類,該類聲明了所有.aidl中描述的方法,Stub還定義了少量的輔助方法,尤其是asInterface(),通過它獲得IBinder(當applicationContext.bindService()成功調用時傳遞到客戶端的onServiceConnected())並且返回用於調用IPC方法的介面實例。要實現自己的介面,就從YourInterface.Stub類繼承,然笑蠢搜後實現相關方法(可以創建.aidl文件實現stub方法而不用在中間編譯,Android編譯過程會在.java文件之前處理.aidl文件)。
在完成了介面的實現後,需要向客戶端暴露介面,也就是發布服務。實現的方法是繼承Service,然後檔知實現以Service.onBind(Intent)返回一個實現了介面的類對象。下面的代碼片斷表示了暴露IRemoteService介面給客戶端的方式。如果有類想要能過AIDL在進程之間傳遞,這一想法是可以實現的,但必須確保這個類在IPC的兩端的有效性。
以上是筆者對《Android中使用AIDL設計遠程介面》的一些思路與實現方法。筆者認為,由於Android自身的集成性、控制性、交互性等特點,可以激發學生的學習的興趣,調動學生的積極參與,擴大學生知識面,提供多種學習的路徑。
(作者單位:鎮江技師學院)