Tinker接入流程

2024-06-17 10:18
文章标签 流程 接入 tinker

本文主要是介绍Tinker接入流程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1.在项目的build.gradl中添加

dependencies {//TINKER_VERSION 在 gradle.properties文件里配置就好 TINKER_VERSION=1.9.8classpath "com.tencent.tinker:tinker-patch-gradle-plugin:${TINKER_VERSION}"}

2.在app的gradle文件中依赖

    implementation("com.tencent.tinker:tinker-server-android:0.3.2")provided("com.tencent.tinker:tinker-android-anno:1.7.7")compile("com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.1.4")implementation "androidx.multidex:multidex:2.0.1"

3.接着配置Tinker的核心任务

def bakPath = file("${buildDir}/bakApk/")/*** you can use assembleRelease to build you base apk* use tinkerPatchRelease -POLD_APK=  -PAPPLY_MAPPING=  -PAPPLY_RESOURCE= to build patch* add apk from the build/bakApk*/
ext {//for some reason, you may want to ignore tinkerBuild, such as instant run debug build?tinkerEnabled = true//for normal build//old apk file to build patch apktinkerOldApkPath = "${bakPath}/app-release-0529-14-52-58.apk"//proguard mapping file to build patch apktinkerApplyMappingPath = "${bakPath}/tinkersimplein-debug-0724-11-11-08-mapping.txt"//resource R.txt to build patch apk, must input if there is resource changedtinkerApplyResourcePath = "${bakPath}/tinkersimplein-debug-0724-11-11-08-R.txt"//only use for build all flavor, if not, just ignore this fieldtinkerBuildFlavorDirectory = "${bakPath}/app-1018-17-32-47"
}def getOldApkPath() {return hasProperty("OLD_APK") ? OLD_APK : ext.tinkerOldApkPath
}def getApplyMappingPath() {return hasProperty("APPLY_MAPPING") ? APPLY_MAPPING : ext.tinkerApplyMappingPath
}def getApplyResourceMappingPath() {return hasProperty("APPLY_RESOURCE") ? APPLY_RESOURCE : ext.tinkerApplyResourcePath
}def getTinkerIdValue() {//return hasProperty("TINKER_ID") ? TINKER_ID : gitSha()return hasProperty("TINKER_ID") ? TINKER_ID : "必填"
}def buildWithTinker() {return hasProperty("TINKER_ENABLE") ? Boolean.parseBoolean(TINKER_ENABLE) : ext.tinkerEnabled
}def getTinkerBuildFlavorDirectory() {return ext.tinkerBuildFlavorDirectory
}if (buildWithTinker()) {apply plugin: 'com.tencent.tinker.patch'tinkerPatch {/*** necessary,default 'null'* the old apk path, use to diff with the new apk to build* add apk from the build/bakApk*/oldApk = getOldApkPath()/*** optional,default 'false'* there are some cases we may get some warnings* if ignoreWarning is true, we would just assert the patch process* case 1: minSdkVersion is below 14, but you are using dexMode with raw.*         it must be crash when load.* case 2: newly added Android Component in AndroidManifest.xml,*         it must be crash when load.* case 3: loader classes in dex.loader{} are not keep in the main dex,*         it must be let tinker not work.* case 4: loader classes in dex.loader{} changes,*         loader classes is ues to load patch dex. it is useless to change them.*         it won't crash, but these changes can't effect. you may ignore it* case 5: resources.arsc has changed, but we don't use applyResourceMapping to build*/ignoreWarning = false/*** optional,default 'true'* whether sign the patch file* if not, you must do yourself. otherwise it can't check success during the patch loading* we will use the sign config with your build type*/useSign = true/*** optional,default 'true'* whether use tinker to build*/tinkerEnable = buildWithTinker()/*** Warning, applyMapping will affect the normal android build!*/buildConfig {/*** optional,default 'null'* if we use tinkerPatch to build the patch apk, you'd better to apply the old* apk mapping file if minifyEnabled is enable!* Warning:* you must be careful that it will affect the normal assemble build!*/applyMapping = getApplyMappingPath()/*** optional,default 'null'* It is nice to keep the resource id from R.txt file to reduce java changes*/applyResourceMapping = getApplyResourceMappingPath()/*** necessary,default 'null'* because we don't want to check the base apk with md5 in the runtime(it is slow)* tinkerId is use to identify the unique base apk when the patch is tried to apply.* we can use git rev, svn rev or simply versionCode.* we will gen the tinkerId in your manifest automatic*/tinkerId = getTinkerIdValue()/*** if keepDexApply is true, class in which dex refer to the old apk.* open this can reduce the dex diff file size.*/keepDexApply = false/*** optional, default 'false'* Whether tinker should treat the base apk as the one being protected by app* protection tools.* If this attribute is true, the generated patch package will contain a* dex including all changed classes instead of any dexdiff patch-info files.*/isProtectedApp = false/*** optional, default 'false'* Whether tinker should support component hotplug (add new component dynamically).* If this attribute is true, the component added in new apk will be available after* patch is successfully loaded. Otherwise an error would be announced when generating patch* on compile-time.** <b>Notice that currently this feature is incubating and only support NON-EXPORTED Activity</b>*/supportHotplugComponent = false}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"tinker.sample.android.app.BaseBuildInfo"]}lib {/*** optional,default '[]'* what library in apk are expected to deal with tinkerPatch* it support * or ? pattern.* for library in assets, we would just recover them in the patch directory* you can get them in TinkerLoadResult with Tinker*/pattern = ["lib/*/*.so"]}res {/*** optional,default '[]'* what resource in apk are expected to deal with tinkerPatch* it support * or ? pattern.* you must include all your resources in apk here,* otherwise, they won't repack in the new apk resources.*/pattern = ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]/*** optional,default '[]'* the resource file exclude patterns, ignore add, delete or modify resource change* it support * or ? pattern.* Warning, we can only use for files no relative with resources.arsc*/ignoreChange = ["assets/sample_meta.txt"]/*** default 100kb* for modify resource, if it is larger than 'largeModSize'* we would like to use bsdiff algorithm to reduce patch file size*/largeModSize = 100}packageConfig {/*** optional,default 'TINKER_ID, TINKER_ID_VALUE' 'NEW_TINKER_ID, NEW_TINKER_ID_VALUE'* package meta file gen. path is assets/package_meta.txt in patch file* you can use securityCheck.getPackageProperties() in your ownPackageCheck method* or TinkerLoadResult.getPackageConfigByName* we will get the TINKER_ID from the old apk manifest for you automatic,* other config files (such as patchMessage below)is not necessary*/configField("patchMessage", "tinker is sample to use")/*** just a sample case, you can use such as sdkVersion, brand, channel...* you can parse it in the SamplePatchListener.* Then you can use patch conditional!*/configField("platform", "all")/*** patch version via packageConfig*/configField("patchVersion", "1.0")}//or you can add config filed outside, or get meta value from old apk//project.tinkerPatch.packageConfig.configField("test1", project.tinkerPatch.packageConfig.getMetaDataFromOldApk("Test"))//project.tinkerPatch.packageConfig.configField("test2", "sample")/*** if you don't use zipArtifact or path, we just use 7za to try*/sevenZip {/*** optional,default '7za'* the 7zip artifact path, it will use the right 7za with your platform*/zipArtifact = "com.tencent.mm:SevenZip:1.1.10"/*** optional,default '7za'* you can specify the 7za path yourself, it will overwrite the zipArtifact value*/
//        path = "/usr/local/bin/7za"}}List<String> flavors = new ArrayList<>();project.android.productFlavors.each { flavor ->flavors.add(flavor.name)}boolean hasFlavors = flavors.size() > 0def date = new Date().format("MMdd-HH-mm-ss")/*** bak apk and mapping*/android.applicationVariants.all { variant ->/*** task type, you want to bak*/def taskName = variant.nametasks.all {if ("assemble${taskName.capitalize()}".equalsIgnoreCase(it.name)) {it.doLast {copy {def fileNamePrefix = "${project.name}-${variant.baseName}"def newFileNamePrefix = hasFlavors ? "${fileNamePrefix}" : "${fileNamePrefix}-${date}"def destPath = hasFlavors ? file("${bakPath}/${project.name}-${date}/${variant.flavorName}") : bakPathfrom variant.outputs.first().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")}}}}}}project.afterEvaluate {//sample use for build all flavor for one timeif (hasFlavors) {task(tinkerPatchAllFlavorRelease) {group = 'tinker'def originOldPath = getTinkerBuildFlavorDirectory()for (String flavor : flavors) {def tinkerTask = tasks.getByName("tinkerPatch${flavor.capitalize()}Release")dependsOn tinkerTaskdef preAssembleTask = tasks.getByName("process${flavor.capitalize()}ReleaseManifest")preAssembleTask.doFirst {String flavorName = preAssembleTask.name.substring(7, 8).toLowerCase() + preAssembleTask.name.substring(8, preAssembleTask.name.length() - 15)project.tinkerPatch.oldApk = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release.apk"project.tinkerPatch.buildConfig.applyMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release-mapping.txt"project.tinkerPatch.buildConfig.applyResourceMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release-R.txt"}}}task(tinkerPatchAllFlavorDebug) {group = 'tinker'def originOldPath = getTinkerBuildFlavorDirectory()for (String flavor : flavors) {def tinkerTask = tasks.getByName("tinkerPatch${flavor.capitalize()}Debug")dependsOn tinkerTaskdef preAssembleTask = tasks.getByName("process${flavor.capitalize()}DebugManifest")preAssembleTask.doFirst {String flavorName = preAssembleTask.name.substring(7, 8).toLowerCase() + preAssembleTask.name.substring(8, preAssembleTask.name.length() - 13)project.tinkerPatch.oldApk = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-debug.apk"project.tinkerPatch.buildConfig.applyMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-debug-mapping.txt"project.tinkerPatch.buildConfig.applyResourceMapping = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-debug-R.txt"}}}}}
}

以上gradle相关配置 大致完成

4.我们开始写我们熟悉的java代码了

package com.zjs.kt;import android.app.Application;
import android.content.Context;
import android.content.Intent;import androidx.multidex.MultiDex;import com.tencent.tinker.anno.DefaultLifeCycle;
import com.tencent.tinker.app.TinkerServerManager;
import com.tencent.tinker.lib.tinker.Tinker;
import com.tencent.tinker.loader.app.DefaultApplicationLike;
import com.tencent.tinker.loader.shareutil.ShareConstants;
import com.zjs.kt.util.TinkerManager;/*** @Description: <切记 .MyApp一定要注册到Manifest.xml中标签application的name>* @author: Leo* @data: 2020/5/29* @version: V1.0*/
@DefaultLifeCycle(application = ".MyApp",flags = ShareConstants.TINKER_ENABLE_ALL,loadVerifyFlag = false)
public class TinkerApplicationLike extends DefaultApplicationLike {public TinkerApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);}@Overridepublic void onBaseContextAttached(Context base) {super.onBaseContextAttached(base);MultiDex.install(base);TinkerManager.installTinker(this);
//        //初始化TinkerPatch SDK    BuildConfig.APP_KEY, BuildConfig.APP_VERSIONTinkerServerManager.installTinkerServer(getApplication(), Tinker.with(getApplication()), 3,"f98425b22067805f", "1.0", "default");
//        //开始检查是否有补丁,这里配置的是每隔访问3小时服务器是否有更新。TinkerServerManager.checkTinkerUpdate(false);}
}

以上代码全部编写完成,

  • 让我们先生成一个基础包如图,把生成的基础包安装到我们的手机上

  • 接着生成补丁包,(前提是把刚才基础包中代码随意修改一下,不让我们怎么知道是否成功加载了补丁)如下图

以此记录接入Tinker的大体流程,以备后期需要。Tinker发布的流程就不提了。

 

这篇关于Tinker接入流程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

Spring AI ectorStore的使用流程

《SpringAIectorStore的使用流程》SpringAI中的VectorStore是一种用于存储和检索高维向量数据的数据库或存储解决方案,它在AI应用中发挥着至关重要的作用,本文给大家介... 目录一、VectorStore的基本概念二、VectorStore的核心接口三、VectorStore的

python之流程控制语句match-case详解

《python之流程控制语句match-case详解》:本文主要介绍python之流程控制语句match-case使用,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录match-case 语法详解与实战一、基础值匹配(类似 switch-case)二、数据结构解构匹

在VSCode中本地运行DeepSeek的流程步骤

《在VSCode中本地运行DeepSeek的流程步骤》本文详细介绍了如何在本地VSCode中安装和配置Ollama和CodeGPT,以使用DeepSeek进行AI编码辅助,无需依赖云服务,需要的朋友可... 目录步骤 1:在 VSCode 中安装 Ollama 和 CodeGPT安装Ollama下载Olla

IDEA接入Deepseek的图文教程

《IDEA接入Deepseek的图文教程》在本篇文章中,我们将详细介绍如何在JetBrainsIDEA中使用Continue插件接入DeepSeek,让你的AI编程助手更智能,提高开发效率,感兴趣的小... 目录一、前置准备二、安装 Continue 插件三、配置 Continue 连接 DeepSeek四

linux环境openssl、openssh升级流程

《linux环境openssl、openssh升级流程》该文章详细介绍了在Ubuntu22.04系统上升级OpenSSL和OpenSSH的方法,首先,升级OpenSSL的步骤包括下载最新版本、安装编译... 目录一.升级openssl1.官网下载最新版openssl2.安装编译环境3.下载后解压安装4.备份

C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)

《C#集成DeepSeek模型实现AI私有化的流程步骤(本地部署与API调用教程)》本文主要介绍了C#集成DeepSeek模型实现AI私有化的方法,包括搭建基础环境,如安装Ollama和下载DeepS... 目录前言搭建基础环境1、安装 Ollama2、下载 DeepSeek R1 模型客户端 ChatBo

SpringBoot快速接入OpenAI大模型的方法(JDK8)

《SpringBoot快速接入OpenAI大模型的方法(JDK8)》本文介绍了如何使用AI4J快速接入OpenAI大模型,并展示了如何实现流式与非流式的输出,以及对函数调用的使用,AI4J支持JDK8... 目录使用AI4J快速接入OpenAI大模型介绍AI4J-github快速使用创建SpringBoot

Linux流媒体服务器部署流程

《Linux流媒体服务器部署流程》文章详细介绍了流媒体服务器的部署步骤,包括更新系统、安装依赖组件、编译安装Nginx和RTMP模块、配置Nginx和FFmpeg,以及测试流媒体服务器的搭建... 目录流媒体服务器部署部署安装1.更新系统2.安装依赖组件3.解压4.编译安装(添加RTMP和openssl模块

0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型的操作流程

《0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeekR1模型的操作流程》DeepSeekR1模型凭借其强大的自然语言处理能力,在未来具有广阔的应用前景,有望在多个领域发... 目录0基础租个硬件玩deepseek,蓝耘元生代智算云|本地部署DeepSeek R1模型,3步搞定一个应

PyCharm 接入 DeepSeek最新完整教程

《PyCharm接入DeepSeek最新完整教程》文章介绍了DeepSeek-V3模型的性能提升以及如何在PyCharm中接入和使用DeepSeek进行代码开发,本文通过图文并茂的形式给大家介绍的... 目录DeepSeek-V3效果演示创建API Key在PyCharm中下载Continue插件配置Con