怎样用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的相应数据。

 

转载于:https://www.cnblogs.com/lonng226/articles/4208204.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值