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

  在Andorid平台中,各个组件运行在自己的进程中,他们之间是不能相互访问的,但是在程序之间是不可避免的要传递一些对象,在进程之间相互通信。为了实现进程之间的相互通信,Andorid采用了一种轻量级的实现方式RPC(Remote Procedure Call 远程进程调用)来完成进程之间的通信,并且Android通过接口定义语言(Andorid Interface Definition Language ,AIDL)来生成两个进程之间相互访问的代码,例如,你在Activity里的代码需要访问Service中的一个方法,那么就可以通过这种方式来实现了。

  AIDL是Android的一种接口描述语言; 编译器可以通过aidl文件生成一段代码,通过预先定义的接口达到两个进程内部通信进程的目的. 如果需要在一个Activity中, 访问另一个Service中的某个对象, 需要先将对象转化成 AIDL可识别的参数(可能是多个参数), 然后使用AIDL来传递这些参数, 在消息的接收端, 使用这些参数组装成自己需要的对象。

  AIDL RPC机制是通过接口来实现的,类似Windows中的COM或者Corba,但他是轻量级的,客户端和被调用实现之间是通过代理模式实现的,代理类和被代理类实现同一个接口Ibinder接口。

  远程绑定调用service主要是用来不同进程的信息共享。就比如服务器和客户端,在服务器端设置好一个service提供方法或信息,然后客户端可以直接调用服务器端service提供方法或信息。这里有个前提是客户端必须有和服务器端一份一样的AIDL.

这这里笔者使用的demo,是在上一篇博客<绑定服务调用本地服务中的方法>基础上修改的, 想查看上一篇博客可点击链接: http://www.cnblogs.com/wanghaoyuhappy/p/5293696.html

1. 先来看一下远程服务中的目录结构:

以及另一个应用的目录结构

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方法,为什么呢?

因为在自动生成的IService.aidl文件中, Stub方法已经继承了IBinder对象并实现了接口.

3. 下面是IService.aidl的代码:

1 package com.example.remoteservice;
2
3 interface IService {
4     void callMethodInService(String name, int money);
5 }

注意: 在普通的接口中, 需要定义访问修饰符为public, 而在aidl文件中不可以定义访问修饰符

新建了一个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,搞定了!!!

时间: 2024-10-25 05:52:13

绑定服务调用远程服务中的方法的相关文章

本地应用调用远程服务中的方法

*  AIDL:安卓接口定义语言 ,来公开服务的接口的方式来暴露服务接口* IPC:进程间通讯 intel-process communication* AIDL编写步骤: 远程工程 1. 把IRemoteService.java接口改成.aidl的接口 2. 去掉.aidl接口文件的权限修饰符public 3. 让远程服务里的内部类继承Stub package com.example.alipay; import android.app.Service; import android.cont

Android(java)学习笔记228:服务(service)之绑定服务调用服务里面的方法

1.绑定服务调用服务里面的方法,图解: 步骤: (1)在Activity代码里面绑定 bindService(),以bind的方式开启服务 :                     bindService(intent, new MyConn(), BIND_AUTO_CREATE): 参数intent:意图对象,服务对应的意图对象  new  Intent(this,Service.class) 参数ServiceConnection (接口,自定义其接口实现内部类MyConn() ):通讯

vs自动生成的WebService配置文件在部署到IIs6后,服务调用失败的解决方法

近日,在项目中需要引用java发布的WebService,添加服务引用后,调用一切正常. 配置如下: <system.serviceModel> <bindings> <basicHttpBinding> <binding name="SecurityServiceImplServiceSoapBinding" maxBufferPoolSize="2147483647" maxReceivedMessageSize=&qu

Unity SLua 如何调用Unity中C#方法

1.原理 就是通常在Lua框架中所说的,开放一个C#的web接口,或者叫做在Slua框架中注册函数. 2.作用 在Lua中调用C#中的方法,这个是在做热更新中很常用的一种方法,无论是slua,还是lua,都差不多.这里,我拿slua举例. 3.实际运用 举例:如何在Slua中打印Log 原理:其实是slua通过调用C#中的Debug.Log方法实现的打印,并不是说是lua中的打印方法起到作用. 步骤: 首先,既然是Lua调用C#中的方法,这里自定义写一个打印log的方法. 1 2 3 4 5 6

webview中js调用Android中的方法

package com.example.helloworld; import android.os.Bundle; import android.app.Activity; import android.content.Intent; import android.view.Menu; import android.webkit.WebView; public class MainActivity extends Activity { private WebView webView = null

使用Java的反射功能调用类中的方法

最近一直在搞Java的反射,今天使用反射调用方法时出现了很多问题,主要是没有详细参考官方API.所以走了很多弯路. 所以想把这个例子记下来,供自己也供他人学习. package com.mine.practice.reflect; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; /** * 使用反射调用类中的方法 * @author 2014-11-5 上午10:51:28

在Android Studio中调用so中的方法

本节用的so是上节用Android Studio创建的so.想在Android Studio中调用so中的方法,需要先引用so.Android Studio中引用so的方法有二种,下面开始介绍. 一 引用so  在app/src/main目录下新建Directory,命名文件夹为jniLIB(文件名不能错),把so文件放进去 ,如图: 二 编写java代码调用so中方法 ①在代码中引用so 创建myJNI.java文件,用System.loadLibrary加载so,同时声明so中的HelloW

绑定服务调用本地服务中的方法

如果想调用服务中的方法, 通过startService()是做不到的, 这时需要用bindService来解决. 下面的demo是在Activity中调用Service中的自定义方法---methodInService 这个demo可以解决在项目开发中调用service里的数据. 这里在service中使用到了代理模式.这是为了,给service组件和activity组件中间添加一个中间人. 通过代理来传递数据.也就是binder对象.这个代理就是接口IService Service中的代码如下

android之绑定服务调用服务的方法

public class MainActivity extends Activity { private music.MyBinder mm;//在activity里面得到服务ibinder对象的引用 @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } public v