在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,Map和CharSequence不需要导入

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

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

BookInfo.aidl文件

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

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

三.向客户端暴露接口

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

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

四.在客户端调用

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

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

五.main.xml和AndroidManifest.xml文件

main.xml

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

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

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

效果图:

Android开发之Service的远程调用的更多相关文章

  1. android开发之service详解

    service作为android的四大组件之一,其重要性可想而知,在开发中,我们经常把一些不需要与用户进行交互的工作放在service中来完成,service运行在后台,这样有些人可能会产生错觉,以为 ...

  2. Android开发之Service的写法以及与Activity的通信

    Service的总结: 1.按运行地点分类: 类别 区别  优点 缺点   应用 本地服务(Local) 该服务依附在主进程上,  服务依附在主进程上而不是独立的进程,这样在一定程度上节约了资源,另外 ...

  3. Android开发之Service

    什么是Service? Android中的服务与Activity不同,他是不能与用户进行交互,自己也不能启动在后台运行的程序,当我们退出应用时,Service应用并没有结束,它仍然在后台运行. 例子: ...

  4. Android开发之bindService()侦听service内部状态

    在Android开发之bindService()通信的基础上,实现bindService()方法侦听service内部状态. 实现侦听service内部状态,使用的是回调机制 1.首先实现一个接口 p ...

  5. Android开发之旅: Intents和Intent Filters(理论部分)

    引言 大部分移动设备平台上的应用程序都运行在他们自己的沙盒中.他们彼此之间互相隔离,并且严格限制应用程序与硬件和原始组件之间的交互. 我们知道交流是多么的重要,作为一个孤岛没有交流的东西,一定毫无意义 ...

  6. Android开发之Java必备基础

    Android开发之Java必备基础 Java类型系统 Java语言基础数据类型有两种:对象和基本类型(Primitives).Java通过强制使用静态类型来确保类型安全,要求每个变量在使用之前必须先 ...

  7. [置顶] Android开发之MediaPlayerService服务详解(一)

    前面一节我们分析了Binder通信相关的两个重要类:ProcessState 和 IPCThreadState.ProcessState负责打开Binder 驱动,每个进程只有一个.而 IPCThre ...

  8. [置顶] Android开发之serviceManager分析

    Android 开发之serviceManager分析 在Android系统中用到最多的通信机制就是Binder,Binder主要由Client.Server.ServiceManager和Binde ...

  9. Android开发之TextView高级应用

    Android开发之TextView高级应用 我们平时使用TextView往往让它作为一个显示文字的容器,但TextView的功能并不局限于此.以下就和大家分享一下TextView的一些使用技巧. A ...

随机推荐

  1. QT QCharts QScatterSeries 空心点阵图,鼠标移动到上面显示数值,鼠标移开数值消失

    在最近接到的需求是这样的,画一个折线图,关键点使用空心的圆点标识出来,鼠标移动到关键点上,显示出当前数值:鼠标移走数值消失. 我们遇到这个需求的时候,第一时间就会想到使用 QLineSeries 画折 ...

  2. iOS开发-多线程简介

    多线程从概念上理解是指从软件或者硬件上实现多个线程并发执行的技术,简单点理解就是同一时间可以执行多个事情(比如说一边听歌一边码代码),听歌是一个线程,码代码是一个线程,如果是单核CPU的话,上面两个动 ...

  3. Android中远程Service浅析

    上一篇文章中简单的写了一下关于Android中Service的两种启动方式,不过都是本地的服务,今天就简单的写下关于Android中远程Service的使用,学习之前先了解两个概念,AIDL( And ...

  4. SVN jsvnadmin 安装与基本使用

    1. jsvnadmin  介绍 https://code.google.com/p/jsvnadmin/ Svn Admin是一个Java开发的管理Svn服务器的项目用户的web应用.安装好Svn服 ...

  5. C#中图片切割,图片压缩,缩略图生成的代码

    **//// <summary> /// 图片切割函数 /// </summary> /// <param name="sourceFile"> ...

  6. 黑马day12 DbUtils的介绍

    简单介绍: DbUtils为不喜欢hibernate框架的钟爱.它是线程安全的,不存在并发问题. 使用步骤: 1. QueryRunner runner=new QueryRunner(这里写数据源. ...

  7. ListView GridViewColumn.CellTemplate

    <ListView.View> <GridView> <GridViewColumn Header="Meaningful Use Objectives&quo ...

  8. Oracle服务启动顺序导致ORA-12514

    在window 上装了oracle11g,按照常规步骤安装完成后一切OK,如下图所示 C:\Users\Administrator>sqlplus /nolog SQL*Plus: Releas ...

  9. Foreda8上安装CMake2.8.1.2

    本机操作系统:Linux 2.6.23.1-42.fc8 #1 SMP Tue Oct 30 13:55:12 EDT 2007 i686 i686 i386 GNU/Linux 在本机上准备安装My ...

  10. utc时间转换成标准时间

    把这个时间 /Date(1484884647943+0800)/ 转成标准时间 String str = String.format("%tF %<tT", 14848846 ...