Integrated tinker

For the original app integration tinker, or relatively simple, according to the tinker wiki instructions. The specific steps are as follows:

  1. Add the tinker-patch-gradle-plugin dependency to your project build.gradle
buildscript {
    dependencies {
        classpath 'com. Tencent. Tinker: tinker - patch - gradle - plugin: 1.7.9'}}Copy the code
  1. Then in app gradle file app/build.gradle, we need to add tinker library dependencies and apply Tinker gradle plugin.
Dependencies {// Optional, used to generate application class Provided'com. Tencent. Tinker: tinker - android - anno: 1.7.9'// Compile is tinker's core library'com. Tencent. Tinker: tinker - android - lib: 1.7.9'}... . // Apply tinker plugin apply plugin:'com.tencent.tinker.patch'
Copy the code
  1. You also need to configure
dexOptions {
        jumboMode = true
    }
Copy the code

Tinker best practices to prevent force-jumbol from causing more changes due to string increases 4. Finally, you can move the tinker related code to Tinkerpatch. gradle. Modify SampleApplication to proxy the behavior of SampleApplication through SampleApplicationLike. For details on wiki and SampleApplication changes, see TinkerDemo

Strengthening support

Tinker supports hardening as of 1.7.8. You only need to modify this part of Tinkerpatch. gradle

buildConfig {
            applyMapping = getApplyMappingPath()
            applyResourceMapping = getApplyResourceMappingPath()
            tinkerId = getTinkerIdValue()
            keepDexApply = false

            isProtectedApp = true// Enable hardening}Copy the code

Integrated patchsdk

Patchsdk use https://github.com/baidao/tinker-manager/tree/master/patchsdk steps are as follows

  1. Need to be added in app/build.gradle
repositories {
    jcenter()
}
dependencies {
    ...
    compile 'com. Dx168. Patchsdk: patchsdk: 1.1.3'
}
Copy the code
  1. Use ApplicationLike to proxy the original Application
@SuppressWarnings("unused")
@DefaultLifeCycle(application = "com.dx168.patchsdk.sample.MyApplication",
        flags = ShareConstants.TINKER_ENABLE_ALL,
        loadVerifyFlag = false)
public class MyApplicationLike extends TinkerApplicationLike {
    public MyApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
        super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
    }

    @Override
    public void onCreate() {
        super.onCreate();
        String appId = "20170112162040035-6936";
        String appSecret = "d978d00c0c1344959afa9d0a39d7dab3";
        PatchManager.getInstance().init(getApplication(), "http://xxx.xxx.xxx/hotfix-apis/", appId, appSecret, new ActualPatchManager() { @Override public void cleanPatch(Context context) { TinkerInstaller.cleanPatch(context); } @Override public void patch(Context context, String patchPath) { TinkerInstaller.onReceiveUpgradePatch(context, patchPath); }}); PatchManager.getInstance().register(newListener() {... }); PatchManager.getInstance().setTag("your tag");
        PatchManager.getInstance().setChannel(""); PatchManager.getInstance().queryAndPatch(); }}Copy the code
  1. Setting up patch background management system refer to Readme to set up patch background, but this background does not have the function of pushing patch delivery, only after the background is delivered, the client pulls the patch and repairs the patch. If your app uses Bugly as an exception report and operation statistics, Then you can directly use the background provided by Bugly, please refer to here for specific operation. Xiao Wu has recorded a series of related videos, which you can learn by referring to the video tutorial. The address is here. But for a fee.

Generate channel package

For channel packages, if you don’t need to use hot fixes, you can generate channel packages any way. Compiling the flavor channel package would result in classes.dex differences between different channel packages due to BuildConfig changes, which is not desirable. It is highly recommended to write channel information in ZIP comment of APK file. For example, project Packer-ng-plugin or WALle which can use V2 Scheme can be used, as well as the latest multi-channel packaging wizard ApkChannelPackage. If you want to use hot fixes, generate channel packages for apps that do not need reinforcement, all three options can be used; For the APP to be reinforced, the channel package can only be generated according to the existing APK in the scheme ApkChannelPackage (if there are other schemes, please remember to tell me). This article makes a detailed distinction between multi-channel packaging tool comparisons. The ApkChannelPackage scheme is also adopted at present.

Generate the patch

TinkerDemo, for example

  1. Execute./gradlew assembleRelease to generate the APK
  2. Reinforce apK with the Bang-Bang Hardening Tool and sign to get the reinforced and re-signed app_protected_signed. Apk
  3. Build channel packages using./gradlew reBuildChannel
  4. Modify some code in TinkerDemo
  5. /gradlew tinkerPatchRelease Generates patch apK (make sure tinkerId is the same as baseline tinkerId). TinkerId is generated according to git commit.
  6. If a patch management background is set up, use the background to upload the patch package and repair it. According to the log, you can observe the result
  7. If I hadn’t built a patch management background, Using the adb push app/build/outputs/tinkerPatch/release/patch_signed_7zip apk/storage/sdcard0 / (refer to tinker, sample projects, as well as tinker access document)

Test patch pack

According to generate the patch number of steps, to test the validity of patches, after the third generation channel package, install one of these channels apk to mobile phones, and then, my side is through the patch management background to upload the patch, the client then pull patch, according to the log, can clearly see the patch whether the download is complete, is valid. After the patch is downloaded, dex is synthesized. Then the app would be killed in the background or after the screen was off, and the patch would only take effect after a reboot, and that’s when we actually fixed the problem.

The pit of tread

  1. Gradle release play packages need to open the signature (. / gradlew assembleRelease), otherwise, the patch package, prompt error (. / gradlew tinkerPatchRelease)
  2. Make sure that the baseline version is the same as the last version of APK, and if you use the default form of Tinker, the tinkerId should be the same as the tinkerId of the last version of APK, that is, open bugFix branches based on the last version of APK tag, but don’t commit the code. In this way, tinkerId is guaranteed to be consistent (it can be considered that the version number of app is VERSION_NAME as tinkerId, and the version number will definitely be changed every time the version is issued). If it is tinker integrated with Bugly, please refer to the official Bugly document
  3. At first, I didn’t understand the compatibility between reinforcement package and channel package. What should I do if there is a need for reinforcement? . We need to understand is that reinforce the package is not a baseline version, use the tinker patch package, use the baseline version, after get the baseline version, we will choose the bang bang, music, love to encrypt this platform to the baseline version of the get reinforced package, also it is important to note that not enough common channels package generation scheme for package. For example, the app of our company adopts bang-bang reinforcement. After reinforcement, the tool automatically generates channel package for you. However, there are problems with the generated channel package, which will make it impossible to patch and repair, and Tinker hot repair will not take effect. In this generated channel package, the CRC of dex corresponding to different channels is different, so we need to ensure that the dex of the generated channel package is the same. It can be known from apksigner that the signature tool of bang-bang-hardening adopts V1 signature scheme, so we can consider adding channel information in the annotation field of APK file. In this way, dex of different channels can be guaranteed to be consistent.
  4. ApkChannelPackage /gradle reBuildChannel: /gradle reBuildChannel: /gradle reBuildChannel: /gradle reBuildChannel: /gradle reBuildChannel: Developers can build their own localMaven to test and modify the repoThe authors have fixed several problems
  5. There are some other pits I can’t remember…

The resources

Tinker Android new generation multi-channel packaging magic wechat Tinker patch management TinkerDemo