怎样用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;
    }

    @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的代码如下:

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类

        @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的相应数据。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

HTTP客户端警告:Going to buffer response body of large or unknown size

HTTP客户端警告&#xff1a;Going to buffer response body of large or unknown size 点关注不迷路&#xff0c;欢迎再访&#xff01; 精简博客内容&#xff0c;尽量已行业术语来分享。 努力做到对每一位认可自己的读者负责。 帮助别人的同时更是丰富自己的良机。 目录 HTTP客…

筑牢思想防线——建行驻江门市分行纪检组举办2023年清廉合规大讲堂

为推动廉洁教育打通“最后一公里”&#xff0c;近日&#xff0c;建行驻江门市分行纪检组举办江门市分行2023年清廉合规大讲堂。 本次大讲堂检察官结合一线办案经历&#xff0c;从防范化解金融风险、预防金融从业人员犯罪等方面对全辖员工进行了深入浅出地的讲解&#xff0c;引导…

msvcp120.dll丢失是什么意思,哪个修复方法最简单

在计算机使用过程中&#xff0c;我们经常会遇到一些错误提示&#xff0c;其中之一就是“找不到msvcp120.dll”。这个错误通常发生在运行某些程序或游戏时&#xff0c;它会导致程序无法正常启动或运行。那么&#xff0c;这个错误提示到底是什么意思呢&#xff1f;为了解决这个问…

[23] 4K4D: Real-Time 4D View Synthesis at 4K Resolution

paper | proj | code 提出一种基于K-Planes的4D point cloud Representation&#xff1b;提出一种Hybrid appearance model&#xff0c;包含image blending model和SH model。其中&#xff0c;image blending model将3D点映射回原图中求得&#xff0c;SH model通过模型预测求得…

JAVA实现flappy bird游戏

图片素材 实现代码 import javax.imageio.ImageIO; import javax.swing.*; import java.awt.*; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import java.awt.image.BufferedImage; import java.util.Date; import java.text.SimpleDateFormat; i…

Linux中flask项目开启https访问

1.下载阿里云免费证书 2.项目添加https配置 3.服务器开启https访问 3.1 重新安装OpenSSL 3.2.重新安装Python 上一次已经讲过Linux安装部署Python: Linux安装Python3.10与部署flask项目实战详细记录,今天记录一下Python项目如何支持https访问…

【软件工程师从0到1】- 多态 (知识汇总)

前言 介绍&#xff1a;大家好啊&#xff0c;我是hitzaki辰。 社区&#xff1a;&#xff08;完全免费、欢迎加入&#xff09;日常打卡、学习交流、资源共享的知识星球。 自媒体&#xff1a;我会在b站/抖音更新视频讲解 或 一些纯技术外的分享&#xff0c;账号同名&#xff1a;hi…

yolov3学习总结

目标检测算法 单阶段&#xff1a;不提取出候选框&#xff0c;直接将整个图像输入模型中&#xff0c;算法直接输出检测结果&#xff0c;端到端 yolo&#xff0c;ssd 端到端&#xff0c;输入图像到网络中&#xff0c;然后从网络中输出图像 二阶段&#xff1a;先从图像中提取出…

C# 执行Excel VBA宏工具类

写在前面 在Excel文档的自动化处理流程中&#xff0c;有部分值需要通过已定义的宏来求解&#xff0c;所以延伸出了用C# 调用Excel中的宏代码的需求。 首先要从NuGet中引入Microsoft.Office.Interop.Excel 类库 using Excel Microsoft.Office.Interop.Excel; 代码实现 /// &l…

解决ubuntu23.10 wifi不能使用的问题

解决ubuntu23.10 wifi不能使用的问题 今天升级到了ubuntu23.10之后&#xff0c;wifi不能使用。 参考此视频解决了问题&#xff1a; https://www.youtube.com/watch?appdesktop&vn92O8rNKVb0 sudo lshw -class networkcd /etc/pm/sleep.dlssudo touch configsudo gedit co…

【git】pip install git+https://github.com/xxx/xxx替换成本地下载编译安装解决网络超时问题

目录 &#x1f311;&#x1f311; 背景 &#x1f312; &#x1f312;作用 &#x1f314;&#x1f314; 问题 &#x1f314;&#x1f314;解决方案 &#x1f319;方法一 &#x1f319;方法二 &#x1f31d;&#x1f31d;我的解决方案 整理不易&#xff0c;欢迎一键三连…

(保姆级教程)Mysql中事务的概念,什么是事务,如何使用事务,以及事务的隔离级别,什么是脏读、幻读,代码演示

继续讲解 Mysql 数据库中最重要的一个概念&#xff1a;事务 文章目录 事务1.1 什么是事务1.2 执行原理1.3 如何操作事务1.4 事务的特点&#xff08;ACID原则&#xff09;1.5 事务并发1.6 事务隔离级别1.6.1 事务并发问题操作演示1.6.2 脏读演示1.6.3 不可重复读演示1.6.4 幻读演…

使用Arrays.Sort并定制Comparator排序解决合并区间

合并区间-力扣算法题56题 以数组 intervals 表示若干个区间的集合&#xff0c;其中单个区间为 intervals[i] [starti, endi] 。请你合并所有重叠的区间&#xff0c;并返回 一个不重叠的区间数组&#xff0c;该数组需恰好覆盖输入中的所有区间 。 示例 1&#xff1a; 输入&am…

新手必看!!附源码!!STM32通用定时器-比较输出PWM

一、什么是PWM? PWM&#xff08;脉冲宽度调制&#xff09;是一种用于控制电子设备的技术。它通过调整信号的脉冲宽度来控制电压的平均值。PWM常用于调节电机速度、控制LED亮度、产生模拟信号等应用。 二、PWM的原理 PWM的基本原理是通过以一定频率产生的脉冲信号&#xff0…

PHP 语法||PHP 变量

PHP 脚本在服务器上执行&#xff0c;然后将纯 HTML 结果发送回浏览器。 基本的 PHP 语法 PHP 脚本可以放在文档中的任何位置。 PHP 脚本以 <?php 开始&#xff0c;以 ?> 结束&#xff1a; <?php // PHP 代码 ?> 值得一提的是&#xff0c;通过设定php.ini的相…

Spring配置其他注解Spring注解的解析原理

Spring配置其他注解 Primary注解用于标注相同类型的Bean优先被使用权&#xff0c;Primary是Spring 3.0引入的&#xff0c;与Component和Bean一起使用&#xff0c;标注该Bean的优先级更高&#xff0c;则在通过类型获取Bean或通过Autowired根据类型进行注入时&#xff0c;会选用优…

什么是数据确权?

在数字化时代&#xff0c;数据已经成为一种新型资产&#xff0c;”新的石油“&#xff0c;具有巨大的价值&#xff0c;未来世界经济竞争一定程度上是数字经济的竞争&#xff0c;而非工业的竞争。数据相关法律制度&#xff0c;尚且还不完整&#xff0c;推动数字经济的发展&#…

YOLOv8训练自己的目标检测数据集

YOLOv8训练自己的目标检测数据集 目录标题 源码下载环境配置安装包训练自己的数据集数据集文件格式数据集文件配置超参数文件配置训练数据集命令行训练脚本.py文件训练 进行detect显示detect的效果 源码下载 YOLOv8官方的GitHub代码&#xff0c;同时上面也有基础环境的配置要…

VOC数据集和COCO数据集直接的相互转换

VOC数据集格式 get_list.py import os import random import shutil# 设置随机种子 random.seed(1000)# 判断Annotations和JpegImages是否对应 train_precent=0.8 label_path= "../../Annotations" print(os.path.abspath(label_path)) save="../Main" pr…

前端工程、静态代码、Html页面 打包成nginx 的 docker镜像

1. 创建一个 mynginx的目录 2. 将前端代码文件夹&#xff08;比如叫 front &#xff09;复制到 mynginx 目录下 3. 在mynginx 目录下创建一个名为Dockerfile 的文件&#xff08;文件名不要改&#xff09;&#xff0c;文件内容如下&#xff1a; # 使用官方的 Nginx 镜像作为基…