绑定服务调用远程服务中的方法

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

相关文章
相关标签/搜索