怎样用AIDL Service 传递复杂数据

大家都知道在Android中通过AIDL可以跨进程调用Service中的数据,网上也有很多实例,但是大部分实例都是关于基本数据类型的远程调用,很少讲到复杂数据的调用,今天我用一个例子来演示一下怎样用AIDL Service 传递复杂数据。

我们分2步开始:

第一步:部署我们的服务端,也就是Service端:

1:在Service端我先自定义2个类型:Person和Pet。因为我们需要跨进程传递Person对象和Pet对象,所以Person类和Pet类都必须实现Parcelable接口,并要求在实现类中定义一个名为CREATER,类型为Parcelable.creator的静态Field。

代码如下:

  1 package com.example.remoteservice;
  2
  3 import android.os.Parcel;
  4 import android.os.Parcelable;
  5
  6 public class Person implements Parcelable {
  7     int id;
  8     String name;
  9     String pass;
 10
 11     public Person() {
 12
 13     }
 14
 15     public Person(int id, String name, String pass) {
 16         this.id = id;
 17         this.name = name;
 18         this.pass = pass;
 19     }
 20
 21     @Override
 22     public boolean equals(Object o) {
 23         if (this == o) {
 24             return true;
 25         }
 26         if (o == null) {
 27             return false;
 28         }
 29
 30         if (getClass() != o.getClass()) {
 31             return false;
 32         }
 33         Person other = (Person) o;
 34
 35         if (name == null) {
 36             if (other.name != null) {
 37                 return false;
 38             }
 39         } else if (!name.equals(other.name)) {
 40             return false;
 41         }
 42
 43         if (pass == null) {
 44             if (other.pass != null) {
 45                 return false;
 46             }
 47         } else if (!pass.equals(other.pass)) {
 48             return false;
 49         }
 50
 51         return true;
 52     }
 53
 54     @Override
 55     public int hashCode() {
 56         final int prime = 31;
 57         int result = 1;
 58         result = prime * result + (name == null ? 0 : name.hashCode());
 59         result = prime * result + (pass == null ? 0 : pass.hashCode());
 60         return result;
 61     }
 62
 63     @Override
 64     public int describeContents() {
 65
 66         return 0;
 67     }
 68
 69     @Override
 70     public void writeToParcel(Parcel arg0, int arg1) {
 71         arg0.writeInt(id);
 72         arg0.writeString(name);
 73         arg0.writeString(pass);
 74     }
 75
 76     public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() {
 77
 78         @Override
 79         public Person createFromParcel(Parcel source) {
 80
 81             return new Person(source.readInt(), source.readString(), source.readString());
 82         }
 83
 84         @Override
 85         public Person[] newArray(int size) {
 86
 87             return new Person[size];
 88         }
 89     };
 90
 91     public int getId() {
 92         return id;
 93     }
 94
 95     public void setId(int id) {
 96         this.id = id;
 97     }
 98
 99     public String getName() {
100         return name;
101     }
102
103     public void setName(String name) {
104         this.name = name;
105     }
106
107     public String getPass() {
108         return pass;
109     }
110
111     public void setPass(String pass) {
112         this.pass = pass;
113     }
114
115 }

因为我们会对Person进行比较,所以在Person类中我重写了

public int hashCode() 和 public boolean equals(Object o)方法
 1 package com.example.remoteservice;
 2
 3 import android.os.Parcel;
 4 import android.os.Parcelable;
 5
 6 public class Pet implements Parcelable {
 7     String name;
 8     float weight;
 9
10     public Pet(String name, float weight) {
11         this.name = name;
12         this.weight = weight;
13     }
14
15     public String getName() {
16         return name;
17     }
18
19     public void setName(String name) {
20         this.name = name;
21     }
22
23     public float getWeight() {
24         return weight;
25     }
26
27     public void setWeight(float weight) {
28         this.weight = weight;
29     }
30
31     @Override
32     public int describeContents() {
33
34         return 1;
35     }
36
37     @Override
38     public void writeToParcel(Parcel dest, int flags) {
39         dest.writeString(name);
40         dest.writeFloat(weight);
41
42     }
43
44     public static final Parcelable.Creator<Pet> CREATOR = new Creator<Pet>() {
45
46         @Override
47         public Pet createFromParcel(Parcel source) {
48
49             return new Pet(source.readString(), source.readFloat());
50         }
51
52         @Override
53         public Pet[] newArray(int size) {
54
55             return new Pet[size];
56         }
57     };
58
59     @Override
60     public String toString() {
61
62         return "name:" + this.name + ";weight:" + this.weight;
63     }
64
65 }

2:创建完自定义类型之后还需要用AIDL来定义它们,Person.aidl和Pet.aidl的代码如下:

1 package com.example.remoteservice;
2 parcelable Person;
1 package com.example.remoteservice;
2 parcelable Pet;

3:完成1,2之后就可以使用AIDL定义通信接口了,在这里我定义一个IPet.aidl的接口,代码如下:

1 package com.example.remoteservice; //必须导入包
2 import com.example.remoteservice.Person; //指定自定义类的位置
3 import com.example.remoteservice.Pet;
4
5 interface IPet
6 {
7 List<Pet> getPets(in Person owner);//这里的in表示Person对象是输入的参数
8 }

4:服务端的最后一步就是实现Service了,当然不要忘了注册Service,代码如下:

 1 package com.example.remoteservice;
 2
 3 import com.example.remoteservice.IPet.Stub;
 4
 5 import java.util.ArrayList;
 6 import java.util.HashMap;
 7 import java.util.List;
 8 import java.util.Map;
 9
10 import android.app.Service;
11 import android.content.Intent;
12 import android.os.IBinder;
13 import android.os.RemoteException;
14 import android.util.Log;
15
16 public class RemoteService extends Service {
17
18     private PetBinder petBinder;
19
20     private static Map<Person, List<Pet>> pets = new HashMap<Person, List<Pet>>();
21     static {
22         ArrayList<Pet> list1 = new ArrayList<Pet>();
23         list1.add(new Pet("candy", 2.2f));
24         list1.add(new Pet("sandy", 4.2f));
25         pets.put(new Person(1, "sun", "sun"), list1);
26
27         ArrayList<Pet> list2 = new ArrayList<Pet>();
28         list2.add(new Pet("moon", 5.2f));
29         list2.add(new Pet("hony", 6.2f));
30         pets.put(new Person(1, "csx", "csx"), list2);
31
32     }
33
34     public class PetBinder extends Stub {// 继承IPet接口中的Stub类,Stub类继承了Binder类,所有PetBinder也间接的继承了Binder类
35
36         @Override
37         public List<Pet> getPets(Person owner) throws RemoteException {
38
39             return pets.get(owner);
40         }
41
42     }
43
44     @Override
45     public IBinder onBind(Intent intent) {
46
47         Log.i("csx", "onBind");
48         return petBinder;
49     }
50
51     @Override
52     public void onCreate() {
53
54         super.onCreate();
55         Log.i("csx", "onCreate");
56         petBinder = new PetBinder();// 实例化Binder
57
58     }
59
60     @Override
61     public boolean onUnbind(Intent intent) {
62
63         Log.i("csx", "onUnbind");
64         return super.onUnbind(intent);
65     }
66
67     @Override
68     public void onDestroy() {
69
70         super.onDestroy();
71         Log.i("csx", "onDestroy");
72     }
73
74 }

这是我Service端的部署情况(其中MainActivity可以不用去实现,因为我们只提供服务,没有窗口显示):

第二步:部署客户端:

1.在客户端新建一个包,命名需要和服务端放置aidl文件的包名相同(我这里是com.example.remoteservice),然后把服务端的Person.java,Pet.java,Person.aidl,Pet.aidl,IPet.aidl复制到这个包下面

2.在activity中绑定远程服务进行数据交换,layout布局和activity代码如下:

 1 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 2     xmlns:tools="http://schemas.android.com/tools"
 3     android:layout_width="match_parent"
 4     android:layout_height="match_parent"
 5     android:paddingBottom="@dimen/activity_vertical_margin"
 6     android:paddingLeft="@dimen/activity_horizontal_margin"
 7     android:paddingRight="@dimen/activity_horizontal_margin"
 8     android:paddingTop="@dimen/activity_vertical_margin"
 9     tools:context="com.example.remoteclient.RemoteClient" >
10
11     <LinearLayout
12         android:layout_width="match_parent"
13         android:layout_height="match_parent"
14         android:orientation="vertical" >
15
16         <LinearLayout
17             android:layout_width="match_parent"
18             android:layout_height="wrap_content"
19             android:orientation="horizontal" >
20
21             <EditText
22                 android:id="@+id/editText_person"
23                 android:layout_width="wrap_content"
24                 android:layout_height="wrap_content"
25                 android:layout_gravity="bottom"
26                 android:ems="10" >
27             </EditText>
28
29             <Button
30                 android:id="@+id/button_ok"
31                 android:layout_width="wrap_content"
32                 android:layout_height="wrap_content"
33                 android:layout_gravity="bottom"
34                 android:text="确定" />
35         </LinearLayout>
36
37         <ListView
38             android:id="@+id/listView_pet"
39             android:layout_width="match_parent"
40             android:layout_height="wrap_content" >
41         </ListView>
42     </LinearLayout>
43
44 </RelativeLayout>

  1 package com.example.remoteclient;
  2
  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.support.v7.app.ActionBarActivity;
 11 import android.util.Log;
 12 import android.view.View;
 13 import android.view.View.OnClickListener;
 14 import android.widget.ArrayAdapter;
 15 import android.widget.Button;
 16 import android.widget.EditText;
 17 import android.widget.ListView;
 18
 19 import com.example.remoteservice.IPet;
 20 import com.example.remoteservice.Person;
 21 import com.example.remoteservice.Pet;
 22
 23 import java.util.List;
 24
 25 public class RemoteClient extends ActionBarActivity {
 26
 27     public static final String REMOTE_SERVICE_ACTION = "com.example.remoteservice.RemoteService.ACTION";
 28     EditText editText;
 29     Button button;
 30     ListView listView;
 31
 32     IPet petService;// 声明IPet接口
 33     List<Pet> pets;
 34     ServiceConnection conn = new ServiceConnection() {
 35
 36         @Override
 37         public void onServiceDisconnected(ComponentName name) {
 38             Log.i("csx", "onServiceDisconnected");
 39             conn = null;
 40         }
 41
 42         @Override
 43         public void onServiceConnected(ComponentName name, IBinder service) {
 44             Log.i("csx", "onServiceConnected");
 45             petService = IPet.Stub.asInterface(service);// 通过远程服务的Binder实现接口
 46
 47         }
 48     };
 49
 50     @Override
 51     protected void onCreate(Bundle savedInstanceState) {
 52         super.onCreate(savedInstanceState);
 53         setContentView(R.layout.remote_client_layout);
 54         editText = (EditText) findViewById(R.id.editText_person);
 55         button = (Button) findViewById(R.id.button_ok);
 56         listView = (ListView) findViewById(R.id.listView_pet);
 57
 58         Intent service = new Intent();
 59         service.setAction(REMOTE_SERVICE_ACTION);
 60
 61         bindService(service, conn, Service.BIND_AUTO_CREATE);// 绑定远程服务
 62
 63         button.setOnClickListener(new OnClickListener() {
 64
 65             @Override
 66             public void onClick(View v) {
 67                 String personName = editText.getText().toString();
 68                 if (personName == null || personName.equals("")) {
 69
 70                     return;
 71                 }
 72
 73                 try {
 74                     pets = petService.getPets(new Person(1, personName, personName));// 调用远程service的getPets方法
 75                     updataListView();
 76
 77                 } catch (RemoteException e) {
 78
 79                     e.printStackTrace();
 80                 } catch (NullPointerException e) {
 81                     e.printStackTrace();
 82                 }
 83
 84             }
 85         });
 86
 87     }
 88
 89     public void updataListView() {
 90         listView.setAdapter(null);
 91
 92         if (pets == null || pets.isEmpty()) {
 93             return;
 94
 95         }
 96         ArrayAdapter<Pet> adapter = new ArrayAdapter<Pet>(RemoteClient.this,
 97                 android.R.layout.simple_list_item_1, pets);
 98         listView.setAdapter(adapter);
 99
100     }
101
102     @Override
103     protected void onDestroy() {
104
105         unbindService(conn);// 解除绑定
106         super.onDestroy();
107     }
108
109 }

到此为止所有的工作都完成了,下面我们看一下效果:我在编辑框中输入“csx”,点击确定,就会显示出服务端RemoteService中pets的相应数据。

时间: 2024-10-11 21:28:23

怎样用AIDL Service 传递复杂数据的相关文章

android 怎样用AIDL Service 传递复杂数据

大家都知道在Android中通过AIDL可以跨进程调用Service中的数据,网上也有很多实例,但是大部分实例都是关于基本数据类型的远程调用,很少讲到复杂数据的调用,今天我用一个例子来演示一下怎样用AIDL Service 传递复杂数据. 我们分2步开始: 第一步:部署我们的服务端,也就是Service端: 1:在Service端我先自定义2个类型:Person和Pet.因为我们需要跨进程传递Person对象和Pet对象,所以Person类和Pet类都必须实现Parcelable接口,并要求在实

Android---45---使用AIDL Service传递复杂数据

 该实例所传输的数据类型是自定义类型. Android 要求调用远程Service的参数和返回值都需要实现Parcelable接口. 实现Parcelable接口相当于Android提供的一种自定义序列化机制. 实现Parcelable接口不仅要求实现该接口里定义的方法,而且要求在实现类中定义一个名为CREATOR 类型为Parcelable.Creator的静态Filed.除此之外,还要求使用AIDL代码来定义这些自定义类型. 服务端: 自定义两个类型:Person与Pet,其中Perso

Android AIDL Service 跨进程传递复杂数据

黑夜 黑夜给了我黑色的眼睛,我却用它寻找光明~ 传值方式 AIDL是同意跨进程传递值的,一般来说有三种方式: - 广播:这样的算是比較常见的一种方式了,传递小数据不错 - 文件:这个是保存到文件里.然后读取,传递大数据不错 - Service Bind模式.这个算是居中的一种方式,只是效率要高的多,唯一麻烦的是编写代码较为麻烦. 特别是复杂类型数据传递麻烦. 其是,另一些其它的办法进行数据传递.另外传递也并非仅仅能够使用一种,能够採用几种结合的方式进行. 今天要说的就是Service Bind进

Android服务之Service(四)--ASDL传递复杂数据对象

此实例与前面aidl不同之处在于,传递的数据比较复杂,传递了自定义数据对象,本实例使用到了两个数据对象Person和Pet,其中Person是作为远程调用Service传递的参数,Pet是远程Service返回调用端的数据.像Java的RMI需要将数据对象序列化一样,此数据对象也需要序列化,因此android要求远程Service传递的参数和返回值需要实现Parcelable接口. 实例化Parcelable接口不仅需要实例化接口中的方法,而且要求在实现类中定义一个名为CREATOR,类型为Pa

Service启动和数据传递

Service是四大组件之一,Service是服务的意思,像Windows上面的服务一样,服务是在后台运行的,承担着静悄悄,默默的在后台付出的工作. 在开发过程中Service可以在很多地方使用,比如播放多媒体的时候用户启动了其他Activity ,这个时候程序要在后台继续播放:或者在后台记录用户地理位置的改变,或者启动服务来一直监听某种事件等.虽然Service存在的价值不如Activity,但是一般都让Service执行耗时时间较长的操作.下面我们详细介绍一下Service. 一,启动Ser

基于Web Service的客户端框架搭建一:C#使用Http Post方式传递Json数据字符串调用Web Service

引言 前段时间一直在做一个ERP系统,随着系统功能的完善,客户端(CS模式)变得越来越臃肿.现在想将业务逻辑层以下部分和界面层分离,使用Web Service来做.由于C#中通过直接添加引用的方来调用Web Service的方式不够灵活,故采取手动发送Http请求的方式来调用Web Service.最后选择使用Post方式来调用Web Service,至于安全性和效率暂不考虑.在学习使用的过程,遇到了很多问题,也花了很长时间来解决,网上相关的帖子很少,如果各位在使用的过程中有一些问题难以解决,可

Android Studio开发基础之启动Service,并通过从Activity向Service传递数据

本实例演示启动Service,并通过从Activity向Service传递数据,新建一个Service,并敲如下代码: package com.example.lhb.startservice; import android.app.Service; import android.content.Intent; import android.os.IBinder; import android.view.ViewDebug; import android.widget.Toast; public

Android学习笔记二十六.跨进程调用Service(AIDL Service)

跨进程调用Service(AIDL Service) 一.AIDL Service 1.什么是AIDL Service? AIDL,即Android Interface Definition Language.是Android用于定义远程接口,AIDL接口定义语言的语法比较简单,这种接口定义语言并不是真正的编程语言,它只是定义两个进程之间的通信接口.AIDL的语法与Java接口很相似,但存在如下几点差异: (1)AIDL定义接口的源代码必须以.aidl结尾; (2)AIDL接口中用到数据类型,除

关于Android中的四大组件(AIDL Service的使用)

跨进程调用Service(AIDL Service) Android系统中的进程之间不能共享内存,因此,需要提供一些机制在不同进程之间进行数据通信. 在前一篇文章(关于Android中的四大组件(Service的开启与关闭))中介绍了开发人员如何定制自己的服务,但这些 服务并不能被其它的应用程序访问,为了使其它的应用程序也可以访问本应用程序提供的服务,Android系统采用了 远程过程调用(Remote Procedure Call,RPC)方式来实现.与很多其它的基于RPC的解决方案一样,An