zoukankan      html  css  js  c++  java
  • Tinker 热修复

     集成方式:

    第一步:在project  build.gradle 文件中添加:

    dependencies {
        // Tinker
        classpath("com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:${TINKERPATCH_VERSION}") { changing = true }
    }

    第二步:在app的  build.gradle 文件中添加  

    //apply tinker插件 最上面
    apply plugin: 'com.tencent.tinker.patch'
    apply from: 'tinkerpatch.gradle'
    
    android {
    buildTypes {
            release {
                minifyEnabled false
    //            proguardFiles getDefaultProguardFile('proguard-android.txt')
                signingConfig signingConfigs.debug
            }
            debug {
                debuggable true
                minifyEnabled false
                signingConfig signingConfigs.debug
            }
        }
    
        signingConfigs {
            release {
                storeFile rootProject.file("keystore/Android.keystore")
                storePassword 'jjjj'
                keyAlias 'kkkk'
                keyPassword 'mmm'
            }
    
            debug {
                storeFile rootProject.file("keystore/debug.keystore")
            }
    lintOptions {
        abortOnError false
    }
    }
    
    
    configurations.all {
        resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    }
    
    dependencies {
    // 热修复
    //无需引入tinker的任何库,使用tinkerpatch sdk即可
    implementation("com.tinkerpatch.sdk:tinkerpatch-android-sdk:${TINKERPATCH_VERSION}") { changing = true }
    
    implementation 'com.google.guava:guava:19.0'
    implementation "org.scala-lang:scala-library:2.11.7"
    
    implementation 'com.android.support:multidex:1.0.1'
    
    } 
     

    tinkerpatch.gradle

    apply plugin: 'tinkerpatch-support'
    import java.util.regex.Matcher
    import java.util.regex.Pattern
    
    /**
     * TODO: 请按自己的需求修改为适应自己工程的参数
     */
    // 基包路径
    def bakPath = file("${buildDir}/bakApk/")
    // 基准包文件夹(打补丁的时候需要修改)
    def baseInfo = "app-1.0.0-0214-16-22-58"
    // 版本名称
    def variantName = "debug"
    
    /**
     * 对于插件各参数的详细解析请参考
     * http://tinkerpatch.com/Docs/SDK
     */
    tinkerpatchSupport {
        /** 可以在debug的时候关闭 tinkerPatch, isRelease() 可以判断BuildType是否为Release **/
        tinkerEnable = true
        reflectApplication = true
        /**
         * 是否开启加固模式,只能在APK将要进行加固时使用,否则会patch失败。
         * 如果只在某个渠道使用了加固,可使用多flavors配置
         **/
        protectedApp = false
        /**
         * 实验功能
         * 补丁是否支持新增 Activity (新增Activity的exported属性必须为false)
         **/
        supportComponent = true
    
        autoBackupApkPath = "${bakPath}"
    
        appKey = "6fa011ee98eb1995"
    
        /** 注意: 若发布新的全量包, appVersion一定要更新 **/
        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"
    
        /**
         * (可选)重命名备份文件的格式化字符串,默认为'${appName}-${variantName}'
         *
         * Available vars:
         * 1. projectName
         * 2. appName
         * 3. packageName
         * 4. buildType
         * 5. versionName
         * 6. versionCode
         * 7. buildTime
         * 8. fileSHA1
         * 9. flavorName
         * 10. variantName
         *
         * default value: '${appName}-${variantName}'
         * Note: plz use single-quotation wrapping this format string
         */
        backupFileNameFormat = '${appName}-${variantName}'
    
        /**
         *  若有编译多flavors需求, 可以参照: https://github.com/TinkerPatch/tinkerpatch-flavors-sample
         *  注意: 除非你不同的flavor代码是不一样的,不然建议采用zip comment或者文件方式生成渠道信息(相关工具:walle 或者 packer-ng)
         **/
    }
    
    /**
     * 用于用户在代码中判断tinkerPatch是否被使能
     */
    android {
        defaultConfig {
            buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
        }
    }
    
    /**
     * 一般来说,我们无需对下面的参数做任何的修改
     * 对于各参数的详细介绍请参考:
     * 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
        }
    }
    
    import java.util.regex.Matcher
    import java.util.regex.Pattern
    
    /**
     * 如果只想在Release中打开tinker,可以把tinkerEnable赋值为这个函数的return
     * @return 是否为release
     */
    def isRelease() {
        Gradle gradle = getGradle()
        String  tskReqStr = gradle.getStartParameter().getTaskRequests().toString()
    
        Pattern pattern;
        if (tskReqStr.contains("assemble")) {
            println tskReqStr
            pattern = Pattern.compile("assemble(\w*)(Release|Debug)")
        } else {
            pattern = Pattern.compile("generate(\w*)(Release|Debug)")
        }
        Matcher matcher = pattern.matcher(tskReqStr)
    
        if (matcher.find()) {
            String task = matcher.group(0).toLowerCase()
            println("[BuildType] Current task: " + task)
            return task.contains("release")
        } else {
            println "[BuildType] NO MATCH FOUND"
            return true;
        }
    }

    注意事项:

    appKey = "6fa011ee98eb1995"  为平台注册的key
    appVersion = "1.0.0":为基础版本的版本号,补丁的appVersion 必须一致  ,还有就是  Tinker platform 新建的版本号也必须一致,否则无法更新


    在application 中初始化:
    package com.xiaozhuyisheng.tinkerdemo;
    
    import android.app.Application;
    import android.content.Context;
    import android.util.Log;
    
    import com.tencent.tinker.entry.ApplicationLike;
    import com.tinkerpatch.sdk.TinkerPatch;
    import com.tinkerpatch.sdk.loader.TinkerPatchApplicationLike;
    
    public class IApp extends Application {
    
        public IApp() {
    
        }
    
        private static final String TAG = "Tinker.SampleApp";
    
        private ApplicationLike tinkerApplicationLike;
    
        @Override
        public void onCreate() {
            super.onCreate();
            initTinkerPatch();
        }
    
        @Override
        protected void attachBaseContext(Context base) {
            super.attachBaseContext(base);
        }
    
        /**
         * 我们需要确保至少对主进程跟patch进程初始化 TinkerPatch
         */
        private void initTinkerPatch() {
            // 我们可以从这里获得Tinker加载过程的信息
            if (BuildConfig.TINKER_ENABLE) {
                tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
                // 初始化TinkerPatch SDK
                TinkerPatch.init(
                        tinkerApplicationLike
    //                new TinkerPatch.Builder(tinkerApplicationLike)
    //                    .requestLoader(new OkHttp3Loader())
    //                    .build()
                )
                        .reflectPatchLibrary()
                        .setPatchRollbackOnScreenOff(true)
                        .setPatchRestartOnSrceenOff(true);
    //                    .setFetchPatchIntervalByHours(3)
                ;
                // 获取当前的补丁版本
                Log.d(TAG, "Current patch version is " + TinkerPatch.with().getPatchVersion());
    
                // fetchPatchUpdateAndPollWithInterval 与 fetchPatchUpdate(false)
                // 不同的是,会通过handler的方式去轮询
    //            TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
            new FetchPatchHandler().fetchPatchWithInterval(3);
            }
        }
    
    
    }

    不要忘记添加以下权限:

    <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"/>

    配置为每三个小时轮询一次是否有新版本,为了验证自己添加了一个按钮,手动更新。

    package com.xiaozhuyisheng.tinkerdemo;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.view.View;
    
    import com.tencent.tinker.lib.util.TinkerLog;
    import com.tinkerpatch.sdk.TinkerPatch;
    import com.tinkerpatch.sdk.server.callback.ConfigRequestCallback;
    
    import java.util.HashMap;
    
    public class MainActivity extends AppCompatActivity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            findViewById(R.id.btnUpdate).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    TinkerPatch.with().fetchPatchUpdate(true);
                }
            });
    
            findViewById(R.id.addNewPage).setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    OtherActivity.startPage(MainActivity.this);
                }
            });
        }
    }

    如何生成基准包: 

     基准包位置:

  • 相关阅读:
    假期周总结报告(五)
    java 原码反码及补码 总结
    java ==与equals()方法的总结
    java String 类型总结
    java 全局变量 的小结
    java static语句的总结
    ATM开学测试(未完成)
    第七周学习进度总结
    第六周学习进度总结
    第五周学习进度总结
  • 原文地址:https://www.cnblogs.com/jiayonghua/p/10382354.html
Copyright © 2011-2022 走看看