怎样用AIDL Service 传递复杂数据

大家都知道在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;}@Overridepublic 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;}@Overridepublic 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;}@Overridepublic int describeContents() {return 0;}@Overridepublic 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>() {@Overridepublic Person createFromParcel(Parcel source) {return new Person(source.readInt(), source.readString(), source.readString());}@Overridepublic 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;}@Overridepublic int describeContents() {return 1;}@Overridepublic void writeToParcel(Parcel dest, int flags) {dest.writeString(name);dest.writeFloat(weight);}public static final Parcelable.Creator<Pet> CREATOR = new Creator<Pet>() {@Overridepublic Pet createFromParcel(Parcel source) {return new Pet(source.readString(), source.readFloat());}@Overridepublic Pet[] newArray(int size) {return new Pet[size];}};@Overridepublic String toString() {return "name:" + this.name + ";weight:" + this.weight;}}

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

Person.aidl

package com.example.remoteservice;
parcelable Person;
Pet.aidl
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类@Overridepublic List<Pet> getPets(Person owner) throws RemoteException {return pets.get(owner);}}@Overridepublic IBinder onBind(Intent intent) {Log.i("csx", "onBind");return petBinder;}@Overridepublic void onCreate() {super.onCreate();Log.i("csx", "onCreate");petBinder = new PetBinder();// 实例化Binder}@Overridepublic boolean onUnbind(Intent intent) {Log.i("csx", "onUnbind");return super.onUnbind(intent);}@Overridepublic 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" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical" ><LinearLayoutandroid:layout_width="match_parent"android:layout_height="wrap_content"android:orientation="horizontal" ><EditTextandroid:id="@+id/editText_person"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom"android:ems="10" ></EditText><Buttonandroid:id="@+id/button_ok"android:layout_width="wrap_content"android:layout_height="wrap_content"android:layout_gravity="bottom"android:text="确定" /></LinearLayout><ListViewandroid: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() {@Overridepublic void onServiceDisconnected(ComponentName name) {Log.i("csx", "onServiceDisconnected");conn = null;}@Overridepublic void onServiceConnected(ComponentName name, IBinder service) {Log.i("csx", "onServiceConnected");petService = IPet.Stub.asInterface(service);// 通过远程服务的Binder实现接口}};@Overrideprotected 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() {@Overridepublic 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);}@Overrideprotected void onDestroy() {unbindService(conn);// 解除绑定super.onDestroy();}}

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/212056.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【神印王座】龙皓晨美妆胜过月夜,魔神皇识破无视,撮合月夜阿宝

Hello,小伙伴们&#xff0c;我是拾荒君。 《神印王座》国漫第82集已更新&#xff0c;拾荒君和大多数人一样&#xff0c;更新就去看了。魔神皇枫秀&#xff0c;威严凛然&#xff0c;突然空降月魔宫&#xff0c;整个宫殿都在这股无与伦比的强大气息中颤栗。为了顺利躲避魔神皇的…

延时任务定时发布,基于 Redis 与 DB 实现

目录 1、什么是延时任务&#xff0c;分别可以使用哪些技术实现&#xff1f; 1.2 使用 Redis 和 DB 相结合的思路图以及分析 2、实现添加任务、删除任务、拉取任务 3、实现未来数据的定时更新 4、将数据库中的任务数据&#xff0c;同步到 Redis 中 1、什么是延时任务&#xff…

【工具栏】热部署不生效

目录 配置热部署&#xff1a; 解决热部署不生效&#xff1a; 首先检查&#xff1a; 第一步&#xff1a; 第二步&#xff1a; 第三步&#xff1a; 第四步&#xff1a; 配置热部署&#xff1a; https://blog.csdn.net/m0_67930426/article/details/133690559 解决热部署不…

深入理解JVM 类加载机制

深入理解JVM 类加载机制 虚拟机如何加载Class文件&#xff1f; Class文件中的信息进入到虚拟机后会发生什么变化&#xff1f; 类加载机制就是Java虚拟机把描述类的数据从Class文件加载到内存&#xff0c;并对数据进行校验、转换解析和初始化&#xff0c;最终形成可以被虚拟机…

6.2.SDP协议

那今天呢&#xff1f;我们来介绍一下sdp协议&#xff0c;那实际上呢&#xff1f;sdp协议非常的简单。我们如果拿到一个stp的文档去看的话&#xff0c;那你要分阅里边的所有的内容会觉得很枯燥&#xff0c;但实际上呢&#xff0c;如果我们按照这张图所展示的结构去看stp的话。你…

[MySQL] MySQL 表的增删查改

本篇文章对mysql表的增删查改进行了详细的举例说明解释。对表的增删查改简称CRUD : Create(创建), Retrieve(读取)&#xff0c;Update(更新)&#xff0c;Delete&#xff08;删除&#xff09;。其中重点是对查询select语句进行了详细解释&#xff0c;并且通过多个实际例子来帮助…

【从零开始实现意图识别】中文对话意图识别详解

前言 意图识别&#xff08;Intent Recognition&#xff09;是自然语言处理&#xff08;NLP&#xff09;中的一个重要任务&#xff0c;它旨在确定用户输入的语句中所表达的意图或目的。简单来说&#xff0c;意图识别就是对用户的话语进行语义理解&#xff0c;以便更好地回答用户…

【RtpRtcp】1: webrtc m79:audio的ChannelReceive 创建并使用

m79中,RtpRtcp::Create 的调用很少 不知道谁负责创建ChannelReceiveclass ChannelReceive : public ChannelReceiveInterface,public MediaTransportAudioSinkInterface {接收编码后的音频帧:接收rtcp包:

VTK表面画贴合线条避免陷入局部最小值

通常画线&#xff0c;由于距离太远会陷入局部最小值&#xff0c;通过算法解决这一问题。 1、陷入局部最小值 2、算法解决陷入局部最小值问题

大模型增量预训练参数说明

在增量预训练过程中通常需要设置三类或四类参数,模型参数,数据参数,训练参数,额外参数。 下面分别针对这四种参数进行说明。 欢迎关注公众号 模型参数 model_type模型类型,例如bloom,llama,baichuan,qwen等。 model_name_or_path模型名称或者路径。 tokenizer_name_or…

奥特曼重返CEO之位!AI发展成硅谷巨头与保守科学家权力之争

OpenAI&#xff0c;一家因ChatGPT而闻名的人工智能公司&#xff0c;近日陷入了一场激烈的权力之争。创始人兼CEO山姆奥特曼&#xff08;Sam Altman&#xff09;突然离职&#xff0c;引发了一系列连锁反应。然而&#xff0c;在经过一番波折和谈判后&#xff0c;奥特曼最终重返Op…