zoukankan      html  css  js  c++  java
  • 怎样用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的相应数据。

  • 相关阅读:
    php实现上传图片保存到数据库的方法
    支付宝集成——如何在回调地址中使用自定义参数
    QQ音乐的各种相关API
    xampp默认mysql密码设置,修改mysql的默认空密码
    node.js 初体验
    php调用empty出现错误Can't use function return value in write context
    ecshop数据库操作函数
    ecshop中$user对象
    为什么我的联想打印机M7450F换完墨粉之后打印机显示请更换墨粉盒?这是我的墨盒第一次灌粉·、
    PHP中获取当前页面的完整URL
  • 原文地址:https://www.cnblogs.com/csxcode/p/4207158.html
Copyright © 2011-2022 走看看