- 到 http://www.tinkerpatch.com 平台注册一个app并获取appKey
- 根据 http://www.tinkerpatch.com/Docs/SDK 文档做配置
- build.gradle.中
// Top-level build file where you can add configuration options common to all sub-projects/modules. buildscript { repositories { google() jcenter() } dependencies { classpath 'com.android.tools.build:gradle:3.1.2' // TinkerPatch 插件 classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.2.6" } } allprojects { repositories { google() jcenter() } } task clean(type: Delete) { delete rootProject.buildDir }
- app/build.gradle中,主要是签名和tinker的包
apply plugin: 'com.android.application' apply from: 'tinkerpatch.gradle' android { signingConfigs { release { keyAlias 'key0' keyPassword 'tinker' storeFile file('../tinker.jks') storePassword 'tinker' } } compileSdkVersion 26 defaultConfig { applicationId "com.android.commonlib.tinkertest" minSdkVersion 19 targetSdkVersion 26 versionCode 1 versionName "1.0.1" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" javaCompileOptions { annotationProcessorOptions { includeCompileClasspath = true } } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' signingConfig signingConfigs.release } debug { signingConfig signingConfigs.release } } } dependencies { implementation fileTree(include: ['*.jar'], dir: 'libs') implementation 'com.android.support:appcompat-v7:26.1.0' implementation 'com.android.support.constraint:constraint-layout:1.1.0' testImplementation 'junit:junit:4.12' androidTestImplementation 'com.android.support.test:runner:1.0.2' androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2' implementation "com.android.support:multidex:1.0.2" //若使用annotation需要单独引用,对于tinker的其他库都无需再引用 annotationProcessor("com.tinkerpatch.tinker:tinker-android-anno:1.9.6") { changing = true } compileOnly("com.tinkerpatch.tinker:tinker-android-anno:1.9.6") { changing = true } implementation("com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.2.6") { changing = true } }
- Application
public class SampleApplication extends Application { @Override public void onCreate() { super.onCreate(); initTinkerPatch(); } private void initTinkerPatch() { // 我们可以从这里获得Tinker加载过程的信息 ApplicationLike tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike(); // 初始化TinkerPatch SDK TinkerPatch.init( tinkerApplicationLike // new TinkerPatch.Builder(tinkerApplicationLike) // .requestLoader(new OkHttp3Loader()) // .build() ) .reflectPatchLibrary() .setPatchRollbackOnScreenOff(true) .setPatchRestartOnSrceenOff(true) .setFetchPatchIntervalByHours(3) ; // 获取当前的补丁版本 // fetchPatchUpdateAndPollWithInterval 与 fetchPatchUpdate(false) // 不同的是,会通过handler的方式去轮询 TinkerPatch.with().fetchPatchUpdateAndPollWithInterval(); } @Override public void attachBaseContext(Context base) { super.attachBaseContext(base); //you must install multiDex whatever tinker is installed! MultiDex.install(base); } }
- tinkerpatch.gradle
apply plugin: 'tinkerpatch-support' /** * TODO: 请按自己的需求修改为适应自己工程的参数 */ def bakPath = file("${buildDir}/bakApk/") def baseInfo = "app-1.0.1-0525-15-59-41" def variantName = "release" /** * 对于插件各参数的详细解析请参考 * http://tinkerpatch.com/Docs/SDK */ tinkerpatchSupport { /** 可以在debug的时候关闭 tinkerPatch **/ /** 当disable tinker的时候需要添加multiDexKeepProguard和proguardFiles, 这些配置文件本身由tinkerPatch的插件自动添加,当你disable后需要手动添加 你可以copy本示例中的proguardRules.pro和tinkerMultidexKeep.pro, 需要你手动修改'tinker.sample.android.app'本示例的包名为你自己的包名, com.xxx前缀的包名不用修改 **/ tinkerEnable = true reflectApplication = true /** * 是否开启加固模式,只能在APK将要进行加固时使用,否则会patch失败。 * 如果只在某个渠道使用了加固,可使用多flavors配置 **/ protectedApp = false /** * 实验功能 * 补丁是否支持新增 Activity (新增Activity的exported属性必须为false) **/ supportComponent = true autoBackupApkPath = "${bakPath}" appKey = "a2fc5f63bf186415" /** 注意: 若发布新的全量包, appVersion一定要更新 **/ appVersion = "1.0.1" def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/" def name = "${project.name}-${variantName}" baseApkFile = "${pathPrefix}/${name}.apk" baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt" baseResourceRFile = "${pathPrefix}/${name}-R.txt" /** * 若有编译多flavors需求, 可以参照: https://github.com/TinkerPatch/tinkerpatch-flavors-sample * 注意: 除非你不同的flavor代码是不一样的,不然建议采用zip comment或者文件方式生成渠道信息(相关工具:walle 或者 packer-ng) **/ } /** * 用于用户在代码中判断tinkerPatch是否被使能 */ android { defaultConfig { buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}" } } /** 1. 一般来说,我们无需对下面的参数做任何的修改 2. 对于各参数的详细介绍请参考: 3. 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 } }
配置完成,测试下,先运行assembleRelease模拟打正式包,生成文件如下(即app-release.apk)安装在手机上。
每次编译都会生成一个基准包,这边此次生成的基准包放在app-1.0.1-0525-15-59-41目录中,修改tinkerpatch.gradle中baseInfo的值为【app-1.0.1-0525-15-59-41】这个目录。
然后随意修改下我们的代码,表示我们要打的补丁。之后再运行tinkerPatchRelease就会基于这个基准包生成补丁包了。即tinker_result/patch_signed_7zip.apk
- 发布到tinkerpatch平台,我们刚刚的appVersion是1.0.1,在tinkerpatch中建一个1.0.1的版本,然后下发补丁即可。
- 建议本地先测试下,可以将补丁包发送到本地目录下,然后调用以下代码即可自动打补丁,重启应用即可生效。如果有错误也可以从log中看出
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView textView = findViewById(R.id.textview); textView.setText("...Hello World..."); textView.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk"); } }); }
文章来源: tinkerpatch使用记事