Android底层软硬件结合开发

Android多媒体功能开发(14)——Camera2框架 Camera2框架的相机模型被设计成一个管道,使用相机时需要先和相机设备建立一个会话,通过该会话向相机发送请求,相机将图像数据保存到配置好的Surface,Surface就是存放图像数据的缓冲区。请求分为单次请求、重复请求和多次请求三种。 阅读详情

Android底层软硬件结合开发概述

Android底层软硬件结合开发概述

Android是 个开源的智能移动平台 一个开源的智能移动平台, 任何 个厂商拿 一个厂商拿到 Android Source 都可以基于自己的硬件架构设计

移动设备。

硬件多样化

厂商自己的利益

软硬件结合开发的弊端?

失去了Android应用的跨平台特性

由于不同厂商研发能力参差不齐,应用程序的稳定性及性能有所不同

分类

NDK开发:

从应用角度来开发软硬结合代码

适用于单个应用程序的底层结合需求

HAL硬件抽象层开发:

从整个系统框架需求角度来开发本地程序

适用于共享功能软硬结合代码

HAL 概念

HAL( Hardware Abstract Layer)硬件抽象层是Google开发的Android系统里上层应用对底层硬件操作屏蔽的一个软件层次,说白了,就是上层的应用不用关心底层硬件具体是如何工作的,只要向上提供一个统一的接口即可,这种设计思想广泛的存在于当前的软件架构设计里。

image-20200706134655889

image-20200706134701523

image-20200706134709193

image-20200706134718998

image-20200706134646845

HAL存在的原因

1、 并不是所有的硬件设备都有标准的 linux kernel 的接口。

2、 Kernel driver涉及到GPL的版权。某些设备制造商并不愿意公开硬件驱动,所以才通过HAL方式绕过GPL。

3、 针对某些硬件, Android有一些特殊的需求。

HAL简介及现状分析

现有HAL架构由 Patrick Brady (Google) 在2008G l oogle I/O演讲中提出, 从上面架构图我们知道,HAL 的目的是为了把 Android framework 与Linux kernel 完整「隔开」。让 Android 不至过度依赖 Linux kernel, 有点「kernel independent」的意思。

AL简介及现状分析

HAL 主要的实现储存于以下目录

libhardware_legacy/ ‐ 旧的架构、 采取链接库模块的观念进行

libhardware/ ‐ 新架构、调整为 HAL stub 的观念

旧的HAL 架构(libhardware_legacy)

libhardware_legacy 作法,是传统的「module」方式,也就是将 *.so 文件当做「shared library」来使用,在runtime(JNI 部份) 以 direct functioncall 使用 HAL module。通过直接调用函数的方式,来操作驱动程序。

当然,应用程序也可以不需要通过 JNI 的方式进行, 直接加载 .so 库(dlopen)的做法调用.so 里的符号(symbol)也是 一种方式。

总而言之是没有经过封装,上层可以直接操作硬件。

image-20200706134945797

image-20200706135452501

新的HAL 架构(libhardware)

现在的 libhardware 架构,就有「stub」的味道了。 HAL stub 是一种代理人(proxy) 的概念, stub 虽然仍是以 *.so的形式存在,但 HAL 已经将 *.so 隐藏起来了。 Stub 向 HAL「提供」 操作函数(operations) ,而 runtime 则是向 HAL 取得特定模块(stub)的 operations,再 callback这些操作函数。 这种以 indirect function call 的架构,让HAL stub 变成是一种「包含」关系,即 HAL 里包含了许许多多的 stub(代理人) 。Runtime 只要说明「类型」,即module ID,就可以取得操作函数。

对于目前的HAL, 可以认为Android定义了HAL层结构框架,通过几个接口访问硬件从而统一了调用方式。

image-20200706135547846

image-20200706135611185

HAL_legacy和HAL的对比

  • HAL_legacy:旧式的HAL是一个模块,采用共享库形式,在编译时会调用到。 由于采用 function call 形式调用,因此可被多个进程使用,但会被 mapping 到多个进程空间中, 同时需要考虑代码能否安全重入的问题(thread safe)。
  • HAL: 新式的HAL采用 HAL module 和 HAL stub 结合形式,HAL stub不是一个share library,编译时上层只拥有访问HAL stub的函数指针, 并不需要HAL stub。 上层通过HAL module提供的统一接口获取并操作HAL stub,so文件只会被mapping到一个进程, 也不存在重复mapping和重入问题。

HAL_legacy和HAL的对比

Module

角色是被调用 , 在Android架构里面仅作为程序库(library)用途

Stub

Stub又称为代理人(proxy) , 扮演操作供应者的概念(operations provider)

HAL_legacy和HAL的对比

HAL stub的框架比较简单: 三个结构体、 两个常量、 一个函数

它的定义在:

 hardware/libhardware/include/hardware/hardware.h
 hardware/libhardware/hardware.c  

HAL Stub架构分析

 /*
 每个一个HAL Stub都通过 hw_module_t 来描述, 我们称之为一个Stub对象。你可以去“ 继承 ”这个 hw_module_t,然后扩展自己的属性,这个HAL Stub对象必须定义为一个固定的名字:HMI( Hardware Module Information ) ,每一个Stub对象里都封装了一个函数open,通过这个函数来打开这个硬件Stub设备,返回这个硬件对应的Operation interface。
 */
 struct hw_module_t;
 /*
 HAL Stub对象的open描述结构体, 它里面只有一个元素: open函数指针
 */
 struct hw_module_methods_t;
 ​
 /*
 由结构体hw_module_t可知,它的open函数返回一个硬件对应的Operation interface, 这个硬件的operation interface的描述由hw_device_t 结构体来描述
 */
 struct hw_device_t;
 // 这个就是HAL Stub对象固定的名字
 #define HAL_MODULE_INFO_SYM HMI
 // 这个是以字符串的名字
 #define HAL_MODULE_INFO_SYM_AS_STR "HMI"
 //这个函数是通过硬件名来获得硬件HAL Stub对象
 int hw_get_module(const char *id, const struct hw_module_t **module);
 //注册一个Stub对象
 const struct led_modulet_HAL_MODULE_INFO_SYM = {
     common: {
     tag: HARDWARE_MODULE_TAG,
     version_major: 1,
     version_minor: 0,
     id: LED_HARDWARE_MODULE_ID,
     name: "led HAL Stub",
     author: "farsight",
     methods: &led_module_methods,
     },
     // 扩展属性放在这儿
 }

image-20200706135929366

image-20200706135949036

Android里的Jni调用机制

JVM 很好的解决java的可移植性问题,使得java软件可以在不同的硬件平台下运行,但是JVM不是万能的,毕竟它只是一个模拟环境,对于一些外围的硬件就很难模拟, JVM只是模拟了一部分的寄存器, 栈结构, JVM储存器,这些都是软件运行的基础硬件结构。

对于像android手机这样的平台, 有很多的外围设备在软件层是需要操作的,如wifi,蓝牙,触摸屏,重力感应,键盘等,如果直接通过java语言操作是很难实现的, JVM无法模拟这些硬件。

JNI( Java Native Interface ), 中文为JAVA本地调用。 从Java1.1开始,Java Native Interface( JNI )标准成为java平台的一部分,它允许Java代码 和 其他语言写的代码进行交互。 JNI一开始是为了本地已编译语言, 尤其是 C 和 C++ 而设计的,但是它并不妨碍你使用其他语言,只要调用约定受支持就可以了。使用 java 与本地已编译的代码交互,通常会丧失平台可移植性。

但是, 有些些情况下这样做是可以接受的, 甚至是必须的,比如, 使用一些旧的库,与硬件、操作系统进行交互,或者为了提高程序的性能。 JNI标准至少保证本地代码能工作在任何Java虚拟机实现下。

image-20200706140038704

Jni在 Java和C、 C++等语言之间建立了一个桥梁作用,因此, JNI首先要做的,就是统一两者间的数据类型。

所有其它引用类型,在JNI中都被定义为 jobject 类型,在C中都定义为 void*。

Java Language TypeJNI Type
booleanjboolean
bytejbyte
charjchar
shortjshort
intjint
longjlong
floatjfloat
doublejdouble

Java中可以直接调用底层语言的函数或方法, Jni规定了Java调用底层语言的方法签名规范。

类型签名Java 类型类型签名Java 类型
Zboolean[[]
Bbyte[Iint[]
Cchar[Ffloat[]
Sshort[Bbyte[]
Iint[Cchar[]
Jlong[Sshort[]
Ffloat[Ddouble[]
Ddouble[Jlong[]
Lfully-qualified-class(全限定的类)[Zboolean[]

Android里的Jni调用机制

  • 函数签名通常是以下结构: 返回值 fun(参数1,参数2,参数3) ;
  • 其对应的Jni方法签名格式为: (参数1参数2参数3)返回值
  • 注意:

函数名,在Jni中没有体现出来

参数列表相挨着, 中间没有逗号, 没有空格

返回值出现在()后面

如果参数是引用类型, 那么参数应该为: L类型;

HAL Led调用流程

/LedDemo/Led Service(java)/Led Service(Native)/Led HAL Stub1:创建服务对象<<create>>2:通过JNI初始化本地服务()3: 查找并得到HAL操作接口()4:返回device操作接口5:操作service提供的API()6: 通过JNI调用本地服务操作接口()7: 调用保存的devicer操作接口()8: 返回HAL操作结果9: 返回本地服务操作结果10: 返回框架服务操作结果/LedDemo/Led Service(java)/Led Service(Native)/Led HAL Stub
/Led APP/Led Service(java)/Led Service(Native)/Led HAL Stub1:new LedService()2:system.loadLibrary()3: JNI_OnLoad()注册java方法与本地函数的映射关系4: _init()5: hw_get_module()6: Return module_t object7: callback module_t open interface()8: Return device_t operations9: LedService.set_on/set_off()10: _set_on, _set_off()11: devict_t->set_on/set_off()/Led APP/Led Service(java)/Led Service(Native)/Led HAL Stub
Android Automotive OS架构 以 Car API 和 Car Service 为中枢,向上为应用提供统一接口,向下通过车辆 HAL 抽象车辆硬件,从而构建了一个既开放又安全、既能快速迭代又能满足汽车级要求的软件平台。这套架构的成功,关键在于它在谷歌的软件生态和汽车制造商的硬件控制之间找到了一个完美的平衡点。 阅读详情

相关推荐

嵌入式安卓驱动开发与系统优化技术详解

本文探讨了嵌入式安卓系统开发的关键技术,包括BSP开发、RTOS实现、外设驱动适配和系统优化。重点分析了嵌入式Linux和Android平台的底层开发流程,详细介绍了驱动开发、性能优化方法及软硬件联调策略。通过RK3568平台的充电桩开发案例,展示了安卓系统在嵌入式领域的实际应用。文章还提供了常见面试问题解答,涵盖BSP作用、FreeRTOS调度、启动优化等核心技术点。全文强调开发文档化和版本迭代的重要性,为嵌入式软件工程师提供了实用技术指南和面试准备参考。

郑伟强dev的专栏 128

Android底层技术:Java层系统服务(Android Service)

为什么我们需要学习撰写系统服务呢? 底层系统服务是Android 框架裡接近Linux/Driver 的部分。为了充分发挥硬件设备的差異化特性,系统服务是让上层Java 应用程序來使用Driver/HW Device 特色的重要管道。于此,先仔细解析Java层系统服务的架构,然后阐述这系统服务的代码开发要点,以及其API设计方法。

Android底层接口与驱动开发技术深度解析及实战代码

很多人以为AIDL只是个生成Stub/Proxy的工具,其实它的设计理念远不止于此。当你写下一行时,你实际上是在描述一种契约(Contract)——关于谁能调用、如何传参、怎样处理错误的明确约定。来看两个版本的传感器接口对比:一眼就能看出区别:AIDL更接近Java习惯,省去了generates这类关键字,使用标准集合类型如List<T>,并支持方向修饰符。更重要的是,AIDL允许在一个文件中定义多个Parcelable类,组织更加灵活。

weixin_30591519的博客 1271

Android底层开发

学习书籍:Android底层开发实践 使用代码:AOSP源码 带@的行表示关键点; 橙色背景的文字表示:整编log分析的关键字 绿色“待补充”文字表示:有待补充内容 -----第三章 Android系统开发环境搭建 3.1 Android上的开发工作 3.1.1 Android的移植开发 1. Linux驱动 @p47 @工作在系统内核空间 2. Android系统硬件抽象层 @p47 @工作在用户控件 ...

DreamWendy 7576

Android系统概述——底层开发的资料

Android系统概述——底层开发的资料 Android系统概述——底层开发的资料

免root实现 Android改机(一键新机)技术解密。

此篇文章仅探讨Android底层技术。不提供任何软件和安装包…… 我们通过一些底层技术对手机中的各种基础信息进行一个修改。 举例说明:主要修改的参数有: Android_Id、IMEI、手机序列号、手机号码、WIFI-MAC、WIFI-Name、安卓系统版本、ROM固件、手机号码、手机型号、手机品牌、CPU型号、手机制造商、GPS定位、通话记录模拟、手机短信模拟…… 等各类安卓手机系统信息的修改功能。 举例子:统改机方式,使用xposed的代码: HTool.XHookMethod(android.telephony.TelephonyManager.class.getName(),mLp

12月26日,唐攀网络直播讲解《Android手机底层软硬件结合开发技术》

唐攀 华清远见高级讲师,高级嵌入式软件工程师。从事多年知名外企嵌入式方向软件研发,拥有丰富的项目经验。擅长ARM体系结构及接口编程,Linux驱动开发,Linux下C语言编程,Android系统移植与优化,著有《深入浅出:嵌入式底层软件开发》等书籍,目前专注于嵌入式移动平台系统领域,参与社区医疗终端系统等多个移动应用项目,从事平板电脑移植与优化,智能家居系统等研发工作.有着丰富的高校师资培训和an

华清远见 | 程序员的学习天堂 2483

利用MobaXterm解密Session密码的实战指南

本文提供了利用MobaXterm解密Session密码的详细实战指南,帮助运维工程师和开发者在忘记密码时找回加密存储的远程连接信息。通过Python脚本和注册表操作,逐步解析MobaXterm的AES加密机制,实现密码解密,并分享安全建议和常见问题解决方案。

weixin_26759093的博客 232

西安嵌入式和Java哪个发展好?学好后都能做什么?

在西安嵌入式和Java有很大的区别,嵌入式是软硬结合的,底层开发用的大多是C语言和汇编语言,现在就业前景薪资待遇都很不错的。而JAVA的是纯软件的,现在市场也趋于饱和的状态,所以并没有什么发展的空间,薪资也不能和嵌入式相提并论。 学完嵌入式可以做以下三个方向: 1. ARM + Linux...

chufengjun5173的博客 642

U24时钟信号上升下降沿出现非单调性--简单分析

交换机U24时钟信号上升下降沿出现非单调性--简单分析

qq_45185504的博客 1132

Proteus下载安装快速入门:30分钟掌握全过程

手把手教你完成proteus下载安装,从环境配置到首次运行一气呵成,适合电子设计新手快速掌握仿真工具的核心操作步骤。

weixin_31974443的博客 895

Android手机底层软硬件

Android是 个开源的智能移动平台 一个开源的智能移动平台, 任何 个厂商拿 一个厂商拿到 Android Source 都可以基于自己的硬件架构设计移动设备。硬件多样化厂商自己的利益软硬件结合开发的弊端?失去了Android应用的跨平台特性由于不同厂商研发能力参差不齐,应用程序的稳定性及性能有所不同分类NDK开发:从应用角度来开发软硬结合代码适用于单个应用程序的底层结合需求HAL硬件抽象层开发:从整个系统框架需求角度来开发本地程序适用于共享功能软硬结合代码。

实力派,无需多言! 1526

FlinkCDC数据同步Bug——同步性能由于写入并行度限制无法提升问题的解决

使用FlinkCDC进行数据同步时,出现增量阶段写入并行度强制为1导致整体同步性能无法提升问题的解决方案

csdn_lan的博客 2081

项目总结之后的思考——小谈安卓应用

很久没有来这里再写一些技术或者相关的东西了!一直忙着赶项目,每天没日没夜的加班,成了我现在的习惯!我不怕日以夜继的做项目,就怕我的努力,没有换来最终的结果!在项目的制作中,我有时候也很想休息,设计的初衷,一改再改,已经快磨掉了我的性子,不过,这也我渐渐培养了我的耐心!对于项目上的疑难杂症,我已经不再像从前那样,没有思路的乱找解决方案!我也懂得了如何去做项目的计划,项目进度,项...

weixin_34406796的博客 84

从“能跑”到“好用”:一名 Python 开发者的工程化进阶之路【Python心得篇】

Python 早已不只是写脚本、跑数据的工具。后端服务AI Agent 编排层自动化平台核心语言数据与业务之间的“中枢层”区别只在于:你是用脚本方式,还是工程方式在写。如果你已经能写“能跑的 Python”,下一步,就是让它长期可跑、稳定可演进。Python 的真正价值不在于“写得快”,而在于能否支撑持续演进的工程实践。当代码从一次性脚本走向长期运行的系统,开发者必须从结构设计、职责拆分、性能意识和类型约束等方面进行系统性思考。

博客 1548

第3.4章 机器人第三方库实战总结(四):G2O优化库从入门到实战(附SLAM实例代码)

自定义边同样是满足复杂应用需求的重要手段。自定义边时,需要明确边所连接的顶点类型以及边所表示的误差项的计算方式。假设我们要定义一条边,用于约束两个上述自定义顶点之间的相对位姿和传感器偏移量关系。我们可以这样定义边类:public:// 计算误差// 计算雅可比矩阵// 读盘和存盘函数,这里暂不实现。

行知SLAM 362

Android开发的新挑战:从应用层到系统级的跨越

步入2024年,Android开发领域的生态悄然变化,不再单纯是应用开发数量的增减问题,而是对开发者能力层次提出了更高要求。市场需求并未减弱,反而在悄然转型——从大众化的应用开发转向对系统级、深层次技术能力的渴求。简而言之,不是需求减少了,而是门槛提高了,对开发者综合技能的要求达到了前所未有的高度。在Android开发的新纪元,行业对开发者的要求从量变走向质变,这既是对传统开发模式的挑战,也是技术进阶的必然趋势。

嘴巴吃糖了 1152

Steam崩溃:ntdll.dll报错0xc0000374...如何解决?

🏆本文收录于 《全栈 Bug 调优(实战版)》 专栏。专栏聚焦真实项目中的各类疑难 Bug,从成因剖析 → 排查路径 → 解决方案 → 预防优化全链路拆解,形成一套可复用、可沉淀的实战知识体系。无论你是初入职场的开发者,还是负责复杂项目的资深工程师,都可以在这里构建一套属于自己的「问题诊断与性能调优」方法论,助你稳步进阶、放大技术价值。

**My Coding Family** 1161

【Android】Android底层开发实战

本书分为四个部分:第一部分为预备知识篇,简要介绍嵌入式系统的定义与软硬件开发以及Android开发环境的搭建。第二部分为系统结构篇,主要介绍Android系统的源码结构、内核与相关工具以及环境库。第三部分为驱动设计篇,主要介绍Android系统中常用外接设备的驱动架构以及实现。内容包括NDK编程、Android中HAL模型架构与实现流程。作为教学实例,*后分析了Android系统中的...

firstxueba的博客 4069

彻底解析 DDIC_TYPE_INCONSISTENCY:从 ABAP ST22 连环 Dump 到 SE14 一键修复

听上去像内核级的致命故障,实则更多源于日常运维的细枝末节。只要掌握的排查三板斧,结合严格的变更流程与周期性的字典体检,再严重的 Dump 也能化险为夷。希望本文的案例与步骤能帮助读者在下一次遇到类似问题时,既能快速止血,也能追根溯源,避免重蹈覆辙。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 629

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

入门安卓开发!Android开发者出路在哪?面试建议

说白了,哪一个行业不是吃青春饭呢?无论哪个行业,大部分的从业人员都是在拿青春赌明天。 而且很残忍的一个事实是,没有人的工作是不可取代的,如果你辞职,老板极力挽留,那就说明,你是那帮取代你的候选人当中最便宜的。 市场在逐渐成熟,程序员的前景确实灰暗,算不上危言耸听。但是这种说法也算不上客观,因为大部分的行业都有这个特点。之所以没见其他行业的人跳出来说事,兴许恰恰说明程序员群体有着高度自省的能力。嗯,我就是要往自己脸上贴金。 另一方面,这也充分体现了程序员在互联网上造势的能力。比如去年Github上响彻海内外

196

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

安卓控制开源机械爪:软硬件协同开发与通信方案详解

嵌入式系统开发与机器人控制是物联网和智能硬件领域的核心技术,其核心在于实现软件与硬件的有效协同。通过通信协议(如蓝牙、Wi-Fi、USB)建立稳定可靠的数据链路,是确保指令精准传达与执行的基础。这项技术极大地降低了机器人应用的开发门槛,使得移动计算平台的强大算力与丰富传感器得以赋能传统机电设备。在创客教育、轻量级自动化及原型开发等场景中,这种软硬结合方案展现出巨大潜力。本文以安卓平台控制开源机械爪为例,深入剖析了从系统架构、通信选型到具体实现的完整路径,并重点探讨了蓝牙通信与安卓开发中的关键实践,为相关开发

weixin_42561249的博客 587

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

安卓手机可以连接斑马系统吗_斑马郝飞:我们一定能在车载系统上打败安卓

(观察者网讯 文/一鸣)“下一步我们还会更进一步在技术融资层面上开放,标签重要吗?”9月27日,在杭州云栖大会期间,当斑马网络CEO郝飞被问及是否担心斑马网络身上浓重的“阿里”标签,会影响其他互联网公司的产品入驻其平台时,他这样向观察者网回答。此前8月28日,在乌镇互联网大会上,上汽集团与阿里巴巴宣布达成深化战略合作协议。上汽集团总裁王晓秋和阿里云智能总裁张建锋签字确认双方战略重组斑马网络和Yun...

weixin_42114041的博客 1256

androidframework开发面试,安卓驱动工程师面试题

分享一份工作1到5年以上的Android程序员架构进阶学习路线体系,希望能对那些还在从事Android开发却还不知道如何去提升自己的,还处于迷茫的朋友!阿里P7级Android架构师技术脑图;查漏补缺,体系化深入学习提升**全套体系化高级架构视频;**七大主流技术模块,视频+源码+笔记有任何问题,欢迎广大网友一起来交流《互联网大厂面试真题解析、进阶开发核心学习笔记、全套讲解视频、实战项目源码讲义》点击传送门即可获取!战项目源码讲义》点击传送门即可获取!**

2401_84408404的博客 1133

嵌入式Linux屏与安卓屏怎么选?从底层逻辑到实战避坑指南

在工业HMI与智能终端领域,嵌入式Linux屏与安卓屏是两条截然不同的技术路线。嵌入式Linux基于专用系统设计,内核精简、进程少,具备秒级开机、长期稳定运行和工业级生命周期;而安卓屏依托通用操作系统,生态丰富、应用开发门槛低,但存在后台进程多、开机慢、系统更新风险等问题。理解两者在系统架构、资源分配与稳定性上的本质差异,是做好技术选型的前提。实际项目中,充电桩、医疗设备、数控机床等强调实时性与可靠性的场景更适用嵌入式Linux,而商业广告机、自助终端等需频繁迭代与第三方SDK的场景则安卓更具优势。本文结合

diaoju3333的博客 464

android面试宝典!这个回答让我错失offer!offer拿到手软_安卓面试宝典

最近两部剧爆火,30而已,20不惑,其实刚刚开始看这个2个电视剧我在想是不是说反了。不是应该29而已,30不惑吗?后面想想其实他应该是想告诉我们这个残酷的现实吧!在这个时代我们20 岁就必须成熟,接受这个世界的残酷,没有时间给我们不惑的时间,世界总是这样逼着我们成长。而30而已更好的是对未来的一种美好愿望吧!30岁在哪里吃早餐决定了,你前面十年奋斗的痕迹,曼妮路边摊,晓芹的温馨幸福,顾佳的豪华早餐。

2401_87022248的博客 1243
上一篇: 智能指针详解及示例代码--看了就懂
下一篇: Linux驱动开发
onnx
博客等级 码龄5年 1万+粉丝 416原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

onnx

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值