綁定服務調用遠程服務中的方法

   在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服務器

 

1. 先來看一下遠程服務中的目錄結構:

 

以及另外一個應用的目錄結構app

 

 

2. 下面是遠程服務中的Service代碼:

 

 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,搞定了!!!

相關文章
相關標籤/搜索