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

2023-11-21 07:59

本文主要是介绍Tinker热更新(微信)详细教程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

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

现在热更新有很多的选择,但是有很多都有限制,例如不能更新资源文件,不支持android7.0等,经过多种尝试,发现tinker是支持面最广的热更新插件了。
Tinker官方GitHub

Tinker和其他常见热更新特点对比

Tinker 执行原理分析

个人观点,不知道是否正确
在原项目中集成tinker的plugin,这时会生成old.apk oldresource-R.txt文件及old-mapping.txt(如果开启混淆才会有)
项目bug修复后,配置oldapk,resource,mapping文件,会对比生成一个patch文件,这个文件后缀名默认是apk,但不是一个可以安装的apk,可以根据自己的情况任意修改后缀名,把这个patch文件放到服务端,如果app需要修复bug则下载这个patch,然后执行后就会成修复后的app了

Tinker集成过程

  • 1.项目project gradle引入
dependencies {classpath 'com.android.tools.build:gradle:2.0.0'//引入tinker plugin 版本可以参考tinker官方githubclasspath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.7.7')       }
  • 2.Moudle app gradle引入library
dependencies {compile 'com.android.support:appcompat-v7:23.2.1'compile 'com.android.support:support-v4:23+'debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5'releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5'//Tinker需要的library开始//可选,用于生成application类provided('com.tencent.tinker:tinker-android-anno:1.7.7')//tinker的核心库compile('com.tencent.tinker:tinker-android-lib:1.7.7')compile "com.android.support:multidex:1.0.1"//Tinker需要的library结束
}
  • 3.设置app的build.gradle

a,如果设置了dex分包则在android节点下的defaultConfig设置

  multiDexEnabled true

b,在app的build.gradle的末尾设置tinker的配置

以下内容很重要,请仔细看,或者直接复制进去后自己根据情况修改

/**Tinker 相关配置----------------开始-----------------------------------*/
//apply tinker插件
apply plugin: 'com.tencent.tinker.patch'
def bakPath = file("${buildDir}/bakApk/")
//这个函数返回的是tinkerid
//tinkerid是用来做代码更改对比的,
//例如 
//线上的是1.0版本
//则这里配置的oldapk 路径就是线上的apk在本地的路径
//如果要在这个版本上更新,则这里返回的string应该与线上版本设置的一模一样
def gitSha() {return "1.0"
}
ext {//for some reason, you may want to ignore tinkerBuild, such as instant run debug build?//变量,控制Tinker是否可用tinkerEnabled = true//for normal build//old apk file to build patch apk 旧包名//这里对应的路径就是app moudle下的oldApk路径(没有则自己新建),并且把需要修复版本的apk放进去tinkerOldApkPath = "${projectDir}/oldApk/old.apk"//proguard mapping file to build patch apk  旧包混淆文件目录//tinkerApplyMappingPath = "${bakPath}/app-debug-1018-17-32-47-mapping.txt"//混淆的mapping 有则配置路径,我这里没有,所以随便写tinkerApplyMappingPath = "${bakPath}/"//resource R.txt to build patch apk, must input if there is resource changed 旧包R文件//跟待修复版本apk一样,把老版本的resoures-r.txt放进来//这个是为了避免新旧版本R不一致,导致找不到资源闪退tinkerApplyResourcePath = "${projectDir}/oldApk/old-R.txt"//only use for build all flavor, if not, just ignore this field  多渠道//tinkerBuildFlavorDirectory = "${bakPath}/app-1018-17-32-47"
}
def getOldApkPath() {return  ext.tinkerOldApkPath
}
def getApplyMappingPath() {return  ext.tinkerApplyMappingPath
}
def getApplyResourceMappingPath() {return  ext.tinkerApplyResourcePath
}
def getTinkerIdValue() {return  gitSha()
}
def buildWithTinker() {return  ext.tinkerEnabled
}
def getTinkerBuildFlavorDirectory() {return ext.tinkerBuildFlavorDirectory
}
if (buildWithTinker()) {apply plugin: 'com.tencent.tinker.patch'tinkerPatch {/*** 基准apk包路径,也就是旧包路径* */oldApk = getOldApkPath()/*** 如果出现以下的情况,并且ignoreWarning为false,我们将中断编译。因为这些情况可能会导致编译出来的patch包* 带来风险:* 1. minSdkVersion小于14,但是dexMode的值为"raw";* 2. 新编译的安装包出现新增的四大组件(Activity, BroadcastReceiver...);* 3. 定义在dex.loader用于加载补丁的类不在main dex中;* 4. 定义在dex.loader用于加载补丁的类出现修改;* 5. resources.arsc改变,但没有使用applyResourceMapping编译。* */ignoreWarning = false/*** 在运行过程中,我们需要验证基准apk包与补丁包的签名是否一致,我们是否需要为你签名* */useSign = truebuildConfig {/*** 可选参数;在编译新的apk时候,我们希望通过保持旧apk的proguard混淆方式,从而减少补丁包的大小。这个只* 是推荐的,但设置applyMapping会影响任何的assemble编译。* */applyMapping = getApplyMappingPath()/*** 可选参数;在编译新的apk时候,我们希望通过旧apk的R.txt文件保持ResId的分配,这样不仅可以减少补丁包的* 大小,同时也避免由于ResId改变导致remote view异常。* */applyResourceMapping = getApplyResourceMappingPath()/*** 在运行过程中,我们需要验证基准apk包的tinkerId是否等于补丁包的tinkerId。这个是决定补丁包能运行在哪些* 基准包上面,一般来说我们可以使用git版本号、versionName等等。* */tinkerId = getTinkerIdValue()}dex {/*** optional,default 'jar'* only can be 'raw' or 'jar'. for raw, we would keep its original format* for jar, we would repack dexes with zip format.* if you want to support below 14, you must use jar* or you want to save rom or check quicker, you can use raw mode also*/dexMode = "jar"/*** necessary,default '[]'* what dexes in apk are expected to deal with tinkerPatch* it support * or ? pattern.*/pattern = ["classes*.dex","assets/secondary-dex-?.jar"]/*** necessary,default '[]'* Warning, it is very very important, loader classes can't change with patch.* thus, they will be removed from patch dexes.* you must put the following class into main dex.* Simply, you should add your own application {@code tinker.sample.android.SampleApplication}* own tinkerLoader, and the classes you use in them**///这个里面是设置你不希望更改的类,一般可以设置一些永远不会变的类,也可以不写loader = [//use sample, let BaseBuildInfo unchangeable with tinker"com.ubestkid.BlApplication","com.ubestkid.foundation.base.BaseApplication"]}lib {/*** 需要处理lib路径,支持*、?通配符,必须使用'/'分割。与dex.pattern一致, 路径是相对安装包的,例如/assets/...*/pattern = ["lib/armeabi/*.so"]}res {/*** 需要处理res路径,支持*、?通配符,必须使用'/'分割。与dex.pattern一致, 路径是相对安装包的,例如/assets/...,* 务必注意的是,只有满足pattern的资源才会放到合成后的资源包。*/pattern = ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]/*** 支持*、?通配符,必须使用'/'分割。若满足ignoreChange的pattern,在编译时会忽略该文件的新增、删除与修改。* 最极端的情况,ignoreChange与上面的pattern一致,即会完全忽略所有资源的修改。*/ignoreChange = ["assets/sample_meta.txt"]/*** 对于修改的资源,如果大于largeModSize,我们将使用bsdiff算法。这可以降低补丁包的大小,但是会增加合成* 时的复杂度。默认大小为100kb*/largeModSize = 100}packageConfig {/*** configField("key", "value"), 默认我们自动从基准安装包与新安装包的Manifest中读取tinkerId,并自动* 写入configField。在这里,你可以定义其他的信息,在运行时可以通过TinkerLoadResult.getPackageConfigByName得到相应的数值。但是建议直接通过修改代码来实现,例如BuildConfig。*/configField("patchMessage", "tinker is sample to use")}sevenZip {/*** 例如"com.tencent.mm:SevenZip:1.1.10",将自动根据机器属性获得对应的7za运行文件,推荐使用*/zipArtifact = "com.tencent.mm:SevenZip:1.1.10"}/***  文件名                              描述*  patch_unsigned.apk                  没有签名的补丁包*  patch_signed.apk                  签名后的补丁包*  patch_signed_7zip.apk              签名后并使用7zip压缩的补丁包,也是我们通常使用的补丁包。但正式发布的时候,最好不要以.apk结尾,防止被运营商挟持。*  log.txt                              在编译补丁包过程的控制台日志*  dex_log.txt                          在编译补丁包过程关于dex的日志*  so_log.txt                          在编译补丁包过程关于lib的日志*  tinker_result                      最终在补丁包的内容,包括diff的dex、lib以及assets下面的meta文件*  resources_out.zip                  最终在手机上合成的全量资源apk,你可以在这里查看是否有文件遗漏*  resources_out_7z.zip              根据7zip最终在手机上合成的全量资源apk*  tempPatchedDexes                  在Dalvik与Art平台,最终在手机上合成的完整Dex,我们可以在这里查看dex合成的产物。*** *//*** bak apk and mapping*  创建Task并执行文件操作*/android.applicationVariants.all { variant ->/*** task type, you want to bak*/def taskName = variant.namedef date = new Date().format("MMdd-HH-mm-ss")tasks.all {if ("assemble${taskName.capitalize()}".equalsIgnoreCase(it.name)) {it.doLast {copy {def fileNamePrefix = "${project.name}-${variant.baseName}"def newFileNamePrefix = "${fileNamePrefix}-${date}"def destPath = bakPathfrom variant.outputs.outputFileinto destPathrename { String fileName ->fileName.replace("${fileNamePrefix}.apk", "${newFileNamePrefix}.apk")}from "${buildDir}/outputs/mapping/${variant.dirName}/mapping.txt"into destPathrename { String fileName ->fileName.replace("mapping.txt", "${newFileNamePrefix}-mapping.txt")}from "${buildDir}/intermediates/symbols/${variant.dirName}/R.txt"into destPathrename { String fileName ->fileName.replace("R.txt", "${newFileNamePrefix}-R.txt")}}}}}}}
}
/**Tinker 相关配置----------------结束-----------------------------------*/

-4.设置application

新建一个类继承DefaultApplicationLike
注意,这个并不是继承原生的application,也不是application的子类
里面有提供getApplication则是真正的application
初始化的一些代码可以写在onBaseContextAttached这个方法里面

@SuppressWarnings("unused")
@DefaultLifeCycle(application = "tinker.sample.android.app.SampleApplication",flags = ShareConstants.TINKER_ENABLE_ALL,loadVerifyFlag = false)
public class SampleApplicationLike extends DefaultApplicationLike {private static final String TAG = "Tinker.SampleApplicationLike";public SampleApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag,long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);}/*** install multiDex before install tinker* so we don't need to put the tinker lib classes in the main dex** @param base*/@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)@Overridepublic void onBaseContextAttached(Context base) {super.onBaseContextAttached(base);//you must install multiDex whatever tinker is installed!MultiDex.install(base);SampleApplicationContext.application = getApplication();SampleApplicationContext.context = getApplication();TinkerManager.setTinkerApplicationLike(this);TinkerManager.initFastCrashProtect();//should set before tinker is installedTinkerManager.setUpgradeRetryEnable(true);//optional set logIml, or you can use default debug logTinkerInstaller.setLogIml(new MyLogImp());//installTinker after load multiDex//or you can put com.tencent.tinker.** to main dexTinkerManager.installTinker(this);Tinker tinker = Tinker.with(getApplication());}@TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback) {getApplication().registerActivityLifecycleCallbacks(callback);}}

-5,修改AndroidManifest.xml
这里的name设置的名称应该与上一步一致

@DefaultLifeCycle(application = "tinker.sample.android.app.SampleApplication",flags = ShareConstants.TINKER_ENABLE_ALL,loadVerifyFlag = false)
 <application
 android:name="tinker.sample.android.app.SampleApplication"//other />

这里可能会报红,不用管,编译后会自动生成这个application

-6.设置加载patch的代码
在程序的入口或者你想加载补丁的地方设置代码

//path根据自己下载后保存的路径填写,这里不用判断文件是否存在,因为文件不存在tinker会自动判断的String path = ""; //注意这个方法名,是onReceiveUpgradePatch,TinkerInstaller有个方法名与这个非常想,别写错了
TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(),path);

OK 调试,应该就好了,如果有其他问题可以评论留言,或者加我QQ 857879622 欢迎骚扰

另外,希望可以进去看看我的github,虽然很烂。。。后期会越来越好的
博主GitHub
我的个人主页

以下的文章也非常不错,可以去看看

Tinker微信热修复框架新手接入

这篇关于Tinker热更新(微信)详细教程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/400954

相关文章

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

W外链微信推广短连接怎么做?

制作微信推广链接的难点分析 一、内容创作难度 制作微信推广链接时,首先需要创作有吸引力的内容。这不仅要求内容本身有趣、有价值,还要能够激起人们的分享欲望。对于许多企业和个人来说,尤其是那些缺乏创意和写作能力的人来说,这是制作微信推广链接的一大难点。 二、精准定位难度 微信用户群体庞大,不同用户的需求和兴趣各异。因此,制作推广链接时需要精准定位目标受众,以便更有效地吸引他们点击并分享链接

Makefile简明使用教程

文章目录 规则makefile文件的基本语法:加在命令前的特殊符号:.PHONY伪目标: Makefilev1 直观写法v2 加上中间过程v3 伪目标v4 变量 make 选项-f-n-C Make 是一种流行的构建工具,常用于将源代码转换成可执行文件或者其他形式的输出文件(如库文件、文档等)。Make 可以自动化地执行编译、链接等一系列操作。 规则 makefile文件

poj3468(线段树成段更新模板题)

题意:包括两个操作:1、将[a.b]上的数字加上v;2、查询区间[a,b]上的和 下面的介绍是下解题思路: 首先介绍  lazy-tag思想:用一个变量记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率。 比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果刚好执行到一个子节点,

hdu1394(线段树点更新的应用)

题意:求一个序列经过一定的操作得到的序列的最小逆序数 这题会用到逆序数的一个性质,在0到n-1这些数字组成的乱序排列,将第一个数字A移到最后一位,得到的逆序数为res-a+(n-a-1) 知道上面的知识点后,可以用暴力来解 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#in

hdu1689(线段树成段更新)

两种操作:1、set区间[a,b]上数字为v;2、查询[ 1 , n ]上的sum 代码如下: #include<iostream>#include<algorithm>#include<cstring>#include<stack>#include<queue>#include<set>#include<map>#include<stdio.h>#include<stdl

hdu 1754 I Hate It(线段树,单点更新,区间最值)

题意是求一个线段中的最大数。 线段树的模板题,试用了一下交大的模板。效率有点略低。 代码: #include <stdio.h>#include <string.h>#define TREE_SIZE (1 << (20))//const int TREE_SIZE = 200000 + 10;int max(int a, int b){return a > b ? a :

AI行业应用(不定期更新)

ChatPDF 可以让你上传一个 PDF 文件,然后针对这个 PDF 进行小结和提问。你可以把各种各样你要研究的分析报告交给它,快速获取到想要知道的信息。https://www.chatpdf.com/

GIS图形库更新2024.8.4-9.9

更多精彩内容请访问 dt.sim3d.cn ,关注公众号【sky的数孪技术】,技术交流、源码下载请添加微信:digital_twin123 Cesium 本期发布了1.121 版本。重大新闻,Cesium被Bentley收购。 ✨ 功能和改进 默认启用 MSAA,采样 4 次。若要关闭 MSAA,则可以设置scene.msaaSamples = 1。但是通过比较,发现并没有多大改善。

SWAP作物生长模型安装教程、数据制备、敏感性分析、气候变化影响、R模型敏感性分析与贝叶斯优化、Fortran源代码分析、气候数据降尺度与变化影响分析

查看原文>>>全流程SWAP农业模型数据制备、敏感性分析及气候变化影响实践技术应用 SWAP模型是由荷兰瓦赫宁根大学开发的先进农作物模型,它综合考虑了土壤-水分-大气以及植被间的相互作用;是一种描述作物生长过程的一种机理性作物生长模型。它不但运用Richard方程,使其能够精确的模拟土壤中水分的运动,而且耦合了WOFOST作物模型使作物的生长描述更为科学。 本文让更多的科研人员和农业工作者