Android:Service之AIDL传递系统基本类型数据

   什么是AIDL?

  先来回顾一下,Android在本地的Service中如何与其它组件进行交互的,首先Service必须实现其onBind()方法,然后在onBind方法传递一个IBinder接口的实现,而在其它组件中使用bindService()绑定一个服务,再通过其中的参数ServiceConnection对象获取到Service中定义的IBinder接口的实现。那么与Service进行数据交互,其实就是传递一个IBinder,通过这个IBinder进行交互。

  而现在就碰到一个问题,在同一个进程中,是可以获取到这个Service类的,也就可以获得这个Service中定义的IBinder,但是如果在不同的应用中,即远程服务,如何获取IBinder呢?仅仅是在不同的应用定义一相同的类是没有用的,所以Android为我们提供了AIDL语言,它需要先定义一个远程调用接口,然后为该接口提供一个实现类,通过共享这个远程调用接口来达到进程间数据交互的目的,而这个接口的代码是有很多共性的,并且编写过程相当枯燥乏味,所以Android开发者为我们提供了ADIL来简化通讯接口的开发。

  AIDL(Android Interface Definition Language)是Android远程调用接口的定义语言。它有它自己的一套语法规范,但是和Java类似,这并不难理解,详细的这个会后面介绍。而当你定义好一个AIDL接口之后,你会发现在gen/目录下,多出一个与定义的AIDL包名相同,文件名相同的一个Java类,这个类是编译器根据定义的AIDL接口自动生成的代码,观察之后发现其实它也是继承了Binder类(Binder是IBinder的实现类),所以它可以通过ServiceConnection进行数据传递。Service只需要暴露这个AIDL接口给客户端,让客户端也定义它,这样两个应用进程就可以通讯了。

  如何定义AIDL?

  AIDL的语法与Java接口的语法非常相似,但是存在一些差异:

  AIDL定义接口的源代码后缀必须以.aidl结尾。

  AIDL一样要指定AIDL接口的包信息package *。

  AIDL接口无需指定public、private、protected等作用域,可以理解为就是public。

  AIDL默认情况下只能传递基本类型、String、List、Map、CharSequence。

  如果需要传递其他类型的对象,需要import对象的包名,并需要对对象进行特殊处理(之后会介绍)。

  例如:

  1 package com.example.aidlservicedemo.domain;

  2

  3 interface IDog{

  4 String getName();

  5 int getAge();

  6 }

  ADIL做了什么?

  当你声明完一个AIDL接口的时候,你会发现在项目的gen/目录下,对应包中存在一个同名的Java文件,这个文件是Android帮我们自动生成的,里面有很多代码,这里只讲一下需要注意的。查看自动生成的这个Java文件代码,会发现它定义了一个名为Stub的静态抽象类,这个Stub继承了Binder,实现了AIDL接口,当然其中也实现了AIDL接口的两个方法,粗略看一下会发现它对数据做了一个序列化和反序列化的操作。正因为AIDL对数据进行了序列化和反序列化,所以才可以在进程间传递。

  使用ADIL传递系统基本数据

  定义好AIDL接口之后,就需要通过服务把接口暴露给客户端,这里Service.onBind()传递的就是这个Stub静态抽象类的实现类,其他没什么特别的。

  下面通过一个Demo来演示ADIL如何传递数据的,在示例中,给出两个应用,分别实现Server与调用客户端,使用的AIDL接口就是上面给出的AIDL示例代码,这里不再重复定义。

  AIDL服务:BaseTypeService.java

  1 package com.example.aidlservicedemo;

  2

  3 import java.util.Random;

  4

  5 import com.example.aidlservicedemo.domain.IDog.Stub;

  6

  7 import android.app.Service;

  8 import android.content.Intent;

  9 import android.os.IBinder;

  10 import android.os.RemoteException;

  11 import android.util.Log;

  12

  13 public class BaseTypeService extends Service {

  14 private final String TAG="main";

  15 private DogBinder binder=null;

  16 private String[] names=new String[]{"小白","旺财","小黑"};

  17 private int[] ages=new int[]{1,2,3};

  18

  19 /**

  20 * Stub的实现类,Stub内部实现了Binder

  21 * 内部实现AIDL定义的方法

  22 */

  23 public class DogBinder extends Stub{

  24

  25 @Override

  26 public String getName() throws RemoteException {

  27 Random random=new Random();

  28 int nextInt = random.nextInt(2);

  29 return names[nextInt];

  30 }

  31

  32 @Override

  33 public int getAge() throws RemoteException {

  34 Random random=new Random();

  35 int nextInt = random.nextInt(2);

  36 return ages[nextInt];

  37 }

  38 }

  39

  40 @Override

  41 public void onCreate() {

  42 super.onCreate();

  43 // 实例化Binder对象

  44 binder=new DogBinder();

  45 Log.i(TAG, "创建服务成功");

  46 }

  47

  48 @Override

  49 public IBinder onBind(Intent intent) {

  50 Log.i(TAG, "绑定服务成功");

  51 // 返回Binder对象

  52 return binder;

  53 }

  54 }

  客户端调用服务获取数据:

  1 package com.example.aidlClientdemo;

  2

  3 import com.example.aidlservicedemo.domain.IDog;

  4 import android.app.Activity;

  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.view.View;

  11 import android.view.View.OnClickListener;

  12 import android.widget.Button;

  13 import android.widget.Toast;

  14

  15 public class BaseTypeActivity extends Activity {

  16 private Button btn_startService, btn_endService,btn_getServiceData;

  17 private IDog dogService;

  18

  19 @Override

  20 protected void onCreate(Bundle savedInstanceState) {

  21 super.onCreate(savedInstanceState);

  22 setContentView(R.layout.activity_service);

  23

  24 btn_startService = (Button) findViewById(R.id.btn_startService);

  25 btn_endService = (Button) findViewById(R.id.btn_endService);

  26 btn_getServiceData = (Button) findViewById(R.id.btn_getServiceData);

  27

  28 btn_startService.setOnClickListener(click);

  29 btn_endService.setOnClickListener(click);

  30 btn_getServiceData.setOnClickListener(click);

  31 }

  32

  33 private View.OnClickListener click = new OnClickListener() {

  34

  35 @Override

  36 public void onClick(View v) {

  37 switch (v.getId()) {

  38 case R.id.btn_startService:

  39 startService();

  40 break;

  41 case R.id.btn_endService:

  42 endService();

  43 break;

  44 case R.id.btn_getServiceData:

  45 getServiceDate();

  46 break;

  47 }

  48 }

  49 };

  50 /*

  51 * 获取数据

  52 */

  53 private void getServiceDate() {

  54 try {

  55 if(dogService!=null){

  56 StringBuilder sBuilder=new StringBuilder();

  57 sBuilder.append("name:"+dogService.getName());

  58 sBuilder.append("nage:"+dogService.getAge());

  59 Toast.makeText(BaseTypeActivity.this, sBuilder.toString(), Toast.LENGTH_SHORT).show();

  60 }

  61 else

  62 {

  63 Toast.makeText(BaseTypeActivity.this, "请先绑定服务", Toast.LENGTH_SHORT).show();

  64 }

  65 } catch (Exception e) {

  66 e.printStackTrace();

  67 }

  68 }

  69

  70 private ServiceConnection connBase=new ServiceConnection() {

  71

  72 @Override

  73 public void onServiceDisconnected(ComponentName name) {

  74 dogService=null;

  75 }

  76

  77 @Override

  78 public void onServiceConnected(ComponentName name, IBinder service) {

  79 // IDog.Stub.asInterface,获取接口

  80 dogService=IDog.Stub.asInterface(service);

  81 }

  82 };

  83

  84 /**

  85 * 开始服务

  86 */

  87 private void startService(){

  88 Intent intent=new Intent();

  89 intent.setAction("cn.bgxt.Service.BASE_TYPE_SERVICE");

  90 bindService(intent, connBase, BIND_AUTO_CREATE);

  91 Toast.makeText(BaseTypeActivity.this, "开始绑定服务", Toast.LENGTH_SHORT).show();

  92 }

  93 /**

  94 * 停止服务

  95 */

  96 private void endService(){

  97 if(connBase!=null)

  98 {

  99 unbindService(connBase);

  100 // 接触绑定的时候需要回收dogService连接资源

  101 // 在源码中漏了,这是后来加上的

  102 dogService=null;

  103 Toast.makeText(BaseTypeActivity.this, "服务解除绑定", Toast.LENGTH_SHORT).show();

  104 }

  105 }

  106 }

  效果展示:先运行服务应用,再运行客户端应用。

 

时间: 2024-09-15 21:46:44

Android:Service之AIDL传递系统基本类型数据的相关文章

Android:Service之AIDL传递复杂对象

  AIDL传递复杂类型对象的特殊处理 前面已经介绍了通过AIDL接口在进程间传递系统允许的数据,如果需要传递一个复杂类型的对象,就没那么简单了,需要额外做一些处理.如下: 定义数据接口的AIDL文件中,使用parcelable关键字,例如:parcelable Message; 在其数据实现类中实现Parcelable接口,并实现对应的方法. 在业务接口的AIDL文件中,使用import引入数据接口AIDL的包名. 例如:Message.aidl 1 parcelable Message; 例

Android service binder aidl 关系

/********************************************************************************** * Android service binder aidl 关系 * 声明: * 最近一直被Android中的service.binder.aidl这三者之间的关系给搞得有点难受, * 于是就自己花了点时间,将他们之间的关系给画出来,这样思维上就清晰多了,也方便 * 和朋友沟通,减少沟通成本. * * 2016-1-10 晴 深圳

Android Service生命周期及用法

上一节我讲解了Android Activity的生命周期,这一节我将讲解一下Service,首先我们要知道Service具体是干什么的,什么时候用到?以及它的生命周期等. Service概念及用途: Android中的服务,它与Activity不同,它是不能与用户交互的,不能自己启动的,运行在后台的程序,如果我们退出应用时,Service进程并没有结束,它仍然在后台运行,那我们什么时候会用到Service呢?比如我们播放音乐的时候,有可能想边听音乐边干些其他事情,当我们退出播放音乐的应用,如果不

Android:复杂数据模型的传递

最近在研究怎样在Android的开发中传递一些复杂的数据.其实网上已经有很多的人都写过相关的,但是看了后,发现都大同小异,缺少我想要看到的地方.所以我打算做一下这方面的探讨. 有时候在团队开发的时候,我们会考虑创建一些复杂(包含的数据类型有多种)的Model,方便在数据上的传输和处理.一些关于Android中对于这类model的传递,一般都是实现Parcelable或者是Serializable这两个接口,这两个接口有一些不同,Serializable接口一般只做一些简单的数据类型传递,而Par

《Android开发进阶:从小工到专家》——第1章,第1.2节Service与AIDL

1.2 Service与AIDLService是Android中实现程序后台运行的解决方案,它非常适合用于去执行那些不需要和用户交互而且还要求长期运行的任务.但不要被"后台"二字所迷惑,Service默认并不会运行在子线程中,它也不运行在一个独立的进程中,它同样执行在UI线程中,因此,不要在Service中执行耗时的操作,除非你在Service中创建了子线程来完成耗时操作. Service的运行不依赖于任何用户界面,即使程序被切换到后台或者用户打开了另外一个应用程序,Service仍然

我的Android进阶之旅------>Android Service学习之AIDL, Parcelable和远程服务实例

通过上一篇(Android Service学习之AIDL, Parcelable和远程服务)的介绍,这一篇写一个小实例来实践一下 step1:建立两个应用,分别为RemoteService和RemoteServiceClient                                         先编写服务器端的内容 step2:开始编写一个StudentQuery.aidl文件      AIDL(Android Interface Definition Language),用来定

我的Android进阶之旅------>Android Service学习之AIDL, Parcelable和远程服务

AIDL的作用     由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象.在Android平台,一个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界.     通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作.       AIDL (Android Interface Definition Language) 是一种I

Android Service学习之AIDL, Parcelable和远程服务

AIDL的作用 由于每个应用程序都运行在自己的进程空间,并且可以从应用程序UI运行另一个服务进程,而且经常会在不同的进程间传递对象.在Android平台,一 个进程通常不能访问另一个进程的内存空间,所以要想对话,需要将对象分解成操作系统可以理解的基本单元,并且有序的通过进程边界. 通过代码来实现这个数据传输过程是冗长乏味的,Android提供了AIDL工具来处理这项工作. AIDL (Android Interface Definition Language) 是一种IDL 语言,用于生成可以在

android jni传递结构体类型给c函数,返回结构体,怎么写啊

问题描述 android jni传递结构体类型给c函数,返回结构体,怎么写啊 android jni传递结构体类型给c函数,返回结构体,怎么写啊 c方法:OutAnalyseResultPacket* EcgMainPro(InEcgPacket* pPacKet) 参数和返回值都是结构体类型 解决方案 参考:http://blog.sina.com.cn/s/blog_414e587f0101411f.html 另外,C那里返回结构体指针不太好,因为你没有机制去释放这些内存.容易内存泄漏.除非