热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

Android开发之Service的远程调用

在Andorid平台中,各个组件运行在自己的进程中,他们之间是不能相互访问的,但是在程序之间是不可避免的要传递一些对象,在进

   在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接口。

下面是实现Activity访问Service例子的步骤:

一.创建.aidl文件

    AIDL使用简单的语法来声明接口,描述其方法以及方法的参数和返回值。这些参数和返回值可以是任何类型,甚至是其他AIDL生成的接口。重要的是必须导入导入除了内建类型(例如:int,boolean等)外的任何其他类型,哪怕是这些类型是在与接口相同的包中。具体的要求如下:

  • JAVA基本数据类型不需要导入
  • String,List,MapCharSequence不需要导入

使用Eclipse的ADT插件创建一个BookInfo.aidl文件,该文件有4个方法:

setName(String name)设置图书的书名,setPrice(int price)设置图书的价格,setPublish(String pname)设置图书的出版社和String display()显示图书的信息.

BookInfo.aidl文件

  1. package com.android.aidl;  
  2.  
  3. //BookInfo接口  
  4. interface BookInfo{  
  5.       
  6.     void setName(String name);  
  7.     void setPrice(int price);  
  8.     void ssetPublish(String pname);  
  9.     //显示图书的信息  
  10.     String display();  

创建好BookInfo.aidl文件,系统会自动在gen目录下生成Java接口文件BookInfo.java

二.实现AIDL文件生成的JAVA接口

    AIDL会生成一个和.aidl文件同名的JAVA接口文件,该接口中有一个静态抽象内部类Stub,该类中声明了AIDL文件中定义的所有方法,其中有一个重要的方法是asInterface(),该方法通过代理模式返回JAVA接口的实现我们可以定义一个实现类,BookImpl,该类继承Stub类,实现我们定义的4个方法

  1. package com.android.aidl;  
  2. import android.os.RemoteException;  
  3.  
  4. public class BookInfoImpl extends BookInfo.Stub {  
  5.     //声明三个个变量  
  6.     private int price;  
  7.     private String name,pname;  
  8.     //显示书名,价格,出版社  
  9.     public String display() throws RemoteException{  
  10.         return "书名:"+name+";价格:"+price+";出版社:"+price;  
  11.     }  
  12.     @Override 
  13.     //设置书名  
  14.     public void setName(String name) throws RemoteException {  
  15.         // TODO Auto  
  16.         this.name= name;  
  17.     }  
  18.  
  19.     @Override 
  20.     //设置价格  
  21.     public void setPrice(int price) throws RemoteException {  
  22.         // TODO Auto-generated method stub  
  23.         this.price = price;  
  24.     }  
  25.     @Override 
  26.     //设置出版社  
  27.     public void setPublish(String pname) throws RemoteException {  
  28.         // TODO Auto  
  29.         this.pname= pname;  
  30.     }     
  31. }  

三.向客户端暴露接口

现在已经实现了BookInfo接口,接下来要将该接口暴露给客户端调用。一般通过定义一个Service来实现,在Service的onBind()方法中返回该接口,当我们绑定该接口时调用该方法。

  1. package com.android.aidl;  
  2.  
  3. import com.android.aidl.BookInfo.Stub;  
  4. import android.app.Service;  
  5. import android.content.Intent;  
  6. import android.os.IBinder;  
  7.  
  8. public class RemoteService extends Service {  
  9.     //声明BookInfo接口  
  10.     private Stub bookifo = new BookInfoImpl();  
  11.     public IBinder onBind(Intent intent){  
  12.         return bookifo;  
  13.     }  

四.在客户端调用

定义一个Activity来绑定远程Service,获得BookInfo接口,通过RPC机制调用接口中的方法。

  1. package com.android.aidl;  
  2.  
  3. import android.app.Activity;  
  4. import android.app.Service;  
  5. import android.content.ComponentName;  
  6. import android.content.Intent;  
  7. import android.content.ServiceConnection;  
  8. import android.os.Bundle;  
  9. import android.os.IBinder;  
  10. import android.os.RemoteException;  
  11. import android.view.View;  
  12. import android.view.View.OnClickListener;  
  13. import android.widget.Button;  
  14. import android.widget.Toast;  
  15.  
  16. public class MainActivity extends Activity {  
  17.     // 声明IPerson接口  
  18.     private BookInfo bookInfo;  
  19.     // 声明 Button  
  20.     private Button btn;  
  21.     // 实例化ServiceConnection  
  22.     private ServiceConnection conn = new ServiceConnection() {  
  23.         @Override 
  24.         synchronized public void onServiceConnected(ComponentName name, IBinder service) {  
  25.             // 获得IPerson接口  
  26.             bookInfo = BookInfo.Stub.asInterface(service);  
  27.             if (bookInfo != null)  
  28.                 try {  
  29.                     // RPC 方法调用  
  30.                     bookInfo.setName("Google Android SDK开发范例大全");  
  31.                     bookInfo.setPrice(55);  
  32.                     bookInfo.setPublish("人民邮电出版社");  
  33.                     String msg = bookInfo.display();  
  34.                     // 显示方法调用返回值  
  35.                     Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG)  
  36.                             .show();  
  37.                 } catch (RemoteException e) {  
  38.                     e.printStackTrace();  
  39.                 }  
  40.         }  
  41.  
  42.         @Override 
  43.         public void onServiceDisconnected(ComponentName name) {  
  44.  
  45.         }  
  46.     };  
  47.  
  48.     @Override 
  49.     public void onCreate(Bundle savedInstanceState) {  
  50.         super.onCreate(savedInstanceState);  
  51.         // 设置当前视图布局  
  52.         setContentView(R.layout.main);  
  53.         // 实例化Button  
  54.         btn = (Button) findViewById(R.id.Button1);  
  55.         //为Button添加单击事件监听器  
  56.         btn.setOnClickListener(new OnClickListener() {  
  57.             @Override 
  58.             public void onClick(View v) {  
  59.                 // 实例化Intent  
  60.                 Intent intent = new Intent();  
  61.                 // 设置Intent Action 属性  
  62.                 intent.setAction("com.android.aidl.action.MY_REMOTE_SERVICE");  
  63.                 // 绑定服务  
  64.                 bindService(intent, conn, Service.BIND_AUTO_CREATE);  
  65.             }  
  66.         });  
  67.     }  

五.main.xml和AndroidManifest.xml文件

main.xml

  1. xml version="1.0" encoding="utf-8"?> 
  2. <LinearLayout xmlns:android&#61;"http://schemas.android.com/apk/res/android" 
  3.     android:orientation&#61;"vertical" 
  4.     android:layout_width&#61;"fill_parent" 
  5.     android:layout_height&#61;"fill_parent" 
  6.     > 
  7.     <Button   
  8.         android:text&#61;"远程调用Service"   
  9.         android:id&#61;"&#64;&#43;id/Button1"   
  10.         android:layout_width&#61;"wrap_content"   
  11.         android:layout_height&#61;"wrap_content" 
  12.         /> 
  13. LinearLayout> 

在AndroidManifest.xml文件16~20声明Service

  1. xml version&#61;"1.0" encoding&#61;"utf-8"?> 
  2. <manifest xmlns:android&#61;"http://schemas.android.com/apk/res/android" 
  3.       package&#61;"com.android.aidl" 
  4.       android:versionCode&#61;"1" 
  5.       android:versionName&#61;"1.0"> 
  6.     <uses-sdk android:minSdkVersion&#61;"10" /> 
  7.  
  8.     <application android:icon&#61;"&#64;drawable/icon" android:label&#61;"&#64;string/app_name"> 
  9.         <activity android:name&#61;".MainActivity" 
  10.                   android:label&#61;"&#64;string/app_name"> 
  11.             <intent-filter> 
  12.                 <action android:name&#61;"android.intent.action.MAIN" /> 
  13.                 <category android:name&#61;"android.intent.category.LAUNCHER" /> 
  14.             intent-filter> 
  15.         activity> 
  16.      <service android:name&#61;"RemoteService"> 
  17.             <intent-filter> 
  18.                 <action android:name&#61;"com.android.aidl.action.MY_REMOTE_SERVICE"/> 
  19.             intent-filter> 
  20.     service> 
  21.     application> 
  22. manifest> 

效果图&#xff1a;



推荐阅读
  • Mac OS 升级到11.2.2 Eclipse打不开了,报错Failed to create the Java Virtual Machine
    本文介绍了在Mac OS升级到11.2.2版本后,使用Eclipse打开时出现报错Failed to create the Java Virtual Machine的问题,并提供了解决方法。 ... [详细]
  • 使用eclipse创建一个Java项目的步骤
    本文介绍了使用eclipse创建一个Java项目的步骤,包括启动eclipse、选择New Project命令、在对话框中输入项目名称等。同时还介绍了Java Settings对话框中的一些选项,以及如何修改Java程序的输出目录。 ... [详细]
  • Nginx使用(server参数配置)
    本文介绍了Nginx的使用,重点讲解了server参数配置,包括端口号、主机名、根目录等内容。同时,还介绍了Nginx的反向代理功能。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • XML介绍与使用的概述及标签规则
    本文介绍了XML的基本概念和用途,包括XML的可扩展性和标签的自定义特性。同时还详细解释了XML标签的规则,包括标签的尖括号和合法标识符的组成,标签必须成对出现的原则以及特殊标签的使用方法。通过本文的阅读,读者可以对XML的基本知识有一个全面的了解。 ... [详细]
  • Android源码深入理解JNI技术的概述和应用
    本文介绍了Android源码中的JNI技术,包括概述和应用。JNI是Java Native Interface的缩写,是一种技术,可以实现Java程序调用Native语言写的函数,以及Native程序调用Java层的函数。在Android平台上,JNI充当了连接Java世界和Native世界的桥梁。本文通过分析Android源码中的相关文件和位置,深入探讨了JNI技术在Android开发中的重要性和应用场景。 ... [详细]
  • Java程序设计第4周学习总结及注释应用的开发笔记
    本文由编程笔记#小编为大家整理,主要介绍了201521123087《Java程序设计》第4周学习总结相关的知识,包括注释的应用和使用类的注释与方法的注释进行注释的方法,并在Eclipse中查看。摘要内容大约为150字,提供了一定的参考价值。 ... [详细]
  • Android系统源码分析Zygote和SystemServer启动过程详解
    本文详细解析了Android系统源码中Zygote和SystemServer的启动过程。首先介绍了系统framework层启动的内容,帮助理解四大组件的启动和管理过程。接着介绍了AMS、PMS等系统服务的作用和调用方式。然后详细分析了Zygote的启动过程,解释了Zygote在Android启动过程中的决定作用。最后通过时序图展示了整个过程。 ... [详细]
  • Week04面向对象设计与继承学习总结及作业要求
    本文总结了Week04面向对象设计与继承的重要知识点,包括对象、类、封装性、静态属性、静态方法、重载、继承和多态等。同时,还介绍了私有构造函数在类外部无法被调用、static不能访问非静态属性以及该类实例可以共享类里的static属性等内容。此外,还提到了作业要求,包括讲述一个在网上商城购物或在班级博客进行学习的故事,并使用Markdown的加粗标记和语句块标记标注关键名词和动词。最后,还提到了参考资料中关于UML类图如何绘制的范例。 ... [详细]
  • 本文介绍了一款名为TimeSelector的Android日期时间选择器,采用了Material Design风格,可以在Android Studio中通过gradle添加依赖来使用,也可以在Eclipse中下载源码使用。文章详细介绍了TimeSelector的构造方法和参数说明,以及如何使用回调函数来处理选取时间后的操作。同时还提供了示例代码和可选的起始时间和结束时间设置。 ... [详细]
  • 本文介绍了MVP架构模式及其在国庆技术博客中的应用。MVP架构模式是一种演变自MVC架构的新模式,其中View和Model之间的通信通过Presenter进行。相比MVC架构,MVP架构将交互逻辑放在Presenter内部,而View直接从Model中读取数据而不是通过Controller。本文还探讨了MVP架构在国庆技术博客中的具体应用。 ... [详细]
  • Hibernate延迟加载深入分析-集合属性的延迟加载策略
    本文深入分析了Hibernate延迟加载的机制,特别是集合属性的延迟加载策略。通过延迟加载,可以降低系统的内存开销,提高Hibernate的运行性能。对于集合属性,推荐使用延迟加载策略,即在系统需要使用集合属性时才从数据库装载关联的数据,避免一次加载所有集合属性导致性能下降。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • Go GUIlxn/walk 学习3.菜单栏和工具栏的具体实现
    本文介绍了使用Go语言的GUI库lxn/walk实现菜单栏和工具栏的具体方法,包括消息窗口的产生、文件放置动作响应和提示框的应用。部分代码来自上一篇博客和lxn/walk官方示例。文章提供了学习GUI开发的实际案例和代码示例。 ... [详细]
  • 如何实现JDK版本的切换功能,解决开发环境冲突问题
    本文介绍了在开发过程中遇到JDK版本冲突的情况,以及如何通过修改环境变量实现JDK版本的切换功能,解决开发环境冲突的问题。通过合理的切换环境,可以更好地进行项目开发。同时,提醒读者注意不仅限于1.7和1.8版本的转换,还要适应不同项目和个人开发习惯的需求。 ... [详细]
author-avatar
魍魉之波_414
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有