Android AIDL Callback的使用(配源码)

news2025/2/26 22:10:19

零、示例说明

本示例,完成的功能是:客户端向服务端注册一个回调,服务端是一个商店shop,当商店里的产品 Product 有变化时,调用回调向通知客户端,什么商品更新了。

一、完整源代码

完整源码链接: https://github.com/jx0260/TestGradle

二、实现步骤

2.1 定义实体

定义 Product.aidl

// Product.aidl
package com.example.testgradle;

// Declare any non-default types here with import statements

parcelable Product;

对应的实体类:

package com.example.testgradle;

import android.os.Parcel;
import android.os.Parcelable;

public class Product implements Parcelable {

    private String no;
    private String name;

    public String getNo() {
        return no;
    }

    public void setNo(String no) {
        this.no = no;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    @Override
    public int describeContents() {
        return 0;
    }

    @Override
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(this.no);
        dest.writeString(this.name);
    }

    public void readFromParcel(Parcel source) {
        this.no = source.readString();
        this.name = source.readString();
    }

    public Product() {
    }

    protected Product(Parcel in) {
        this.no = in.readString();
        this.name = in.readString();
    }

    public static final Creator<Product> CREATOR = new Creator<Product>() {
        @Override
        public Product createFromParcel(Parcel source) {
            return new Product(source);
        }

        @Override
        public Product[] newArray(int size) {
            return new Product[size];
        }
    };
}

定义Callback AIDL,此 IShopProductCallback 将会注册到服务端去。

// IShopProductCallback.aidl
package com.example.testgradle;
import com.example.testgradle.Product;

// Declare any non-default types here with import statements

interface IShopProductCallback {
    oneway void onProductChanged(in Product product);
}

定义服务端 IShopAidlInterface.aidl,里面有一个registerCallback的方法

// IShopAidlInterface.aidl
package com.example.testgradle;
import com.example.testgradle.IShopProductCallback;

// Declare any non-default types here with import statements

interface IShopAidlInterface {

    String getProductInfo(int productNo);

    void buyProduct1(int productNo, String address);

    oneway void registerCallback(in IShopProductCallback callback);

}

2.2 Make project 生成相应的 AIDL实现类

客户端:
在这里插入图片描述
服务端:
在这里插入图片描述

2.2 编写客户端

Intent serviceIntent = new Intent("com.example.testgradle.ShopService");
serviceIntent.setPackage("com.example.testgradle");
bindService(serviceIntent, new ServiceConnection() {
    @Override
    public void onServiceConnected(ComponentName name, IBinder service) {
        Log.i(TAG, "onServiceConnected() service=" + service);
        iShopAidlInterface = IShopAidlInterface.Stub.asInterface(service);
        try {
            Log.i(TAG, "Client: register Stub to Server!");
            iShopAidlInterface.registerCallback(new IShopProductCallback.Stub() {
                @Override
                public void onProductChanged(Product product) throws RemoteException {
                    Log.i(TAG, "Client: received product changed -- " + product.getNo() + " name:" + product.getName());
                }
            });
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onServiceDisconnected(ComponentName name) {

    }
}, BIND_AUTO_CREATE);

bindService() com.example.testgradle.ShopService ,在 onServiceConnected 回调中,使用拿到的 iShopAidlInterface 对象,调用 registerCallback,注意,此处传入的 callback 是 IShopProductCallback.Stub

public interface IShopProductCallback extends android.os.IInterface
{
  /** Local-side IPC implementation stub class. */
  public static abstract class Stub extends android.os.Binder

IShopProductCallback.Stub 继承了 Binder,实际上此处将 IShopProductCallback 的实现传进了参数,到达服务端。服务端拿到的是 IShopProductCallback.Stub.Proxy,这里就会有一种服务端变成客户端的感觉。实际上确实如此,在使用Callback的时候 服务端对于Callback来说 确实就变成了客户端,将变化的product 提交到服务端(也就是业务上的客户端)
此处,引用的“客户端”,“服务端”是有两套意思,一套是指我们总体业务的 客户端、服务端,另一套是指对于callback来说,程序实现的 客户端、服务端。

2.3 编写服务端

package com.example.testgradle;

import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;

import javax.security.auth.login.LoginException;

public class ShopService extends Service {
    private String TAG = "ShopService";
    private IShopProductCallback mCallback;

    public ShopService() {
    }

    private IShopAidlInterface.Stub mBinder = new IShopAidlInterface.Stub() {
        @Override
        public void registerCallback(IShopProductCallback callback) throws RemoteException {
            Log.i(TAG, "Server: registerCallback() this callback obj is a proxy!");
            mCallback = callback;

            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    Product product = new Product();
                    product.setNo("No.0001");
                    product.setName("banana");
                    try {
                        Log.i(TAG, "Server: the proxy obj invoke onProductChanged, pass the product to the client!");
                        mCallback.onProductChanged(product);
                    } catch (RemoteException e) {
                        e.printStackTrace();
                    }
                }
            }, 20000);
        }
    };

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }
}

服务端 public void registerCallback(IShopProductCallback callback) 拿到客户端传来的 callback其实是一个proxy 存到mCallback 本地变量中,20秒后,创建一个变化的Product 调用 mCallback.onProductChanged(product); 将商品信息回调给客户端。

2.4 运行

日志打印:

com.example.testgradle I/ShopService: Server: registerCallback() this callback obj is a proxy!

com.example.testgradle I/ShopService: Server: the proxy obj invoke onProductChanged, pass the product to the client!
com.example.clientdemo I/ClientActivity: Client: received product changed -- No.0001 name:banana

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

电脑丢失dll文件怎么一键修复?哪种dll修复方法靠谱?

在使用电脑时&#xff0c;我们经常会遇到一些问题&#xff0c;例如电脑丢失了某些dll文件。这些文件是电脑运行所必需的&#xff0c;如果缺少了这些文件&#xff0c;电脑就无法正常运行。在这种情况下&#xff0c;我们需要使用使用一些方法去进行相关的修复&#xff01;下面我们…

微信小程序原生开发功能合集十九:大屏适配、分栏代码可视化编辑、骨架屏生成及WebView使用介绍

本章实现小程序大屏适配实现、pc端分栏展示实现、代码可视化编辑、骨架屏生成及WebView组件使用介绍。   另外还提供小程序开发基础知识讲解课程,包括小程序开发基础知识、组件封装、常用接口组件使用及常用功能实现等内容,具体如下:    1. CSDN课程: https://edu.csd…

高精度气象模拟软件WRF:天气预报、观测气温、分析降水、模拟尺度气象、模拟水汽湿度、土地利用变化影响、土壤水分通量、分析风场、分析土壤水体植被等气象变量

查看原文>>>高精度气象模拟软件WRF(Weather Research Forecasting)技术及案例应用 气候是多个领域&#xff08;生态、水资源、风资源及碳中和等问题&#xff09;的主要驱动因素&#xff0c;合理认知气候变化有利于解释生态环境变化机理及过程&#xff0c;而了解现在、…

立刻杀掉Oracle中的会话(session)

一、需求描述 我们开发项目的过程中,涉及到连接oracle数据库的操作,正常来说我们执行完对应的sql语句后且关闭了连接,数据库的连接就会释放了;但是现实的情况是我们在查询数据库建立的会话时,发现存在大量的InAactive会话(我们需要找到原因,且将当前的会话立刻手动删除掉…

从零手写操作系统之RVOS任务同步和锁实现-07

从零手写操作系统之RVOS任务同步和锁实现-07 并发与同步临界区、锁、死锁自旋锁1.0 版本2.0 版本原子指令思路测试 3.0 版本测试 小结其他同步技术 本系列参考: 学习开发一个RISC-V上的操作系统 - 汪辰 - 2021春 整理而来&#xff0c;主要作为xv6操作系统学习的一个前置基础。 …

练习:程序切片

练习&#xff1a;程序切片 1 简介 注&#xff1a;问题3提到了conditioned slicing。 我们没有给出计算条件切片的算法&#xff0c;但你不应该要求这样的算法。 2 问题 1 对于以下每个代码片段&#xff0c;绘制程序依赖图&#xff08;没有定义顺序边&#xff09;。 基于这些&am…

什么是 Vue.js 中的 v-if 和 v-show 指令?

什么是 Vue.js 中的 v-if 和 v-show 指令&#xff1f; Vue.js 是一种用于构建交互式用户界面的渐进式框架。它采用了响应式的数据绑定机制和组件化的开发模式&#xff0c;让开发者能够更加高效地构建复杂的 Web 应用。在 Vue.js 中&#xff0c;v-if 和 v-show 是两个常用的指令…

STM32开发——电动车报警装置

1.项目简介 1.1项目需求 点击遥控器 A 按键&#xff0c;系统进入警戒模式&#xff0c;一旦检测到震动&#xff08;小偷偷车&#xff09;&#xff0c;则喇叭发出声响报警&#xff0c; 吓退小偷。 点击遥控器 B 按键&#xff0c;系统退出警戒模式&#xff0c;再怎么摇晃系统都不…

通过项目驱动的学习方法快速掌握Java编程

摘要 Java作为一种广泛应用于软件开发领域的编程语言&#xff0c;对于零基础的学习者来说&#xff0c;学习Java编程可能存在一定的难度。本文将介绍如何通过项目驱动的学习方法&#xff0c;帮助零起点的学习者快速掌握Java编程。通过以项目为核心的学习路径、结合实践和理论的…

【Pytorch】自定义模型、自定义损失函数及模型删除修改层的常用操作

目录 问题一&#xff1a;更改模型最后一层&#xff0c;删除最后一层问题二&#xff1a;自定义模型及参数冻结问题三&#xff1a;自定义损失函数及广播机制 问题1&#xff1a;更改模型最后一层&#xff0c;删除最后一层&#xff0c;添加层。 改变模型最后一层 # Load the mo…

Jmter自动化

一、接口测试流程 1、拿到api接口文档&#xff0c;熟悉接口业务。 2、编写测试用例。 正例&#xff1a;正常参数&#xff0c;是否接口正常 反例&#xff1a;鉴权异常情况、参数异常、兼容性、黑名单、调用次数异常 3、使用接口测试用具&#xff08;Jmeter&#xff09; 4、…

chatgpt赋能python:Python安装gym:入门指南

Python安装gym: 入门指南 如果您是一位正在学习强化学习的学生&#xff0c;或者是一位研究者、开发人员&#xff0c;那么您一定会对OpenAI出品的gym库感兴趣。该库为编写和比较强化学习算法提供了一组标准环境。但是&#xff0c;在使用gym之前&#xff0c;您需要将其安装到您的…

ThinkPad无法进系统的解决方案(实测)

ThinkPad无法进系统如何解决&#xff1f; 不一样的笔记本进到BIOS的方法是不太一样的&#xff0c;下面就和大伙儿具体解读电脑上进到thinkpad的bios设置启动项的方法吧。 在开机或重启的Lenovo画面自检处&#xff0c;快速、连续多次按键盘的“F1”按键&#xff0c;即可进入BI…

基于html+css的图展示112

准备项目 项目开发工具 Visual Studio Code 1.44.2 版本: 1.44.2 提交: ff915844119ce9485abfe8aa9076ec76b5300ddd 日期: 2020-04-16T16:36:23.138Z Electron: 7.1.11 Chrome: 78.0.3904.130 Node.js: 12.8.1 V8: 7.8.279.23-electron.0 OS: Windows_NT x64 10.0.19044 项目…

PHP实现文件上传

上传文件的必备三个条件&#xff1a; 1、上传到后台的文件 2、method "post";&#xff08;不可以为get方法&#xff09; 3、enctype "multipart/form-data";&#xff08;注意哦&#xff0c;是data&#xff0c;不是date&#xff09; 三者缺一不可 后台…

抛弃传统网络?SDN协议、标准、接口对比分析!

概要&#xff1a; 随着网络规模的不断扩大和复杂性的增加&#xff0c;传统的网络架构已经难以满足日益增长的网络需求。SDN&#xff08;Software Defined Networking&#xff09;技术的出现&#xff0c;为网络的管理和控制带来了革命性的变化。SDN的核心思想是将网络的控制和管…

chatgpt赋能python:Python如何访问文件

Python如何访问文件 Python是一种优秀的编程语言&#xff0c;被广泛应用于各种领域&#xff0c;包括文件处理。在Python中&#xff0c;我们可以使用内置的文件处理功能访问文件。 什么是文件&#xff1f; 文件是计算机系统中的一种数据存储形式。它们可以包含任何类型的信息…

u盘视频丢失怎么找回?居然还得靠它

u盘视频丢失怎么找回&#xff1f;U盘作为一款常用的存储数据的工具&#xff0c;因为其自身的小巧便携&#xff0c;方便我们随身携带&#xff0c;深受广大用户的喜爱。在使用U盘的过程中&#xff0c;我们也会遇到一些文件丢失的麻烦&#xff0c;比如误删除里面的视频文件。当遇到…

浅谈 Tarjan 算法

在了解 Tarjan 算法之前&#xff0c;我们先来了解 dfs 搜索树。 1 dfs 生成树 定义&#xff1a; dfs 遍历整张图&#xff0c;按照 dfs 序构成一棵树。 1.1 有向图的 dfs 生成树 有向图的 dfs 生成树包括四种边&#xff1a; 树边&#xff08;tree edge&#xff09;&#xff…

CDC是什么?有没有合适的技术方案?

CDC 是 Change Data Capture(变更数据获取)的简称。核心思想是&#xff0c;监测并捕获数据库的 变动&#xff08;包括数据或数据表的插入、更新以及删除等&#xff09;&#xff0c;将这些变更按发生的顺序完整记录下 来&#xff0c;写入到消息中间件中以供其他服务进行订阅及…