深入Android架构(从线程到AIDL)_22 IPC的Proxy-Stub设计模式04
目录
5、 谁来写Proxy及Stub类呢?
如何考虑人的分工
IA接口知识取得的难题
在编程上,有什么技术可以实现这个方法?
范例
5、 谁来写Proxy及Stub类呢?
-- 强龙提供AIDL工具,给地头蛇产出Proxy和Stub类
如何考虑人的分工
- 由框架开发者来撰写Proxy-Stub类,才能减轻开发者的负担。
- 框架分为: <天子框架>和<曹操框架>。
- 因此, 应该由两者(天子或曹操)之一来撰写Proxy-Stub类。
IA接口知识取得的难题
- 但是,有个难题: IA接口(如下图所示)的内容必须等到<买主>来了才会知道。
- 在框架开发阶段,买主还没来, IA接口的知识无法取得,又如何定义IA接口呢? 没有IA接口定义,又如何撰写Stub和Proxy类呢?
- 好办法是:
“强龙(天子或曹操)撰写代码(在先) ;然后地头蛇(App开发者)定义接口(在后)。 ”
在编程上,有什么技术可以实现这个方法?
技术之一是: 類別模板(class template)例如,强龙撰写模板:
template< class T >
class SomeClass
{private:T data;public:SomeClass() { }void set(T da){ data = da; }
};
- 地头蛇利用模板来生成一个类:
SomeClass<Integer> x;
由于接口(interface)是一种特殊的类(class),所以也可以定义模板如下:
template<interface I>class BinderProxy{// ………};
- 地头蛇利用模板来生成一个类:
- 除了模板之外,还有其它编程技术可以实现<强龙写代码,地头蛇定义接口>的方案吗?
- 答案是:
程序生成器(program generator)
例如: Android的aidl.exe
AIDL
- AIDL的目的是定义Proxy/Stub来封装IBinder接口,以便产生更亲切贴心的新接口。
- •所以,在应用程序里,可以选择使用IBinder接口,也可以使用AIDL来定义出接口。
- AIDL的目的是定义Proxy/Stub来封装IBinder接口,以便产生更亲切贴心的新接口。
- 所以,在应用程序里,可以选择使用IBinder接口,也可以使用AIDL来定义出新接口。由于IBinder接口只提供单一函数(即transact()函数)来进行远距通信,呼叫起来比较不方便。
- 所以Android提供aidl.exe工具来协助产出Proxy和Stub类别,以化解这个困难。
- 只要你善于使用开发环境的工具(如Android的aidl.exe软件工具)自动产生Proxy和Stub类别的程序代码;那就很方便
了。
范例
- 此范例使用Android-SDK的/tools/里的aidl.exe工具程序,根据接口定义档(如下述的mp3PlayerInterface.aidl)而自动产出Proxy及Stub类别,其结构如下:
- 藉由开发工具自动产出Proxy及Stub类的代码,再分别转交给ac01和mp3Binder开发者。此范例程序执行时,出现画面如下:
- 依据UI画面的两项功能: <Play>和< Stop>,以Java定义接口,如下的代码:
// mp3PlayerInterface.aidl
interface mp3PlayerInterface mp3PlayerInterface{void play();void stop();
}
- 使用Android-SDK所含的aidl.exe工具,将上述的mp3PlayerInterface.aidl档翻译成为下述的mp3PlayerInterface.java档案。
// mp3PlayerInterface.java
/*
* This file is auto-generated. DO NOT MODIFY.
* Original file: mp3PlayerInterface.aidl
*/
// ………
public interface mp3PlayerInterface extends android.os.IInterface
{/** Local-side IPC implementation stub class. */public static abstract class Stub extends android.os.Binder implements com.misoo.pkgx.mp3PlayerInterface{// ……….public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags) throws android.os.RemoteException{switch (code){case INTERFACE_TRANSACTION:{reply.writeString(DESCRIPTOR);return true;}case TRANSACTION_play:{data.enforceInterface(DESCRIPTOR);this.play();reply.writeNoException();return true;}case TRANSACTION_stop:{data.enforceInterface(DESCRIPTOR);this.stop();reply.writeNoException();return true;}}return super.onTransact(code, data, reply, flags);}private static class Proxy implements com.misoo.pkgx.mp3PlayerInterface{private android.os.IBinder mRemote;//………….public void play() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_play, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();} }}public void stop() throws android.os.RemoteException{android.os.Parcel _data = android.os.Parcel.obtain();android.os.Parcel _reply = android.os.Parcel.obtain();try {_data.writeInterfaceToken(DESCRIPTOR);mRemote.transact(Stub.TRANSACTION_stop, _data, _reply, 0);_reply.readException();}finally {_reply.recycle();_data.recycle();}}static final int TRANSACTION_play = (IBinder.FIRST_CALL_TRANSACTION + 0);static final int TRANSACTION_stop = (IBinder.FIRST_CALL_TRANSACTION + 1);}public void play() throws android.os.RemoteException;public void stop() throws android.os.RemoteException;
}
- 表面上,此mp3PlayerInterface.java是蛮复杂的,其实它的结构是清晰又简单的,只要对于类继承、反向調用和接口等面向对象观念有足够的认识,就很容易理解了。
// mp3Binder.java
package com.misoo.pkgx;
import android.content.Context;
import android.media.MediaPlayer;
import android.util.Log;public class mp3Binder extends mp3PlayerInterface.Stub{private MediaPlayer mPlayer = null;private Context ctx;public mp3Binder(Context cx){ ctx= cx; }public void play(){if(mPlayer != null) return;mPlayer = MediaPlayer.create(ctx, R.raw.test_cbr);try { mPlayer.start();} catch (Exception e){ Log.e("StartPlay", "error: " + e.getMessage(), e); }}public void stop(){if (mPlayer != null){ mPlayer.stop(); mPlayer.release(); mPlayer = null; }}
}
- 撰写mp3RemoteService类
// mp3Service.java
package com.misoo.pkgx;
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;public class mp3Service extends Service {IBinder ib = null;@Override public void onCreate() {super.onCreate();ib = new mp3Binder(this.getApplicationContext());}@Override public void onDestroy() { }@Override public IBinder onBind(Intent intent) {return ib;}
}// ac01.java
// ………
public class ac01 extends Activity implements OnClickListener {//……….private PlayerProxy pProxy = null;public void onCreate(Bundle icicle) {// ………startService(new Intent("com.misoo.pkgx.REMOTE_SERVICE"));bindService(new Intent("com.misoo.pkgx.REMOTE_SERVICE"),mConnection, Context.BIND_AUTO_CREATE);}private ServiceConnection mConnection = new ServiceConnection() {public void onServiceConnected(ComponentName className,IBinder ibinder) {pProxy = mp3PlayerInterface.Stub.asInterface(ibinder);}public void onServiceDisconnected(ComponentName className) {}};public void onClick(View v) {switch (v.getId()) {case 101: pProxy.play(); tv.setText(pProxy.getStatus()); break;case 102: pProxy.stop(); tv.setText(pProxy.getStatus()); break;case 103:unbindService(mConnection);stopService(new Intent("com.misoo.pkgx.REMOTE_SERVICE"));finish(); break;}}
}
- 对于Anrdoid的初学者而言, Android的 AIDL机制可说是最难弄懂的。
相关文章:

深入Android架构(从线程到AIDL)_22 IPC的Proxy-Stub设计模式04
目录 5、 谁来写Proxy及Stub类呢? 如何考虑人的分工 IA接口知识取得的难题 在编程上,有什么技术可以实现这个方法? 范例 5、 谁来写Proxy及Stub类呢? -- 强龙提供AIDL工具,给地头蛇产出Proxy和Stub类 如何考虑人的分工 由框架开发者…...

【MySQL数据库】基础总结
目录 前言 一、概述 二、 SQL 1. SQL通用语法 2. SQL分类 3. DDL 3.1 数据库操作 3.2 表操作 4. DML 5. DQL 5.1 基础查询 5.2 条件查询 5.3 聚合函数 5.4 分组查询 5.5 排序查询 5.6 分页查询 6. DCL 6.1 管理用户 6.2 权限控制 三、数据类型 1. 数值类…...
49_Lua调试
Lua提供了debug库用于创建自定义调试器,尽管Lua本身没有内置的调试器1。这个库允许开发者在程序运行时检查和控制执行流程,这对于开发过程中的错误查找和修复非常有用。 1.Debug库概述 debug库提供的函数可以分为两类:自省函数(introspection functions)和钩子函数(hoo…...
vue的KeepAlive应用(针对全部页面及单一页面进行缓存)
KeepAlive的作用是缓存包裹在其中的动态切换组件 当一个组件在 中被切换时,它的 activated 和 deactivated 生命周期钩子将被调用,用来替代 mounted 和 unmounted。这适用于 的直接子节点及其所有子孙节点。 缓存全部页面 将app.vue中的路由出口改为&am…...

lwip单网卡多ip的实现
1、今天要实现lwip的多个ip配置,本来以为需要自己修改很多核心代码 2、查阅资料才发现,lwip已经把接口留出来了 /** Define this to 1 and define LWIP_ARP_FILTER_NETIF_FN(pbuf, netif, type) * to a filter function that returns the correct neti…...
// Error: line 1: XGen: Candidate guides have not been associated!
Maya xgen 报错// Error: line 1: XGen: Candidate guides have not been associated! 复制下面粘贴到Maya脚本管理器python运行: import maya.cmds as cmds def connect_xgen_guides():guide_nodes cmds.ls(typexgmMakeGuide)for node in guide_nodes:downstream…...

第21篇 基于ARM A9处理器用汇编语言实现中断<三>
Q:怎样编写ARM A9处理器汇编语言代码配置按键端口产生中断? A:使用Intel Monitor Program创建中断程序时,Linker Section Presets下拉菜单中需选择Exceptions。主程序在.vectors代码段为ARM处理器设置异常向量表,在…...

mac homebrew配置使用
本文介绍mac上homebrew工具的安装、配置过程。homebrew功能类似于centos的yum,用于软件包的管理,使用上有命令的差异。 本次配置过程使用mac,看官方文档,在linux上也可以用,但我没试过,有兴趣的同学可以试试…...

慧集通(DataLinkX)iPaaS集成平台-业务建模之业务对象(三)
4.搜索配置 搜索配置是用于该业务对象发布后被其它业务对象的搜索组件调用时界面显示内容以及对应查询条件的配置;当我们选择一条业务对象然后点击功能按钮【搜索配置】,则进入业务对象的搜索配置维护界面。 在搜索配置的维护界面我们可以维护该业务对象…...

【redis初阶】环境搭建
目录 一、Ubuntu 安装 redis 二、Centos7 安装 redis 三、Centos8 安装 redis 四、redis客户端介绍 redis学习🥳 一、Ubuntu 安装 redis 使用 apt 安装 apt install redis -y 查看redis版本 redis-server --version 支持远程连接…...
salesforce sandbox的用户如何重置密码
在 Salesforce Sandbox 环境中,用户可以通过以下步骤重置密码: 方法 1:通过用户界面重置密码 登录到 Sandbox 环境: 打开 Sandbox 环境的 URL,通常形如 https://test.salesforce.com。输入用户名和密码。如果忘记密码&…...

做一个 简单的Django 《股票自选助手》显示 用akshare 库(A股数据获取)
图: 股票自选助手 这是一个基于 Django 开发的 A 股自选股票信息查看系统。系统使用 akshare 库获取实时股票数据,支持添加、删除和更新股票信息。 功能特点 支持添加自选股票实时显示股票价格和涨跌幅一键更新所有股票数据支持删除不需要的股票使用中…...

01、kafka知识点综合
kafka是一个优秀大吞吐消息队列,下面我就从实用的角度来讲讲kafka中,“kafka为何有大吞吐的机制”,“数据不丢失问题”,“精准一次消费问题” 01、kafka的架构组织和运行原理 kafka集群各个节点的名称叫broker,因为kaf…...
怎么用python写个唤醒睡眠电脑的脚本?
环境: win10 python3.12 问题描述: 怎么用python写个唤醒睡眠电脑的脚本? 解决方案: 1.唤醒处于睡眠状态的电脑通常不是通过编程直接实现的,而是依赖于硬件和操作系统提供的特性。对于Windows系统,可…...

【Linux】Linux开发:GDB调试器与Git版本控制工具指南
Linux相关知识点可以通过点击以下链接进行学习一起加油!初识指令指令进阶权限管理yum包管理与vim编辑器GCC/G编译器make与Makefile自动化构建 在 Linux 开发中,GDB 调试器和 Git 版本控制工具是开发者必备的利器。GDB 帮助快速定位代码问题,G…...
Git 的引用规格(refspec)语法
目录 引用规格语法格式常见用法强制 -f 和 的区别git fetch origin remote-branch:local-branch 和 git push origin local-branch:remote-branch 区别 引用规格语法格式 格式如下:[]<src>:<dst> 常见用法 # fetch git fetch origin <remote-bra…...

反转链表题目
文章目录 反转链表题目链接:[在线OJ](https://leetcode.cn/problems/reverse-linked-list/description/)题目详解思路1:思路1算法复杂度 思路2代码实现思路2算法复杂度 结语 欢迎大家来到我的博客,给生活来点impetus 让我们进入《题海探骊》…...

LED灯按键调光芯片、PWM调光IC、发光灯控制调光芯片
按键调光芯片,特别是LED灯使用PWM调光的芯片IC,是一种用于控制LED灯具亮度的集成电路,常用于台灯、壁灯、吊灯等照明设备中。这种芯片通过脉冲宽度调制(PWM)技术来调节LED的亮度,可以实现从最亮到最暗的平滑…...
Android Room 报错:too many SQL variables (code 1 SQLITE_ERROR) 原因及解决方法
报错信息: android.database.sqlite.SQLiteException: too many SQL variables (code 1 SQLITE_ERROR): while compiling: SELECT * FROM points WHERE id IN (?,?,?,...,?,?,?)SQLiteException: too many SQL variables 通常是由于一次查询或插入的 SQL 语句…...

USA-Entrepreneur-20240708-Business/Unusual
How to Get More Attention You can’t run a great business if you can’t capture people’s attention, says Gary Vaynerchuk. “如果你无法吸引人们的注意力,你就不能经营一家伟大的企业。”——Gary VaynerchukGary Vaynerchuk是一位知名的企业家、作家和公…...
React hook之useRef
React useRef 详解 useRef 是 React 提供的一个 Hook,用于在函数组件中创建可变的引用对象。它在 React 开发中有多种重要用途,下面我将全面详细地介绍它的特性和用法。 基本概念 1. 创建 ref const refContainer useRef(initialValue);initialValu…...

React第五十七节 Router中RouterProvider使用详解及注意事项
前言 在 React Router v6.4 中,RouterProvider 是一个核心组件,用于提供基于数据路由(data routers)的新型路由方案。 它替代了传统的 <BrowserRouter>,支持更强大的数据加载和操作功能(如 loader 和…...

安宝特方案丨XRSOP人员作业标准化管理平台:AR智慧点检验收套件
在选煤厂、化工厂、钢铁厂等过程生产型企业,其生产设备的运行效率和非计划停机对工业制造效益有较大影响。 随着企业自动化和智能化建设的推进,需提前预防假检、错检、漏检,推动智慧生产运维系统数据的流动和现场赋能应用。同时,…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
基于数字孪生的水厂可视化平台建设:架构与实践
分享大纲: 1、数字孪生水厂可视化平台建设背景 2、数字孪生水厂可视化平台建设架构 3、数字孪生水厂可视化平台建设成效 近几年,数字孪生水厂的建设开展的如火如荼。作为提升水厂管理效率、优化资源的调度手段,基于数字孪生的水厂可视化平台的…...
linux 下常用变更-8
1、删除普通用户 查询用户初始UID和GIDls -l /home/ ###家目录中查看UID cat /etc/group ###此文件查看GID删除用户1.编辑文件 /etc/passwd 找到对应的行,YW343:x:0:0::/home/YW343:/bin/bash 2.将标红的位置修改为用户对应初始UID和GID: YW3…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解
本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说,直接开始吧! 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

什么是Ansible Jinja2
理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具,可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板,允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板,并通…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...

【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...