Tinker thermal repair actual combat

On March 10, 2016, Tinker project was officially launched from wechat official, which is really good news for developers, no longer need to nest webView for dynamic update, solve some small bugs online, and no need to release version. But for actual maintenance, package management is also a bit of a hassle. The realization principle is to deliver the differential packet to the client for update through dex differential

First, the effect drawing

2. Reference links

Principle: www.cnblogs.com/popfisher/p…

Official tutorial: www.tinkerpatch.com/

Why write this blog post when there is an official tutorial?

Is to document the potholes during the introduction of Tinker.

3. Integration steps

1. The first step is to add gradle plugin dependencies

Buildscript {repositories {jCenter ()} dependencies {// TinkerPatch classpath "Com. Tinkerpatch. SDK: tinkerpatch - gradle - plugin: 1.2.9"}}Copy the code

2. Step 2 Integrate TinkerPatch SDK

If dependencies {/ / using the annotation requires a separate reference, other libraries are no references to tinker provided (" com. Tinkerpatch. Tinker: tinker - android - anno: 1.9.9 ") The compile (" com. Tinkerpatch. SDK: tinkerpatch - the android SDK: 1.2.9 ")}Copy the code

An error message is displayed during this step

Configuration ‘provided’ is obsolete and has been replaced with ‘compileOnly’.

Obviously, just modify it

If dependencies {/ / using the annotation requires a separate reference, reference for other libraries are no longer tinker compileOnly (" com. Tinkerpatch. Tinker: tinker - android - anno: 1.9.9 ") Implementation (" com. Tinkerpatch. SDK: tinkerpatch - the android SDK: 1.2.9 ")}Copy the code

3. Create TinkerPatch. gradle and set tinkerpatchSupport

(1) Create a tinkerPatch. gradle file in the app root directory and fill in the following information, which is from github

apply plugin: 'tinkerpatch-support' /** * TODO: / def bakPath = file("${buildDir}/bakApk/") def baseInfo = "app-1.0.0-1112-12-49-34" def baseInfo = "app-1.0.0-1112-12-49-34" def baseInfo = "app-1.0.0-1112-12-49-34 VariantName = "debug" / * * * for parsing the refer to the parameters of the plug-in * http://tinkerpatch.com/Docs/SDK * / tinkerpatchSupport {/ * * can be closed in the debug TinkerPatch **/ /** Add multiDexKeepProguard and proguardFiles when disable tinker. These configuration files are automatically added by tinkerPatch plug-in. When you need to manually add after disable you can copy the example of proguardRules. Pro and tinkerMultidexKeep. Pro, require you to manually modify 'tinker. Sample. Android. App' this sample package called your own package name, **/ tinkerEnable = true reflectApplication = true /** * Whether to enable the hardening mode. It can be used only when APK is to be hardened; otherwise, patch will fail. * If hardening is only used in one channel, You can try any options **/ protectedApp = false /** * experiment features ** Whether the patch supports new Activities (The exported properties of new activities must be false) **/ SupportComponent = true autoBackupApkPath = "${bakPath}" appKey = "f938475486f91936" If a new full package is released, **/ appVersion = "1.0.0" def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/" def name =" "${project.name}-${variantName}" baseApkFile = "${pathPrefix}/${name}.apk" baseProguardMappingFile = ${pathPrefix}/${name}-mapping.txt" baseResourceRFile = "${pathPrefix}/${name} -r.txt" * note: https://github.com/TinkerPatch/tinkerpatch-flavors-sample Unless you have a different flavor code, use zip Comment or a file to generate channel information. */ android {defaultConfig {buildConfigField "Boolean ", "TINKER_ENABLE", "${tinkerpatchSupport. TinkerEnable}"}} / * * * in general, we don't need to make any changes * the following parameters for details please refer to the parameters of: * 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 / 7 za"} buildConfig {keepDexApply = false}}Copy the code

If there is an error Tinker Exception: applicationLike must not be null.

Because tinkerpatch. gradle configured reflectApplication = false, but you didn’t modify your Application class accordingly. This article is about not modifying our Application class to access Tinker, so the configuration should be: reflectApplication = ture.

(2) For simplicity and convenience, we put all the configurations related to TinkerPatch in Tinkerpatch. gradle. We need to introduce them in app/build.gradle:


apply from: 'tinkerpatch.gradle'

Copy the code

4. Initialize TinkerPatch SDK

(1) Create the SampleApplication custom Application class and introduce it in the androidmanifest.xml file name=””


android:name=".SampleApplication"

Copy the code

(2) Add the following code to SampleApplication

public class SampleApplication extends Application { private ApplicationLike tinkerApplicationLike; @Override public void onCreate() { super.onCreate(); / / we can get from here Tinker loading process information tinkerApplicationLike = TinkerPatchApplicationLike. GetTinkerPatchApplicationLike (); // Initialize TinkerPatch SDK, You may refer to more configuration API in the chapter, to initialize the SDK TinkerPatch. The init (tinkerApplicationLike). ReflectPatchLibrary (.) setPatchRollbackOnScreenOff (true) .setPatchRestartOnSrceenOff(true) .setFetchPatchIntervalByHours(3); / / every three hours (by setFetchPatchIntervalByHours setting) to access to update the background, through the handler to achieve the effect of training in rotation TinkerPatch.with().fetchPatchUpdateAndPollWithInterval(); }}Copy the code

5. Change the Key and start using it

(1) Fill in the key applied in Tinkerpatch

Change in tinkerpatch.gradle


appKey = "your key"

Copy the code

(2) Start using – official introduction

1. Run assembleRelease Task to build the base package (please make sure to update the appVersion in tinkerpatchSupport before publishing). TinkerPatch will automatically back up the base package information to the corresponding folder based on the autoBackupApkPath you entered, including: apk files, r.txt files and mapping.txt files. Mapping.txt is a product of ProGuard. If you don't have ProGuard enabled, you won't have this file. To issue patch packages, you only need to fill the automatically saved files into baseApkFile, baseProguardMappingFile and baseResourceRFile in tinkerpatchSupport respectively. 3. Run tinkerPatchRelease task to construct patches, and patches will be in the build/outputs/tinkerPatchCopy the code

(3) Start using – practice yourself

Let’s start with some concepts.

AssembleRelease is packaging

TinkerPatchRelease is used to generate differential packages

  1. Start by manually simulating a bug
public class MainActivity extends Activity { TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.tv_test); Textview.settext (" I am a bug"); }}Copy the code
  1. If you want to take effect in time, download an official demo and turn on the test switch

Address: www.tinkerpatch.com/Docs/dev

  1. Open AndroidStudio on the rightGradle

  1. Click assembleRelease to find the error
* What went wrong: Execution failed for task ':app:javaPreCompileRelease'. > Annotation processors must be explicitly declared now. The following dependencies on the compile classpath are found to contain annotation processor. Please add them to the AnnotationProcessor configuration. - tinker - android - anno - 1.9.9. Jar (com. Tinkerpatch. Tinker: tinker - android - anno: 1.9.9) Alternatively, set android.defaultConfig.javaCompileOptions.annotationProcessorOptions.includeCompileClasspath = true to continue with previous behavior. Note that this option is deprecated and will be removed in the future. See https://developer.android.com/r/tools/annotation-processor-error-message.html for more details.Copy the code

To solve

Add it in the build of your app

android { ... defaultConfig { ... / / add the following configuration with respect to OK javaCompileOptions {annotationProcessorOptions {includeCompileClasspath = true}}}... }Copy the code

After a successful run, you’ll find a lot of files generated under your app/build

  1. Manual emulation fixes this bug
public class MainActivity extends Activity { TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = findViewById(R.id.tv_test); Textview.settext ("bug fixed "); }}Copy the code
  1. Modify thetinkerpatch.gradlefile

Many of the attributes in this file refer to local directories. In this format, you need to modify the following parameters.

Def baseInfo = "app-1.0.0-0416-20-10-21" def variantName = "release"Copy the code
  1. And then runtinkerPatchRelease

The following errors were found


* What went wrong:

Execution failed for task ':app:tinkerPatchRelease'.

> can't the get signConfig for this build

Copy the code

You can’t get signature configuration information in build, so let’s configure signature information.

This step is not clear how to configure please go to Google

  1. Proceed with tinkerPatchRelease to generate the differential package

If not, start with step 4 for the Clean project

After success, the difference package (patch file) is generated and uploaded to TinkerPatch platform

  1. For convenience, we selected the development preview and opened the test environment in the official demo.
  • Install the buggy installation package first

  • After opening, kill the process and re-enter, and find that the interface prompts “Bug fixed”; If not, try it several times, give it some time to synthesize

Six, other points need to pay attention to

  1. Need to add permissions

<uses-permission android:name="android.permission.INTERNET" />

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

Copy the code
  1. The version added on TinkerPatch platform is the version of app, and the corresponding version requests the patch of the corresponding version

  2. AppVersion in TinkerPatch. gradle needs to be updated for full update