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

我们分2步开始:

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

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

代码如下:

 package com.example.remoteservice;

 import android.os.Parcel;
import android.os.Parcelable; public class Person implements Parcelable {
int id;
String name;
String pass; public Person() { } public Person(int id, String name, String pass) {
this.id = id;
this.name = name;
this.pass = pass;
} @Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null) {
return false;
} if (getClass() != o.getClass()) {
return false;
}
Person other = (Person) o; if (name == null) {
if (other.name != null) {
return false;
}
} else if (!name.equals(other.name)) {
return false;
} if (pass == null) {
if (other.pass != null) {
return false;
}
} else if (!pass.equals(other.pass)) {
return false;
} return true;
} @Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (name == null ? 0 : name.hashCode());
result = prime * result + (pass == null ? 0 : pass.hashCode());
return result;
} @Override
public int describeContents() { return 0;
} @Override
public void writeToParcel(Parcel arg0, int arg1) {
arg0.writeInt(id);
arg0.writeString(name);
arg0.writeString(pass);
} public static final Parcelable.Creator<Person> CREATOR = new Creator<Person>() { @Override
public Person createFromParcel(Parcel source) { return new Person(source.readInt(), source.readString(), source.readString());
} @Override
public Person[] newArray(int size) { return new Person[size];
}
}; public int getId() {
return id;
} public void setId(int id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public String getPass() {
return pass;
} public void setPass(String pass) {
this.pass = pass;
} }

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

public int hashCode() 和 public boolean equals(Object o)方法
 package com.example.remoteservice;

 import android.os.Parcel;
import android.os.Parcelable; public class Pet implements Parcelable {
String name;
float weight; public Pet(String name, float weight) {
this.name = name;
this.weight = weight;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public float getWeight() {
return weight;
} public void setWeight(float weight) {
this.weight = weight;
} @Override
public int describeContents() { return 1;
} @Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeString(name);
dest.writeFloat(weight); } public static final Parcelable.Creator<Pet> CREATOR = new Creator<Pet>() { @Override
public Pet createFromParcel(Parcel source) { return new Pet(source.readString(), source.readFloat());
} @Override
public Pet[] newArray(int size) { return new Pet[size];
}
}; @Override
public String toString() { return "name:" + this.name + ";weight:" + this.weight;
} }

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

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

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

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

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

 package com.example.remoteservice;

 import com.example.remoteservice.IPet.Stub;

 import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map; import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log; public class RemoteService extends Service { private PetBinder petBinder; private static Map<Person, List<Pet>> pets = new HashMap<Person, List<Pet>>();
static {
ArrayList<Pet> list1 = new ArrayList<Pet>();
list1.add(new Pet("candy", 2.2f));
list1.add(new Pet("sandy", 4.2f));
pets.put(new Person(1, "sun", "sun"), list1); ArrayList<Pet> list2 = new ArrayList<Pet>();
list2.add(new Pet("moon", 5.2f));
list2.add(new Pet("hony", 6.2f));
pets.put(new Person(1, "csx", "csx"), list2); } public class PetBinder extends Stub {// 继承IPet接口中的Stub类,Stub类继承了Binder类,所有PetBinder也间接的继承了Binder类 @Override
public List<Pet> getPets(Person owner) throws RemoteException { return pets.get(owner);
} } @Override
public IBinder onBind(Intent intent) { Log.i("csx", "onBind");
return petBinder;
} @Override
public void onCreate() { super.onCreate();
Log.i("csx", "onCreate");
petBinder = new PetBinder();// 实例化Binder } @Override
public boolean onUnbind(Intent intent) { Log.i("csx", "onUnbind");
return super.onUnbind(intent);
} @Override
public void onDestroy() { super.onDestroy();
Log.i("csx", "onDestroy");
} }

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

第二步:部署客户端:

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

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

 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="com.example.remoteclient.RemoteClient" > <LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" > <LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal" > <EditText
android:id="@+id/editText_person"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:ems="10" >
</EditText> <Button
android:id="@+id/button_ok"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:text="确定" />
</LinearLayout> <ListView
android:id="@+id/listView_pet"
android:layout_width="match_parent"
android:layout_height="wrap_content" >
</ListView>
</LinearLayout> </RelativeLayout>

 package com.example.remoteclient;

 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.support.v7.app.ActionBarActivity;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ListView; import com.example.remoteservice.IPet;
import com.example.remoteservice.Person;
import com.example.remoteservice.Pet; import java.util.List; public class RemoteClient extends ActionBarActivity { public static final String REMOTE_SERVICE_ACTION = "com.example.remoteservice.RemoteService.ACTION";
EditText editText;
Button button;
ListView listView; IPet petService;// 声明IPet接口
List<Pet> pets;
ServiceConnection conn = new ServiceConnection() { @Override
public void onServiceDisconnected(ComponentName name) {
Log.i("csx", "onServiceDisconnected");
conn = null;
} @Override
public void onServiceConnected(ComponentName name, IBinder service) {
Log.i("csx", "onServiceConnected");
petService = IPet.Stub.asInterface(service);// 通过远程服务的Binder实现接口 }
}; @Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.remote_client_layout);
editText = (EditText) findViewById(R.id.editText_person);
button = (Button) findViewById(R.id.button_ok);
listView = (ListView) findViewById(R.id.listView_pet); Intent service = new Intent();
service.setAction(REMOTE_SERVICE_ACTION); bindService(service, conn, Service.BIND_AUTO_CREATE);// 绑定远程服务 button.setOnClickListener(new OnClickListener() { @Override
public void onClick(View v) {
String personName = editText.getText().toString();
if (personName == null || personName.equals("")) { return;
} try {
pets = petService.getPets(new Person(1, personName, personName));// 调用远程service的getPets方法
updataListView(); } catch (RemoteException e) { e.printStackTrace();
} catch (NullPointerException e) {
e.printStackTrace();
} }
}); } public void updataListView() {
listView.setAdapter(null); if (pets == null || pets.isEmpty()) {
return; }
ArrayAdapter<Pet> adapter = new ArrayAdapter<Pet>(RemoteClient.this,
android.R.layout.simple_list_item_1, pets);
listView.setAdapter(adapter); } @Override
protected void onDestroy() { unbindService(conn);// 解除绑定
super.onDestroy();
} }

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

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

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

    黑夜 黑夜给了我黑色的眼睛,我却用它寻找光明~ 传值方式 AIDL是同意跨进程传递值的,一般来说有三种方式: - 广播:这样的算是比較常见的一种方式了,传递小数据不错 - 文件:这个是保存到文件里.然 ...

  2. Android菜鸟的成长笔记(22)——Android进程间传递复杂数据(AIDL)

    在上一篇中介绍了Andorid中的进程间的通信方式AIDL,本篇文章将介绍传递复杂数据的AIDL Service 下面通过一个示例说明: 本例子中用到了两个自定义类型:Person与Pet, 其中Pe ...

  3. Android AIDL Service

    AIDL Service //跨进程调用Service    一个APK想调用另一个APK中的Service 如何实现AIDL //定义两个进程之间的通信接口 Demo1 传递简单数据 AidlSer ...

  4. Android AIDL SERVICE 双向通信 详解

    http://www.cnblogs.com/punkisnotdead/p/5062631.html 起因 是这个blog 提到了 用webview 的时候 用开启子进程的方式 可以极大避免内存泄露 ...

  5. android中通过intent传递复杂数据

    android中在各个service或者acitivity之间可以通过Intent来传递一些数据,intent原生直接提供了一些简单数据类型的数据的传递,使用起来也很方便,比如int boolean ...

  6. 利用AXIS2传递JSON数据

    Axis2是目前比较流行的WebService引擎.WebService被应用在很多不同的场景.例如,可以使用WebService来发布服务端 Java类的方法,以便使用不同的客户端进行调用.这样可以 ...

  7. Android中的跨进程通信方法实例及特点分析(一):AIDL Service

    转载请注明出处:http://blog.csdn.net/bettarwang/article/details/40947481 近期有一个需求就是往程序中增加大数据的採集点,可是由于我们的Andro ...

  8. android 多个notifycation向同一个Actiivity传递不同数据

    如果你有这方面的需求,那你实践的时候可能会发现,多个Notifycation点击的时候会传递相同的数据. 通常情况下我们可能这样写. Notification notification = new N ...

  9. 通过js获取前台数据向一般处理程序传递Json数据,并解析Json数据,将前台传来的Json数据写入数据库表中

    摘自:http://blog.csdn.net/mazhaojuan/article/details/8592015 通过js获取前台数据向一般处理程序传递Json数据,并解析Json数据,将前台传来 ...

随机推荐

  1. poj 2367 Genealogical tree (拓扑排序)

    火星人的血缘关系很奇怪,一个人可以有很多父亲,当然一个人也可以有很多孩子.有些时候分不清辈分会产生一些尴尬.所以写个程序来让n个人排序,长辈排在晚辈前面. 输入:N 代表n个人 1~n 接下来n行 第 ...

  2. VisualBox会造成VPN连接不上问题

    今天连接VPN查找点资料,但是怎么也连接不上,一直出现651错误,开始以为是服务器配置原因,重新配置后发现问题依旧,后查找相关资料,发现有提到VisualPC, 感觉VisualBox跟VisualP ...

  3. hdoj 3849 By Recognizing These Guys, We Find Social Networks Useful【双连通分量求桥&&输出桥&&字符串处理】

    By Recognizing These Guys, We Find Social Networks Useful Time Limit: 2000/1000 MS (Java/Others)     ...

  4. ActiveMQ内存设置和流控

    启动脚本设置jvm的内存 if "%ACTIVEMQ_OPTS%" == "" set ACTIVEMQ_OPTS=-Xms1G-Xmx1G -Djava.ut ...

  5. python 语句,条件,循环

    #coding:utf-8__author__ = 'Administrator'#想要在同一行打印,print后面加','print 12,print 34'''从模块导入函数import some ...

  6. Yii CGridView 基本使用(三)关联表相关字段搜索

    加入 关联表 相关字段的搜索: 先说一句,我们在这里仅仅谈 "一对多" 的关联搜索,首先,不要忘了我们的数据库,忘记的同学请戳这里:这里.能够看到在 tbl_post 中是有一个外 ...

  7. int 0x13中断的參数传递

    int 0x13中断向量所指向的中断服务程序实质上就是磁盘服务程序. 用途:将指定扇区的代码载入到内存的指定位置. 因此,在使用int 0x13中断时要将參数传递给服务程序: 比如:将指定扇区和载入的 ...

  8. vim中的一些高级命令的使用

    现在一般在windows下面对txt文档操作的时候,我一般使用gvim软件来操作,虽然没有unix/linu下面的正宗,并且很多命令没有,但是还是有很多方便之处的 下面是重温vim命令时,我我自己以前 ...

  9. Qt全局热键(windows篇)

      Qt对于系统底层,一直没有很好的支持,例如串口并口通信,还有我们经常都会用到的全局热键,等等.既然Qt可能出于某种原因,不对这些进行支持,我们就只能自己写代码,调用系统相关的API了. 注意,这个 ...

  10. mfc开发问题_v1

    1. 设置对话框按钮背景图片? 首先,设置对话框按钮的属性为Bitmap,然后导入资源文件(一个你需要作为背景的小图片),最后在该对话框类的OnInitDialog函数中添加如下代码: //设置对话框 ...