zoukankan      html  css  js  c++  java
  • 绑定服务调用远程服务中的方法

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

  • 相关阅读:
    Java实现哥德巴赫猜想
    Java实现哥德巴赫猜想
    Java实现哥德巴赫猜想
    Java实现哥德巴赫猜想
    Java实现哥德巴赫猜想
    Java实现 洛谷 P1487 陶陶摘苹果(升级版)
    Java实现 洛谷 P1487 陶陶摘苹果(升级版)
    Java实现 洛谷 P1487 陶陶摘苹果(升级版)
    Spring异步任务处理,@Async的配置和使用
    Spring Boot系列二 Spring @Async异步线程池用法总结
  • 原文地址:https://www.cnblogs.com/wanghaoyuhappy/p/5293999.html
Copyright © 2011-2022 走看看