# TinkerPatch **Repository Path**: huqs/TinkerPatch ## Basic Information - **Project Name**: TinkerPatch - **Description**: Android 热修复 - **Primary Language**: Android - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2017-01-10 - **Last Updated**: 2020-12-19 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # TinkerPatch ``` TinkerPatch 是一个Android热修复补丁使用说明 是基于腾讯开源个框架Tinker和TinkerPatch 实现的 SDK地址:https://github.com/TinkerPatch 后台地址:http://www.tinkerpatch.com/Docs/intro ``` [相关文档](http://tinkerpatch.com/Docs/intro) ![tinkerpatch-sample] (image.png) ###集成步骤 1.引入sdk库 app/build.gradle ``` dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile "com.android.support:appcompat-v7:23.1.1" compile "com.android.support:multidex:1.0.1" //若使用annotation需要单独引用,对于tinker的其他库都无需再引用 provided("com.tencent.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true } compile("com.tinkerpatch.sdk:tinkerpatch-android-sdk:${TINKERPATCH_VERSION}") { changing = true } compile 'com.github.bumptech.glide:glide:3.7.0' } ``` 2.在project 的 build.gradle引入tinkerpatch插件用来编译补丁和其他资源 ``` // Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { mavenLocal() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:2.2.3' //无需再单独引用tinker的其他库 classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:${TINKERPATCH_VERSION}" } } ``` 3.在app/下创建 tinkerpatch.gradle 文件 代码如下: ``` import java.text.SimpleDateFormat apply plugin: 'tinkerpatch-support' //编译的文件保存路径(APK) def bakPath = file("${buildDir}/bakApk/") //编译文件夹路径 def appName = "app-1.0.0-0109-17-17-55" //编译的文件保存路径(APK) def basePath = file("base") //获取系统时间 def time =new SimpleDateFormat("yyyy-MM-dd").format(new Date()) //获取Android project 版本号 def version= android.defaultConfig.versionName /** * 对于插件各参数的详细解析请参考 * http://tinkerpatch.com/Docs/SDK */ tinkerpatchSupport { //是否开启 tinkerpatchSupport 插件功能。 tinkerEnable = true //在 TinkerPatch 平台 申请的 appkey appKey = "2e2c417e282c3d65" //在 TinkerPatch 平台 输入的版本号,注意,我们使用 appVersion 作为 TinkerId, 我们需要保证每个发布出去的基础安装包的 appVersion 都不一样。 appVersion = "${version}" //将每次编译产生的 apk/mapping.txt/R.txt 归档存储的位置 autoBackupApkPath = "${bakPath}/${time}" //编译补丁包时,必需指定基准版本的 apk,默认值为空,则表示不是进行补丁包的编译。 baseApkFile = "${basePath}/${appName}/app-release.apk" //在编译新的 apk 时候,我们希望通过保持基准 apk 的 proguard 混淆方式,从而减少补丁包的大小。这是强烈推荐的,编译补丁包时,我们推荐输入基准 apk 生成的 mapping.txt 文件。 baseProguardMappingFile = "${basePath}/${appName}/app-release-mapping.txt" //在编译新的apk时候,我们希望通基准 apk 的 R.txt 文件来保持 Resource Id 的分配,这样不仅可以减少补丁包的大小,同时也避免由于 Resource Id 改变导致 remote view 异常。 baseResourceRFile = "${basePath}/${appName}/app-release-R.txt" } /** * * 编译发布版本的安装包 * ./gradlew assembleRelease * * 编译基础包的产物 *./gradlew autoBackupApkPath * 编译补丁文件 * ./gradlew tinkerPatchRelease * * * */ /** * 一般来说,我们无需对下面的参数做任何的修改 * 对于各参数的详细介绍请参考: * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97 */ tinkerPatch { ignoreWarning = false useSign = true dex { dexMode = "jar" pattern = ["classes*.dex"] loader = [] } lib { pattern = ["lib/*/*.so"] } res { pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"] ignoreChange = [] largeModSize = 100 } packageConfig { } sevenZip { zipArtifact = "com.tencent.mm:SevenZip:1.1.10" // path = "/usr/local/bin/7za" } buildConfig { keepDexApply = false } } ``` 4.需要在app/build.gradle 最后 引用刚刚创建的.gradle 文件 ``` apply from: 'tinkerpatch.gradle' ``` 5.接下配置Application ```java @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.SampleAppLike"; public SampleApplicationLike(Application application, int i, boolean b, long l, long l1, Intent intent, Resources[] resources, ClassLoader[] classLoaders, AssetManager[] assetManagers) { super(application, i, b, l, l1, intent, resources, classLoaders, assetManagers); } /** * install multiDex before install tinker * so we don't need to put the tinker lib classes in the main dex */ @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH) @Override public void onBaseContextAttached(Context base) { super.onBaseContextAttached(base); //you must install multiDex whatever tinker is installed! MultiDex.install(base); } @Override public void onCreate() { super.onCreate(); //开始检查是否有补丁,这里配置的是每隔访问3小时服务器是否有更新。 TinkerPatch.init(this) .reflectPatchLibrary() .setPatchRollbackOnScreenOff(true) .setPatchRestartOnSrceenOff(true); //每隔3个小时去访问后台时候有更新,通过handler实现轮训的效果 new FetchPatchHandler().fetchPatchWithInterval(3); } /** * 在这里给出TinkerPatch的所有接口解释 * 更详细的解释请参考:http://tinkerpatch.com/Docs/api */ private void useSample() { TinkerPatch.init(this) //是否自动反射Library路径,无须手动加载补丁中的So文件 //注意,调用在反射接口之后才能生效,你也可以使用Tinker的方式加载Library .reflectPatchLibrary() //向后台获取是否有补丁包更新,默认的访问间隔为3个小时 //若参数为true,即每次调用都会真正的访问后台配置 .fetchPatchUpdate(false) //设置访问后台补丁包更新配置的时间间隔,默认为3个小时 .setFetchPatchIntervalByHours(3) //向后台获得动态配置,默认的访问间隔为3个小时 //若参数为true,即每次调用都会真正的访问后台配置 .fetchDynamicConfig(new ConfigRequestCallback() { @Override public void onSuccess(HashMap hashMap) { } @Override public void onFail(Exception e) { } }, false) //设置访问后台动态配置的时间间隔,默认为3个小时 .setFetchDynamicConfigIntervalByHours(3) //设置当前渠道号,对于某些渠道我们可能会想屏蔽补丁功能 //设置渠道后,我们就可以使用后台的条件控制渠道更新 .setAppChannel("default") //屏蔽部分渠道的补丁功能 .addIgnoreAppChannel("googleplay") //设置tinkerpatch平台的条件下发参数 .setPatchCondition("test", "1") //设置补丁合成成功后,锁屏重启程序 //默认是等应用自然重启 .setPatchRestartOnSrceenOff(true) //我们可以通过ResultCallBack设置对合成后的回调 //例如弹框什么 .setPatchResultCallback(new ResultCallBack() { @Override public void onPatchResult(PatchResult patchResult) { Log.i(TAG, "onPatchResult callback here"); } }) //设置收到后台回退要求时,锁屏清除补丁 //默认是等主进程重启时自动清除 .setPatchRollbackOnScreenOff(true) //我们可以通过RollbackCallBack设置对回退时的回调 .setPatchRollBackCallback(new RollbackCallBack() { @Override public void onPatchRollback() { Log.i(TAG, "onPatchRollback callback here"); } }); } /** * 自定义Tinker类的高级用法,一般不推荐使用 * 更详细的解释请参考:http://tinkerpatch.com/Docs/api */ private void complexSample() { TinkerPatch.Builder builder = new TinkerPatch.Builder(this); //修改tinker的构造函数,自定义类 builder.listener(new DefaultPatchListener(getApplication())) .loadReporter(new DefaultLoadReporter(getApplication())) .patchReporter(new DefaultPatchReporter(getApplication())) .resultServiceClass(TinkerServerResultService.class) .upgradePatch(new UpgradePatch()) .patchRequestCallback(new TinkerPatchRequestCallback()); TinkerPatch.init(builder.build()); } } ``` 6.最后配置Manifest文件 ```xml ``` 如果在编译补丁过程中提示没有权限 ``` -bash: ./gradlew: Permission denied 解决的办法:在终端中输入以下命令回车 chmod +x gradlew ```