Android通过Service调用远程接口—AIDL-进程间通信

在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文件

package com.android.aidl;   //BookInfo接口  interface BookInfo{            void setName(String name);      void setPrice(int price);      void ssetPublish(String pname);      //显示图书的信息      String display();  }

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

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

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

package com.android.aidl;  import android.os.RemoteException;   public class BookInfoImpl extends BookInfo.Stub {      //声明三个个变量      private int price;      private String name,pname;      //显示书名,价格,出版社      public String display() throws RemoteException{          return "书名:"+name+";价格:"+price+";出版社:"+price;      }      @Override     //设置书名      public void setName(String name) throws RemoteException {          // TODO Auto          this.name= name;      }       @Override     //设置价格      public void setPrice(int price) throws RemoteException {          // TODO Auto-generated method stub          this.price = price;      }      @Override     //设置出版社      public void setPublish(String pname) throws RemoteException {          // TODO Auto          this.pname= pname;      }     }

三.向客户端暴露接口

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

package com.android.aidl;   import com.android.aidl.BookInfo.Stub;  import android.app.Service;  import android.content.Intent;  import android.os.IBinder;   public class RemoteService extends Service {      //声明BookInfo接口      private Stub bookifo = new BookInfoImpl();      public IBinder onBind(Intent intent){          return bookifo;      }  }

四.在客户端调用

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

package com.android.aidl;   import android.app.Activity;  import android.app.Service;  import android.content.ComponentName;  import android.content.Intent;  import android.content.ServiceConnection;  import android.os.Bundle;  import android.os.IBinder;  import android.os.RemoteException;  import android.view.View;  import android.view.View.OnClickListener;  import android.widget.Button;  import android.widget.Toast;   public class MainActivity extends Activity {      // 声明IPerson接口      private BookInfo bookInfo;      // 声明 Button      private Button btn;      // 实例化ServiceConnection      private ServiceConnection conn = new ServiceConnection() {          @Override         synchronized public void onServiceConnected(ComponentName name, IBinder service) {              // 获得IPerson接口              bookInfo = BookInfo.Stub.asInterface(service);              if (bookInfo != null)                  try {                      // RPC 方法调用                      bookInfo.setName("Google Android SDK开发范例大全");                      bookInfo.setPrice(55);                      bookInfo.setPublish("人民邮电出版社");                      String msg = bookInfo.display();                      // 显示方法调用返回值                      Toast.makeText(MainActivity.this, msg, Toast.LENGTH_LONG)                              .show();                  } catch (RemoteException e) {                      e.printStackTrace();                  }          }           @Override         public void onServiceDisconnected(ComponentName name) {           }      };       @Override     public void onCreate(Bundle savedInstanceState) {          super.onCreate(savedInstanceState);          // 设置当前视图布局          setContentView(R.layout.main);          // 实例化Button          btn = (Button) findViewById(R.id.Button1);          //为Button添加单击事件监听器          btn.setOnClickListener(new OnClickListener() {              @Override             public void onClick(View v) {                  // 实例化Intent                  Intent intent = new Intent();                  // 设置Intent Action 属性                  intent.setAction("com.android.aidl.action.MY_REMOTE_SERVICE");                  // 绑定服务                  bindService(intent, conn, Service.BIND_AUTO_CREATE);              }          });      }  }

五.main.xml和AndroidManifest.xml文件

main.xml

<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"     android:orientation="vertical"     android:layout_width="fill_parent"     android:layout_height="fill_parent"     >     <Button           android:text="远程调用Service"           android:id="@+id/Button1"           android:layout_width="wrap_content"           android:layout_height="wrap_content"         /> </LinearLayout>

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

<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"       package="com.android.aidl"       android:versionCode="1"       android:versionName="1.0">     <uses-sdk android:minSdkVersion="10" />      <application android:icon="@drawable/icon" android:label="@string/app_name">         <activity android:name=".MainActivity"                   android:label="@string/app_name">             <intent-filter>                 <action android:name="android.intent.action.MAIN" />                 <category android:name="android.intent.category.LAUNCHER" />             </intent-filter>         </activity>      <service android:name="RemoteService">             <intent-filter>                 <action android:name="com.android.aidl.action.MY_REMOTE_SERVICE"/>             </intent-filter>     </service>     </application> </manifest>

效果图:

时间: 2024-10-13 00:21:42

Android通过Service调用远程接口—AIDL-进程间通信的相关文章

android 中activity调用远程service中的方法之 aidl的使用

服务端:只有服务,没有界面 1.编写interface文件,复制到 .aidl 文件中,并去掉其中的public 等修饰符.系统会自动在gen目录下生成对应的java文件  (对应本地调用中的接口文件) 2.编写service,其中内部类的自定义bind 只需要继承Stub即可.(本地调用则需要继承Bind 并实现 interface接口) 1 public class PayService extends Service { 2 3 @Override 4 public IBinder onB

(Java) 模拟http请求调用远程接口

package com.vcgeek.hephaestus.utils; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.io.PrintWriter; import java.util.HashMap; import java.util.List; import java.util.Map; /** * 功能描述 * * @autho

Android系统进程间通信(IPC)机制Binder中的Client获得Server远程接口过程源代码分析

文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/6633311 在上一篇文章中,我 们分析了Android系统进程间通信机制Binder中的Server在启动过程使用Service Manager的addService接口把自己添加到Service Manager守护过程中接受管理.在这一篇文章中,我们将深入到Binder驱动程序源代码去分析Client是如何通过Service Manager的

解读Android之Service(3)AIDL

本文翻译自android官方文档,结合自己测试,整理如下. Android Interface Definition Language(AIDL)能够让我们定义自己的编程接口,该接口可以使得客户端和service之间进行跨进程通信(interprocess communication,IPC).通常,在android中无法直接跨进程通信.因此,需要把传递的对象分解成系统可以识别的原始状态(数据),并将它们跨进程序列化marshalling.由于marshalling过程繁琐,因此android通

springBoot使用feign实现远程接口调用和错误熔断

1.第一步,新建两个简单的springboot项目并创建rest接口 demo系统的rest接口 plus系统的调用接口 2.在项目pom文件里导入feign和hystrix的pom依赖包 <properties> <java.version>1.8</java.version> <spring-cloud.version>Greenwich.SR1</spring-cloud.version> </properties> <!

Android服务之Service(三)关于AIDL进程间通信

转载:http://www.cnblogs.com/zhangdongzi/archive/2012/01/09/2317197.html 一.基础知识 AIDL的作用 在Android平台,每个应用程序App都运行在自己的进程空间.通常一 个进程不能访问另一个进程的内存空间(一个应用不能访问另一个应用),如果想沟通,需要将对象分解成操作系统可以理解的基本单元,Android提供了AIDL来处理. AIDL (Android Interface Definition Language) 是一种I

Android深入源码分析理解Aidl整体调用流程(雷惊风)

2017年开始上班的第一天,老不想工作了,假期感觉还没开始就已经结束了,唉,时间就是这样,新的一年开始了,虽然很不想干正事,没办法,必须干起来,因为后边的路还很长,距离六十岁还很远.刚上班也没什么事,复习一下之前的东西,看了一下Aidl相关的知识,仔细瞅了瞅Aidl的调用流程,这里写篇文章整理一下,帮助大家的同时,自己也加深一下印象.对Aidl不太了解的童鞋可以先看一下我之前的一篇文章, 链接如下:http://blog.csdn.net/liuyonglei1314/article/detai

android应用程序如何调用支付宝接口

最近在做一个关于购物商城的项目,项目里面付款这块我选的是调用支付宝的接口,因为用的人比较多. 在网上搜索了以下,有很多这方面的教程,但大部分教程过于陈旧,而且描述的过于简单.而且支付宝提供的接口一直在更新,可能支付宝那边是为了让接口更容易被调用吧,以前有些老的教程稍微跟现在接口有些不能“对号入座”,于是,我决定抽空写一篇关于调用支付宝接口的文章,跟大家分享,让大家以最快的速度掌握如何调用支付宝接口的方法.如果写的不好,请大家多多指教哦. 不多说了,开写. 1,到支付宝官网,下载支付宝集成开发包,

Android调用webservice 接口

以查询手机号码归属地的Web service为例,它的wsdl为 http://webservice.webxml.com.cn/WebServices/MobileCodeWS.asmx?wsdl 1 在Android项目中导入??Ksoap2-android jar第三方jar包?? 2 Activity代码 public class SecondActivity extends Activity { private EditText phoneSecEditText;       priv