【正文】
vice) { 70 mathService = (()service).getService()。 71 } 72 本地服務(wù) ? 服務(wù)綁定 ? 73 Override 74 public void onServiceDisconnected(ComponentName name) { 75 mathService = null。 76 } 77 }。 78 } 遠(yuǎn)程服務(wù) ? 進(jìn)程間通信 ? 在 Android系統(tǒng)中,每個應(yīng)用程序在各自的進(jìn)程中運(yùn)行,而且出于安全原因的考慮,這些進(jìn)程之間彼此是隔離的,進(jìn)程之間傳遞數(shù)據(jù)和對象,需要使用 Android支持的進(jìn)程間通信( InterProcess Communication, IPC)機(jī)制 ? 在 Unix/Linux系統(tǒng)中,傳統(tǒng)的 IPC機(jī)制包括共享內(nèi)存、管道、消息隊(duì)列和 socket等等,這些 IPC機(jī)制雖然被廣泛使用,但仍然存在著固有的缺陷,如容易產(chǎn)生錯誤、難于維護(hù)等等 ? 在 Android系統(tǒng)中,沒有使用傳統(tǒng)的 IPC機(jī)制,而是采用Intent和遠(yuǎn)程服務(wù)的方式實(shí)現(xiàn) IPC,使應(yīng)用程序具有更好的獨(dú)立性和魯棒性 遠(yuǎn)程服務(wù) ? 進(jìn)程間通信 ? Android系統(tǒng)允許應(yīng)用程序使用 Intent啟動 Activity和Service,同時 Intent可以傳遞數(shù)據(jù),是一種簡單、高效、易于使用的 IPC機(jī)制 ? Android系統(tǒng)的另一種 IPC機(jī)制就是遠(yuǎn)程服務(wù),服務(wù)和調(diào)用者在不同的兩個進(jìn)程中,調(diào)用過程需要跨越進(jìn)程才能實(shí)現(xiàn) ? 在 Android系統(tǒng)中使用遠(yuǎn)程服務(wù),一般按照以下三個步驟實(shí)現(xiàn) ? 使用 AIDL語言定義遠(yuǎn)程服務(wù)的接口 ? 根據(jù) AIDL語言定義的接口,在具體的 Service類中實(shí)現(xiàn)接口中定義的方法和屬性 ? 在需要調(diào)用遠(yuǎn)程服務(wù)的組件中,通過相同的 AIDL接口文件,調(diào)用遠(yuǎn)程服務(wù) 遠(yuǎn)程服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 在 Android系統(tǒng)中,進(jìn)程之間不能直接訪問相互的內(nèi)存控件,因此為了使數(shù)據(jù)能夠在不同進(jìn)程間傳遞,數(shù)據(jù)必須轉(zhuǎn)換成能夠穿越進(jìn)程邊界的系統(tǒng)級原語,同時,在數(shù)據(jù)完成進(jìn)程邊界穿越后,還需要轉(zhuǎn)換回原有的格式 ? AIDL( Android Interface Definition Language)是Android系統(tǒng)自定義的接口描述語言,可以簡化進(jìn)程間數(shù)據(jù)格式轉(zhuǎn)換和數(shù)據(jù)交換的代碼,通過定義 Service內(nèi)部的公共方法,允許在不同進(jìn)程間的調(diào)用者和 Service之間相互傳遞數(shù)據(jù) ? AIDL的 IPC機(jī)制、 COM和 Corba都是基于接口的輕量級進(jìn)程通信機(jī)制 遠(yuǎn)程服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? AIDL語言的語法與 Java語言的接口定義非常相似,唯一不同之處在于, AIDL允許定義函數(shù)參數(shù)的傳遞方向 ? AIDL支持三種方向: in、 out和 inout ? 標(biāo)識為 in的參數(shù)將從調(diào)用者傳遞到遠(yuǎn)程服務(wù)中 ? 標(biāo)識為 out的參數(shù)將從遠(yuǎn)程服務(wù)傳遞到調(diào)用者中 ? 標(biāo)識為 inout的參數(shù)將先從調(diào)用者傳遞到遠(yuǎn)程服務(wù)中,再從遠(yuǎn)程服務(wù)返回給調(diào)用者 ? 如果不標(biāo)識參數(shù)的傳遞方向,默認(rèn)所有函數(shù)的傳遞方向?yàn)?in ? 出于性能方面的考慮,不要在參數(shù)中標(biāo)識不需要的傳遞方向 遠(yuǎn)程服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 遠(yuǎn)程服務(wù)的創(chuàng)建和調(diào)用需要使用 AIDL語言,一般分為以下幾個過程 ? 使用 AIDL語言定義遠(yuǎn)程服務(wù)的接口 ? 通過繼承 Service類實(shí)現(xiàn)遠(yuǎn)程服務(wù) ? 綁定和使用遠(yuǎn)程服務(wù) 遠(yuǎn)程服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 下面以 RemoteMathServiceDemo示例為參考,說明如何創(chuàng)建遠(yuǎn)程服務(wù) ? 在這個示例中定義了 MathService服務(wù),可以為遠(yuǎn)程調(diào)用者提供加法服務(wù) ? 使用 AIDL語言定義遠(yuǎn)程服務(wù)的接口 ? 首先使用 AIDL語言定義 MathService的服務(wù)接口,服務(wù)接口文件的擴(kuò)展名為 .aidl,使用的包名稱與 Android項(xiàng)目所使用的相同 ? 在 src目錄下的建立 ,代碼如下 1 package 。 2 interface IMathService { 3 long Add(long a, long b)。 4 } 遠(yuǎn)程服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 從上面的代碼中可以看出, IMathService接口僅包含一個add()方法,傳入的參數(shù)是兩個長型整數(shù),返回值也是長型整數(shù) ? 使用 Eclipse編輯 ,當(dāng)保存文件后Eclipse的 ADT插件根據(jù) AIDL文件在 gen目錄下生產(chǎn) java接口文件 ? 右圖為 遠(yuǎn)程服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 使用 AIDL語言定義遠(yuǎn)程服務(wù)的接口 ? ,生成了一個內(nèi)部靜態(tài)抽象類 Stub, Stub繼承了 Binder類,并實(shí)現(xiàn) IMathService接口 ? 在 Stub類中,還包含一個重要的靜態(tài)類 Proxy??梢哉J(rèn)為Stub類用來實(shí)現(xiàn)本地服務(wù)調(diào)用, Proxy類用來實(shí)現(xiàn)遠(yuǎn)程服務(wù)調(diào)用,將 Proxy作為 Stub的內(nèi)部類完全是出于使用方便的目的 遠(yuǎn)程服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 使用 AIDL語言定義遠(yuǎn)程服務(wù)的接口 ? Stub類和 Proxy類關(guān)系圖 A I D L 文 件I M a t h S e r v i c e . a i d lA I D L工 具生 成 J a v a 接 口 文 件I M a t h S e r v i c e . j a v a生 成 內(nèi) 部 靜 態(tài) 抽 象 S t u b 類I M a t h S e r v i c e . S t u b生 成 內(nèi) 部 靜 態(tài) P r o x y 類I M a t h S e r v i c e . S t u b . P r o x y遠(yuǎn) 程 服 務(wù) 對 象使 用 a s l n t e r f a c e ( ) 獲 取遠(yuǎn) 程 P r o x y 對 象 的 引 用T r a n s a c t ( )本 地 服 務(wù) 對 象S t u b . a s I n t e r f a c e ( ) 用 來 返回 遠(yuǎn) 程 服 務(wù) 對 象 ( P r o x y )o n T r a n s a c t ( )I M a t h S e r v i c e . S t u bI M a t h S e r v i c e a s I n t e r f a c e ( I B i n d e r o b j )I B i n d e r a s B i n d e r ( )b o o l e a n o n T r a n s a c t ( i n t c o d e , P a r c e l d a t a , P a r c e l r e p l y , i n t f l a g s ) I B i n d e r a s B i n d e r ( )S t r i n g g e t I n t e r f a c e D e s c r i p t o r ( )l o n g A d d ( l o n g a , l o n g b ) I M a t h S e r v i c e . S t u b . P r o x y 本地服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 1 package 。 2 public interface IMathService extends { 3 /** Localside IPC implementation stub class. */ 4 public static abstract class Stub extends implements { 5 private static final DESCRIPTOR = 。 6 /** Construct the stub at attach it to the interface. */ 7 public Stub(){ 8 (this, DESCRIPTOR)。 9 } 10 /** 11 * Cast an IBinder object into an IMathService interface, 本地服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 12 * generating a proxy if needed. 13 */ 14 public static asInterface( obj){ 15 if ((obj==null)) { 16 return null。 17 } 18 iin = () (DESCRIPTOR)。 19 if (((iin!=null)(iin instanceof ))) { 20 return (()iin)。 21 } 本地服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 22 return new (obj)。 23 } 24 public asBinder(){ 25 return this。 26 } 27 public boolean onTransact(int code, data, reply, int flags) throws { 28 switch (code) { 29 case INTERFACE_TRANSACTION: 30 { 31 (DESCRIPTOR)。 32 return true。 本地服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 33 } 34 case TRANSACTION_Add: 35 { 36 (DESCRIPTOR)。 37 long _arg0。 38 _arg0 = ()。 39 long _arg1。 40 _arg1 = ()。 41 long _result = (_arg0, _arg1)。 42 ()。 43 (_result)。 44 return true。 本地服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 45 } 46 } 47 return (code, data, reply, flags)。 48 } 49 private static class Proxy implements { 50 private mRemote。 51 Proxy( remote){ 52 mRemote = remote。 53 } 54 public asBinder(){ 55 return mRemote。 56 } 本地服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 57 public getInterfaceDescriptor(){ 58 return DESCRIPTOR。 59 } 60 public long Add(long a, long b) throws { 61 _data = ()。 62 _reply = ()。 63 long _result。 64 try { 65 (DESCRIPTOR)。 66 (a)。 67 (b)。 68 (, _data, _reply, 0)。 本地服務(wù) ? 服務(wù)創(chuàng)建與調(diào)用 ? 69 ()。 70 _result = ()。 71 } 72 finally { 73