在Andorid平臺中,各個組件運行在本身的進程中,他們之間是不能相互訪問的,可是在程序之間是不可避免的要傳遞一些對象,在進程之間相互通訊。爲了實現進程之間的相互通訊,Andorid採用了一種輕量級的實現方式RPC(Remote Procedure Call 遠程進程調用)來完成進程之間的通訊,而且Android經過接口定義語言(Andorid Interface Definition Language ,AIDL)來生成兩個進程之間相互訪問的代碼,例如,你在Activity裏的代碼須要訪問Service中的一個方法,那麼就能夠經過這種方式來實現了。html
AIDL是Android的一種接口描述語言; 編譯器能夠經過aidl文件生成一段代碼,經過預先定義的接口達到兩個進程內部通訊進程的目的. 若是須要在一個Activity中, 訪問另外一個Service中的某個對象, 須要先將對象轉化成 AIDL可識別的參數(多是多個參數), 而後使用AIDL來傳遞這些參數, 在消息的接收端, 使用這些參數組裝成本身須要的對象。java
AIDL RPC機制是經過接口來實現的,相似Windows中的COM或者Corba,但他是輕量級的,客戶端和被調用實現之間是經過代理模式實現的,代理類和被代理類實現同一個接口Ibinder接口。android
遠程綁定調用service主要是用來不一樣進程的信息共享。就好比服務器和客戶端,在服務器端設置好一個service提供方法或信息,而後客戶端能夠直接調用服務器端service提供方法或信息。這裏有個前提是客戶端必須有和服務器端一份同樣的AIDL.數組
這這裏筆者使用的demo,是在上一篇博客<綁定服務調用本地服務中的方法>基礎上修改的, 想查看上一篇博客可點擊連接: http://www.cnblogs.com/wanghaoyuhappy/p/5293696.html服務器
以及另外一個應用的目錄結構app
1 public class ALiPayService extends Service { 2 3 //建立內部人員,繼承aidl 4 private class MyBinder extends IService.Stub { 5 public void callMethodInService(String name,int money){ 6 7 serviceInMethod(name,money); 8 } 9 } 10 11 //在綁定服務時調用該方法, 12 //返回了IBinder對象 13 @Override 14 public IBinder onBind(Intent arg0) { 15 return new MyBinder(); 16 } 17 18 @Override 19 public void onCreate() { 20 System.out.println("服務已開啓"); 21 super.onCreate(); 22 } 23 24 @Override 25 public void onDestroy() { 26 System.out.println("服務已銷燬"); 27 super.onDestroy(); 28 } 29 30 //服務中的方法 31 public void serviceInMethod(String name,int money){ 32 System.out.println(name + "成功存入"+ money); 33 } 34 35 }
與調用本地服務不一樣的是: 在Service中建立內部類的時候須要繼承IService.aidl中的Stub方法,爲何呢?ide
由於在自動生成的IService.aidl文件中, Stub方法已經繼承了IBinder對象並實現了接口.post
3. 下面是IService.aidl的代碼:spa
1 package com.example.remoteservice; 2 3 interface IService { 4 void callMethodInService(String name, int money); 5 }
注意: 在普通的接口中, 須要定義訪問修飾符爲public, 而在aidl文件中不能夠定義訪問修飾符3d
新建了一個aidl文件後, Eclipse會在gen目錄下自動建立一個IService.java文件, 詳細看上面的目錄結構
4. 下面是另外一個應用程序, 也就是調用者的示例代碼:
(1) 首先須要將遠程服務中的aidl文件連同所在的包一同複製到本身的工程下
保證本身工程下的aidl文件與遠程服務中的aidl文件相同,包括包名
(2) 下面是Activity中的示例代碼:
1 public class MainActivity extends Activity { 2 3 @Override 4 protected void onCreate(Bundle savedInstanceState) { 5 super.onCreate(savedInstanceState); 6 setContentView(R.layout.activity_main); 7 } 8 9 private Myconn conn; 10 private IService iService; 11 12 // 與服務創建鏈接的一個通道 13 private class Myconn implements ServiceConnection { 14 15 @Override 16 public void onServiceConnected(ComponentName name, IBinder service) { 17 // 與遠程服務器創建鏈接 18 iService = IService.Stub.asInterface(service); 19 } 20 21 @Override 22 public void onServiceDisconnected(ComponentName name) { 23 24 } 25 } 26 27 public void start(View view) { 28 // 這個時候須要用隱式意圖了 29 Intent intent = new Intent("com.example.remoteservice"); 30 startService(intent); 31 } 32 33 public void bind(View view) { 34 Intent intent = new Intent("com.example.remoteservice"); 35 conn = new Myconn(); 36 bindService(intent, conn, BIND_AUTO_CREATE); 37 } 38 39 // 調用服務中的方法 40 public void call(View view) { 41 try { 42 iService.callMethodInService("張三", 500); 43 } catch (RemoteException e) { 44 e.printStackTrace(); 45 } 46 } 47 48 public void unbind(View view) { 49 if (conn != null) { 50 // 解綁服務 51 unbindService(conn); 52 // 鏈接的通道置爲空,釋放資源 53 conn = null; 54 } 55 } 56 57 public void stop(View view) { 58 Intent intent = new Intent("com.example.remoteservice"); 59 stopService(intent); 60 } 61 62 //在用戶按返回鍵時,解綁服務,防止內存泄露 63 @Override 64 public void onBackPressed() { 65 super.onBackPressed(); 66 if (conn != null) { 67 // 解綁服務 68 unbindService(conn); 69 // 鏈接的通道置爲空,釋放資源 70 conn = null; 71 } 72 } 73 74 }
關鍵代碼已經用紅色標出, 有兩點須要注意:
1) 在綁定服務的時候須要用隱式意圖了
2) 在鏈接服務的時候使用的是這句代碼: iService = IService.Stub.asInterface(service);
5. 另外下面是Service中清單文件的註冊信息:
1 <service android:name="com.example.remoteservice.ALiPayService"> 2 <intent-filter> 3 <action android:name="com.example.remoteservice"/> 4 </intent-filter> 5 </service>
6. 運行效果如圖:
OK,搞定了!!!