【腾讯Bugly干货分享】微信Tinker的一切都在这里,包括源码(一)

最新微信Tinker 热修复平台接入教程(超详细) 目录 Tinker接入文档 1 Tinker简介 1.1Tinker优点 1.2 Tinker缺点 2 Tinker 接入过程 2.1 配置过程 2.2 使用过程 2.3 注意事项 Tinker接入文档 1 Tinker简介 1.1Tinker优点 1.2 Tinker缺点 1.Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件(... 阅读详情

本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57ecdf2d98250b4631ae034b

最近半年以来,Android热补丁技术热潮继续爆发,各大公司相继推出自己的开源框架。Tinker在最近也顺利完成了公司的审核,并非常荣幸的成为github.com/Tencent上第一个正式公开的项目。

回顾这半年多的历程,这是一条跪着走完,坑坑不息之路。或许只有自己真正经历过,深入研究过, 才会真正的明白

热补丁不是请客吃饭

对热补丁技术本身,还是对使用者来说都是如此。它并不简单,也有着自己的局限性,在使用之前我们需要对它有所了解。我希望通过分享微信在这历程中的思考与经验,能帮助大家更容易的决定是否在自己的项目中使用热补丁技术,以及选择什么样方案。

热补丁技术背景

热补丁是什么以及它的应用场景介绍,大家可以参考文章微信Android热补丁实践演进之路。

在笔者看来Android热补丁技术应该分为以下两个流派:

  • Native,代表有阿里的Dexposed、AndFix与腾讯的内部方案KKFix;
  • Java, 代表有Qzone的超级补丁、大众点评的nuwa、百度金融的rocooFix, 饿了么的amigo以及美团的robust。

Native流派与Java流派都有着自己的优缺点,它们具体差异大家可参考上文。事实上从来都没有最好的方案,只有最适合自己的。

对于微信来说,我们希望得到一个“高可用”的补丁框架,它应该满足以下几个条件:

  1. 稳定性与兼容性;微信需要在数亿台设备上运行,即使补丁框架带来1%的异常,也将影响到数万用户。保证补丁框架的稳定性与兼容性是我们的第一要务;
  2. 性能;微信对性能要求也非常苛刻,首先补丁框架不能影响应用的性能,这里基于大部分情况下用户不会使用到补丁。其次补丁包应该尽量少,这关系到用户流量与补丁的成功率问题;
  3. 易用性;在解决完以上两个核心问题的前提下,我们希望补丁框架简单易用,并且可以全面支持,甚至可以做到功能发布级别。

在“高可用”这个大前提下,微信对当时存在的两个方案做了大量的研究:

  1. Dexposed/AndFix;最大挑战在于稳定性与兼容性,而且native异常排查难度更高。另一方面,由于无法增加变量与类等限制,无法做到功能发布级别;
  2. Qzone;最大挑战在于性能,即Dalvik平台存在插桩导致的性能损耗,Art平台由于地址偏移问题导致补丁包可能过大的问题;

在2016年3月,微信为了追寻“高可用”这个目标,决定尝试搭建自己的补丁框架——Tinker。Tinker框架的演绎并不是一蹴而就,它大致分为三个阶段,每一阶段需要解决的核心问题并不相同。而Tinker v1.0的核心问题是实现符合性能要求的Dex补丁框架。

Tinker v1.0-性能极致追求之路

为了稳定性与兼容性,微信选择了Java流派。当前最大难点在于如何突破Qzone方案的性能问题,这时通过研究Instant Run的冷插拔与buck的exopackage给了我们灵感。它们的思想都是全量替换新的Dex。

简单来说,我们通过完全使用了新的Dex,那样既不出现Art地址错乱的问题,在Dalvik也无须插桩。当然考虑到补丁包的体积,我们不能直接将新的Dex放在里面。但我们可以将新旧两个Dex的差异放到补丁包中,这里我们可以调研的方法有以下几个:

  1. BsDiff;它格式无关,但对Dex效果不是特别好,而且非常不稳定。当前微信对于so与部分资源,依然使用bsdiff算法;
  2. DexMerge;它主要问题在于合成时内存占用过大,一个12M的dex,峰值内存可能达到70多M;
  3. DexDiff;通过深入Dex格式,实现一套diff差异小,内存占用少以及支持增删改的算法。

如何选择?在“高可用”的核心诉求下,性能问题也尤为重要。非常庆幸微信在当时那个节点坚决的选择了自研DexDiff算法,这过程虽然有苦有泪,但也正是有它,才有现在的Tinker。

一. DexDiff技术实践

在不断的深入研究[Dex格式](https://source.android.com/devices/tech/dalvik/dex-format.html
)后,我们发现自己跳进了一个深坑,主要难点有以下三个:

  1. Dex格式复杂;Dex大致分为像StringID,TypeID这些Index区域以及使用Offset的Data区域。它们有大量的互相引用,一个小小的改变可能导致大量的Index与Offset变化;
  2. dex2opt与dex2oat校验;在这两个过程系统会做例如四字节对齐,部分元素排序等校验,例如StringID按照内容的Unicode排序,TypeID按照StringID排序…
  3. 低内存,快速;这要求我们对Dex每一块做到一次读写,无法像baksmali与dexmerge那样完全结构化。

这不仅要求我们需要研究透Dex的格式,也要把dex2opt与dex2oat的代码全部研究透。现在回想起来,这的确是一条跪着走完的路。与研究Dalvik与Art执行一致,这是经历一次次翻看源码,一次次编Rom查看日志,一次次dump内存结构换来的结果。

下面以最简单的Index区域举例:

要想将从左边序列更改成右边序列,Diff算法的核心在于如何生成最小操作序列,同时修正Index与Offset,实现增删改的功能。

  1. Del 2;”b”元素被删除,它对应的Index是2,为了减少补丁包体积,除了新增的元素其他一律只存Index;
  2. “c”, “d”, “e”元素自动前移,无须操作;
  3. Addf(5); 在第五个位置增加”f”这个元素。

对于Offset区,由于每个Section可能有非常多的元素,这里会更加复杂。最后我们得到最终的操作队列,为什么DexDiff可以做到内存非常少?这是因为DexDiff算法是每一个操作的处理,它无需一次性读入所有的数据。DexDiff的各项数据如下:

通过DexDiff算法的实现,我们既解决了Dalvik平台的性能损耗问题,又解决了Art平台补丁包过大的问题。但这套方案的缺点在于占Rom体积比较大,微信考虑到移动设备的存储空间提升比较快,增加几十M的Rom空间这个代价可以接受。

二. Android N的挑战

信心满满上线后,却很快收到华为反馈的一个Crash:

而且这个Crash只在Android N上出现,在当时对我们震动非常大,难道Android N不支持Java方式热补丁了?难道这两个月的辛苦都白费了吗?一切想象都苍白无力,只有继续去源码里面找原因。

在之前的基础上,这一块的研究并没有花太多的时间,主要是Android N的混合编译模式导致。更多的详细分析可参考文章Android N混合编译与对热补丁影响解析。

三. 厂商OTA的挑战

刚刚解决完Android N的问题,还在沉醉在自己的胜利的愉悦中。前线很快又传来噩耗,小米反馈开发版的一些用户在微信启动时黑屏,甚至ANR.

当时第一反应是不可能,所有的DexOpt操作都是放到单独的进程,为什么只在Art平台出现?为什么小米开发版用户反馈比较多?经过分析,我们发现优化后odex文件存在有效性的检查:

  • Dalvik平台:modtime/crc…
  • Art平台: checksum/image_checksum/image_offset…

这就非常好理解了,因为OTA之后系统image改变了,odex文件用到image的偏移地址很可能已经错误。对于ClassN.dex文件,在OTA升级系统已完成重新dex2oat,而补丁是动态加载的,只能在第一次执行时同步执行。

这个耗时可能高达十几秒,黑屏甚至ANR也是非常好理解。那为什么只有小米用户反馈比较多呢?这也是因为小米开发版每周都会推送系统升级的原因。

在当时那个节点上,我们重新的审视了全量合成这一思路,再次对方案原理本身产生怀疑,它在Art平台上面带来了以下几个代价:

  1. OTA后黑屏问题;这里或许可以通过lLoading界面实现,但并不是很好的方案;
  2. Rom体积问题;一个10M的Dex,在Dalvik下odex产物只有11M左右,但在Art平台,可以达到30多M;
  3. Android N的问题;Android N在混合编译上努力,被补丁全量合成机制所废弃了。这是因为动态加载的Dex,依然是全量编译。

回想起来,Qzone方案它只把需要的类打包成补丁推送,在Art平台上可能导致补丁很大,但它肯定比全量合成10M的Dex少很多很多。在此我们提出分平台合成的想法,即在Dalvik平台合成全量Dex,在Art平台合成需要的Dex

DexDiff算法已经非常复杂,事实上要实现分平台合成并不容易。

主要难点有以下几个方面:

  • small dex的类收集;什么类应该放在这个小的Dex中呢?
  • ClassN处理;对于ClassN怎么样处理,可能出现类从一个Dex移动到另外一个Dex?
  • 偏移二次修正; 补丁包中的操作序列如何二次修正?
  • Art.info的大小; 为了修正偏移所引入的info文件的大小?

庆幸的是,面对困难我们并没有畏惧,最后实现了这一套方案,这也是其他全量合成方案所不能做到的:

  1. Dalvik全量合成,解决了插桩带来的性能损耗;
  2. Art平台合成small dex,解决了全量合成方案占用Rom体积大, OTA升级以及Android N的问题;
  3. 大部分情况下Art.info仅仅1-20K, 解决由于补丁包可能过大的问题;

事实上,DexDiff算法变的如此复杂,怎么样保证它的正确性呢?微信为此做了以下三件事情:

  1. 随机组成Dex校验,覆盖大部分case;
  2. 微信200个版本的随机Diff校验, 覆盖日常使用情况;
  3. Dex文件合成产物有效性校验,即使算法出现问题,也只是编译不出补丁包。

每一次DexDiff算法的更新,都需要经过以上三个Test才可以提交,这样DexDiff的这套算法已完成了整个闭环。

四. 其他技术挑战

在实现过程,我们还发现其他的一些问题:

  1. Xposed等微信插件; 市面上有各种各样的微信插件,它们在微信启动前会提前加载微信中的类,这会导致两个问题:

    a. Dalvik平台:出现Class ref in pre-verified class resolved to unexpected implementation的crash;

    b. Art平台:出现部分类使用了旧的代码,这可能导致补丁无效,或者地址错乱的问题。

    微信在这里的处理方式是若crash时发现安装了Xposed,即清除并不再应用补丁。

    1. Dex反射成功但是不生效;部分三星android-19版本存在Dex反射成功,但出现类重复时,查找顺序始终从base.apk开始。
      微信在这里的处理方式是增加Dex反射成功校验,具体通过在框架中埋入某个类的isPatch变量为false。在补丁时,我们自动将这个变量改为true。通过这个变量最终的数值,我们可以知道反射成功与否。

Tinker v1.0总结

一. 关于性能

通过Tinker v1,0的努力,我们解决了Qzone方案的性能问题,得到一个符合“高可用”性能要求的补丁框架。

  • 它补丁包大小非常少,通常都是10k以内;
  • 对性能几乎没有影响, 2%的性能影响主要原因是微信运行时校验补丁Dex文件的md5导致(虽然文件在/data/data/目录,微信为了更高级别的安全);
  • Art平台通过革命性的分平台合成,既解决了地址偏移的问题,占Rom体积与Qzone方案一致。

二. 关于成功率

也许有人会质疑微信成功率为什么这么低,其他方案都是99%以上。事实上,我们的成功率计算方式是:

应用成功率= 补丁版本转化人数/基准版本安装人数

即三天后,94.1%的基础版本都成功升级到补丁版本,由于基础版本人数也是持续增长,同时可能存在基准或补丁版本用户安装了其他版本,所以本统计结果应略为偏低,但它能现实的反应补丁的线上总体覆盖情况。

事实上,采用Qzone方案,3天的成功率大约为96.3%,这里还是有很多的优化空间。

三. Tinker v2.0-稳定性的探寻之路

在v1.0阶段,大部分的异常都是通过厂商反馈而来,Tinker并没有解决“高可用”下最核心的稳定性与兼容性问题。我们需要建立完整的监控与补丁回退机制,监控每一个阶段的异常情况。这也是Tinker v2.0的核心任务,由于边幅问题这部分内容将放在下一篇文章。


关注Tinker,来Github给我们star吧

https://github.com/Tencent/tinker

更多精彩内容欢迎关注bugly的微信公众账号:

腾讯 Bugly是一款专为移动开发者打造的质量监控工具,帮助开发者快速,便捷的定位线上应用崩溃的情况以及解决方案。智能合并功能帮助开发同学把每天上报的数千条 Crash 根据根因合并分类,每日日报会列出影响用户数最多的崩溃,精准定位功能帮助开发同学定位到出问题的代码行,实时上报可以在发布后快速的了解应用的质量情况,适配最新的 iOS, Android 官方操作系统,鹅厂的工程师都在使用,快来加入我们吧!

微信tinker导致冷启动变慢的问题优化 微信tinker导致冷启动变慢的问题优化1. Android S用户反馈微信启动慢2. 抓取微信systrace查看一下3. tinker对冷启动时间的影响4. 修改方案5. Open Dex是什么时候触发的?其中传入的location又是那里来的?6. 断点看一下带tinker和不带tinker的ClassLoader7. 微信内部tinker加载的流程8. 优化tinker导致启动慢的方案 1. Android S用户反馈微信启动慢 首先第一个想到的就是dex的状态问题 是否有进行oat dex(例如 阅读详情

相关推荐

微信Tinker热修复集成测试完整Demo

随着Android应用的复杂度不断提升,线上Bug的修复变得愈发重要。传统的修复方式需要用户重新下载安装新版本,这不仅影响用户体验,也增加了运维成本。为了解决这一问题,热修复技术应运而生。微信团队推出的Tinker框架,是业界较为成熟的一种全量热修复方案,它支持类、资源文件(res)、Android资源目录(assets)以及原生库(so)的动态替换,从而实现不重新发版即可修复线上问题。

weixin_28787801的博客 870

Android开发者峰会:微信 Tinker 热补丁实践演进之路

Tinker 是微信 Android 团队推出的开源热补丁框架,它可以帮助应用获得动态更新能力。本次分享首先介绍 Tinker 项目的演进历程,重点分析我们在开发过程中遇到的问题以及解决方案。然后剖析 Tinker 框架的核心架构设计,讲述 Tinker 是如何保证一致性、安全性、稳定性、高性能等关键问题。后结合热补丁在微信的应用与实践,分享如何使用 Tinker 动态部署。

微信Android热更新Tinker使用详解(星空武哥)

Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。当然,你也可以使用Tinker来更新你的插件

微信热修复框架Tinker集成和使用,爬了很多坑后。带你成功跑通项目!

前言:在你上线项目的时候,出现一个小的代码bug,或者遇到节假日时需要有节假日活动,增加用户体验了。除了重新打包发布之外,此时热更新,热修复技术应运而生。虽然google是严令禁用包括苹果。但是在android方面却风生水起。 网上很多文章都写的非常好,但是比较古老。你会发现,你项目根本生成不了补丁apk。这也是这篇文章踩过了很多坑以后,才决定写。所以这篇文章不会介绍的非常细,直接上干货。建议先...

岩浆李的游鱼 2139

别再乱设阻尼了!Abaqus动力分析中瑞利阻尼的α和β到底怎么算?

本文深入解析Abaqus动力分析中瑞利阻尼参数α和β的科学计算方法,帮助工程师准确设置阻尼参数以提升仿真精度。详细介绍了基于模态阻尼比的经典计算方法和多模态优化法,并结合工程案例演示参数设置流程,避免常见的阻尼设置误区。

weixin_42634811的博客 731

PCB设计必看:铜皮厚度与载流能力对照表(附Excel计算工具)

本文深入解析了PCB设计中铜皮厚度与载流能力的核心关系,提供了基于IPC-2152标准的动态计算逻辑与实用Excel工具。文章不仅分享了载流对照表,更重点剖析了影响载流能力的关键因素(如铜厚、线宽、温升、布线层),并给出了高电流设计的实战技巧与测试验证方法,帮助工程师规避常见陷阱,实现从理论到实践的闭环设计。

weixin_29228781的博客 724

Tinker热更新(微信)详细教程

Tinker热更新(微信)详细教程 现在热更新有很多的选择,但是有很多都有限制,例如不能更新资源文件,不支持android7.0等,经过多种尝试,发现tinker是支持面最广的热更新插件了。 Tinker官方GitHub Tinker和其他常见热更新特点对比 Tinker 执行原理分析 个人观点,不知道是否正确 在原项目中集成tinker的plugin,这时会生成old.a...

哈格咂丶 5385

Vivado 2018.3 安装步骤及 license 获取

本文的主要内容是介绍 Vivado 2018.3 版本的安装步骤及其 license 的获取与加载。

西岸贤 4万+

微信Tinker的一切都在这里,包括源码(一)

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34247299的博客 274

CentOS 7 Linux yum 安装 Docker,解决 Docker 镜像拉取失败问题

本文详细介绍了在 CentOS 7 系统上通过 yum 安装 Docker 的完整流程,包括卸载旧版本、配置阿里云国内镜像源、安装 Docker 及其组件、设置日志限制等关键步骤。针对国内用户常见的 Docker 镜像拉取失败问题,提供了两种实用解决方案:配置镜像加速器或通过代理访问官方源,并附带验证方法与排错指南,帮助读者高效完成 Docker 环境部署。

寒水馨 · 轻量级技术文档 · hanshuixin.org 1718

Android Telephony主要模块及功能

Telephony的代码主要由五个模块组成 1.Telephony Frameworks 代码区域: frameworks/opt/telephony/ 其中主要的文件在如下目录 /frameworks/opt/telephony/src/java/com/android/internal/telephony/ 其中比较常见的有以下几类文件 1.BaseCommands、RIL构成R

泊客 7723

【腾讯Bugly干货分享】微信热补丁Tinker的实践演进之路

为什么80%的码农都做不了架构师?>>> ...

weixin_33948416的博客 142

高通开发系列 - Bootloader之lk匹配dtb和dtbo中msm-id和board-id的知识

lk匹配dtb和dtbo中的msm-id和board-id等知识

fulinux的博客 4246

微信热修复tinker初探

前言 Tinker简介 Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。当然,你也可以使用Tinker来更新你的插件。 Tinker已知问题 1) Tinker不支持修改AndroidManifest.xml,Tinker不支持新增四大组件; 2) 由于Google Play的开发者条款限制,不建议在GP...

taowuhua的博客 500

【首发独家】华为OD机试 - 服务中心选址、服务中心的最佳位置(C 语言解题)

最近更新的博客 华为 od 2023 | 什么是华为 od,od 薪资待遇,od 机试题清单 华为 OD 机试真题大全,用 Python 解华为机试题 | 机试宝典 【华为 OD 机试】全流程解析+经验分享,题型分享,防作弊指南 华为 od 机试,独家整理 已参加机试人员的实战技巧 本篇华为 OD 机试题解:服务中心选址、服务中心的最佳位置

梦想橡皮擦,专栏100例写作模式先行者,现象级专栏 《Python 爬虫 100 例》作者、《滚雪球学 Python 专栏》原创者 1万+

控制科学与工程(自动化)保研经验【4】——浙大篇

控制科学与工程(自动化)保研经验【4】——浙大篇

Control Everything 1万+

Android热修复-微信Tinker

作者:邓浩宸 11/9/2016 1:13:49 PM Android的热修复前言:随着时代的发展,由于公司的项目需要去求变化平凡计划总赶不上变化,H5的高灵活性,开发周期短,更新速度快H5以及一些混合开发越来越被看好,然而主要原因之一:这种混合开发的方式容错率大,更新和修复BUG快.不用发布版本就可以让用户不觉的情况下就更新对应的内容或者BUG,我们不能否认混合开发的快捷,正在此前提下热修复和热

chengzichen_的博客 7174

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

Android 热修复 Tinker接入及源码浅析,2024阿里手淘Android面试题目

我坚信,坚持学习,每天进步一点,滴水穿石,我们离成功都很近!以下是总结出来的字节经典面试题目,包含:计算机网络,Kotlin,数据结构与算法,Framework源码,微信小程序,NDK音视频开发,计算机网络等。字节高级Android经典面试题和答案自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。深知大多数Android工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。

2401_84023604的博客 967

Outlook Express 6 (OE6) for Win7/Win8/Win10

英文版 Outlook Express6.0, 兼容Win7/Win10/WinXP,解压就可用。

efm32 入门.pdf

本PDF共计22页,介绍的是操作驱动API,下载与否自己斟酌。

微信Android热补丁方案Tinker

微信Android热补丁方案Tinker

搬砖 1602

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

微信Tinker在Android中集成以及使用

Tinker项目(点击进入) Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码。.so库以及资源库,让应用能够在不需要重复安装的情况下实现更新,当然也可以使用Tinker来更新你的插件。 在接入Tinker之前我们先对Tinker的结构了解一下Tinker主要包括一下几个部分: 1.gradle编译插件:tinker-patch-gradle-plugin。 2

秦川小将 778

微信Tinker热更新集成文档

微信Tinker热更新方案骆阳2016-11-11一、微信Tinker热更新简介1、github地址: https://github.com/Tencent/tinker 2、Tinker原理: http://mp.weixin.qq.com/s?__biz=MzAwNDY1ODY2OQ==&mid=2649286306&idx=1&sn=d6b2865e033a99de60b2d4314c6e0a

charles674611395的专栏 4610

Android 热更新技术实现方案-Tinker

Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。Tinker 官网地址:https://github.com/Tencent/tinker市面上的热修复工具很多,比较流行的无非有阿里的AndFix、美团的Robust以及QZone的超级补丁方案。但它们都存在无法解决的问题。他们具体的对比如下:通过以上对比和实际情况,选择了Tinker。特别是在Android N之后,由于混合编译的inline策略修改,对于市面上的各种方案

随时分享高质量技术文章 3189

【Android】微信热修复 Tinker 的集成和使用

简介Tinker: n. 〈英〉小炉匠,补锅匠,修补匠Tinker 是微信官方开源的 Android 热修复框架,支持在无需升级APK的前提下更新 dex, library and resources 文件。它也就是今年9月24才刚刚开源,几天功夫star数就超过3000,可见在开发者中的影响力有多大,也说明这是一个刚需。Tinker GitHub: https://github.com/Ten

Mlib 3608

微信 Tinker 在 Android 中集成以及使用

作者 | 秦川小将 地址 | http://www.jianshu.com/p/d50817b6d622 声明 | 本文是 秦川小将 原创,已获授权发布,未经原作者允许请勿转载 Tinker 简介 Tinker 是微信官方的 Android 热补丁解决方案,它支持动态下发代码。.so 库以及资源库,让应用能够在不需要重复安装的情况下实现更新,当然也可以使用 Tinker 来

code小生 788
上一篇: 【腾讯Bugly干货分享】iOS10 SiriKit QQ适配详解
下一篇: 【腾讯Bugly干货分享】聊一聊微信“小程序”
腾讯Bugly
博客等级 码龄12年 1875粉丝 201原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值