zoukankan      html  css  js  c++  java
  • tinker接入

    对于热修复无非就是两大类,一类是tencent代表的classloader模式的,另一类是阿里系代表的底层方面替换。

    下面以本人的经验介绍下微信的tinker接入:

        命令行接入方式; gradle接入方式

    1. 核心库引入,在你应用的app模块下build.gradle文件加入

    //tinker hotfix
    //可选,用于生成application类
    // compileOnly("com.tencent.tinker:tinker-android-anno:${TINKER_VERSION}")
    //tinker's main Android lib
    implementation "com.tencent.tinker:tinker-android-lib:${TINKER_VERSION}"

    如果应用开启了multiDex(一般应用都会用到),还必须加入如下配置
    defaultConfig {
      ...
       ...

    multiDexEnabled true
    //必须打入第一个dex包的java类
    multiDexKeepProguard file("tinker_multidexkeep.pro")

    }
    当然其实上述采用的是proguard方式加入到Main dex中,当然也可以采用multiDexKeepFile方式(一行一个类形式)
    主要目的就是确保tinker的包中类分到第一个dex中,具体可以参考:https://juejin.im/entry/5893e54f128fe100654763a0
    https://www.kancloud.cn/alex_wsc/artist/481985https://blog.csdn.net/zhangbuzhangbu/article/details/52770939

    其实关于分包模式的问题,可以参考我的一片博文: https://www.cnblogs.com/linghu-java/p/10983671.html
    https://www.kancloud.cn/alex_wsc/android_plugin/481528

    2、一般应用的application都有很多特殊的初始化和配置的内容,所以这里不打算使用注解生成application的方式,而是自己加入tinker的内容。
    明文写出Application的构造函数,在里面调用super类TinkerApplication的构造函数
      public class WishApplication extends TinkerApplication {
        public WishApplication(){
        super(//tinkerFlags, which types is supported dex only, library only, all support
      ShareConstants.TINKER_ENABLE_ALL,
      // This is passed as a string so the shell application does not
      // have a binary dependency on your ApplicationLifeCycle class.
      "com.yunzhiyuan100.wish.SimpleApplicationLike");
        }
    }
    如果本来extends MultiApplictiaon的话就要换成 extends TinkerApplication了,然后重写attachBaseContext()方法,在该方法里加入MultiDex的内容。
    如下

    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
    MultiDex.install(this);
    }
    然后就是你原来Application的代码逻辑的内容,可以不用变动
    3. 然后自定义Application中初始化函数用到ApplicationLike类参数实例,可以直接按照tinker给的代码拷贝
     1 public class SimpleApplicationLike extends ApplicationLike {
     2 
     3     public SimpleApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag,
     4                                  long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
     5         super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
     6     }
     7 
     8     @Override
     9     public void onBaseContextAttached(Context base) {
    10         super.onBaseContextAttached(base);
    11 
    12     }
    13     @Override
    14     public void onCreate() {
    15         super.onCreate();
    16         TinkerInstaller.install(this);
    17     }
    18 
    19     @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    20     public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback) {
    21         getApplication().registerActivityLifecycleCallbacks(callback);
    22     }
    23 
    24 }

     4. proguard改变

    1 #your dex.loader pattern here
    2 -keep class com.tencent.tinker.loader.**
    3 #注意 AndroidManifest.xml中的applicaion
    4 -keep class com.yunzhiyuan100.wish.WishApplication
    5 
    6 # ***************** Tinker patch包
    7 # 打替换apk包的时候需要
    8 -applymapping mapping.txt

    然后就可以打包了,打old.apk的时候自动生成mapping.txt, 第二次打new.apk包的时候为了保持混淆的一致性,要使用第一混淆的时候的mapping文件,

    -applymapping mapping.txt

    5.  AndroidManifest修改,application标签下面加入

    1 <meta-data
    2     android:name="TINKER_ID"
    3     android:value="20190604" />
    6.下载Thinker的项目 

      tinker提供了patch生成的工具,源码见:tinker-patch-cli,打成一个jar就可以使用,并且提供了命令行相关的参数以及文件。

           tinker的项目地址: https://github.com/Tencent/tinker

           然后通过android studio打开整个项目

      (1). 在控制台输入:./gradlew buildTinkerSdk    (window上gradlew buildTinkerSdk)

          在指定路径看到生成的文件之后,将刚才生成的old.apk和new.apk拷贝进去。

           (2). 修改tinker_config.xml

        loader修改成自己的application

        <issue id="dex">
            <!--only can be 'raw' or 'jar'. for raw, we would keep its original format-->
            <!--for jar, we would repack dexes with zip format.-->
            <!--if you want to support below 14, you must use jar-->
            <!--or you want to save rom or check quicker, you can use raw mode also-->
            <dexMode value="jar"/>
    
            <!--what dexes in apk are expected to deal with tinkerPatch-->
            <!--it support * or ? pattern.-->
            <pattern value="classes*.dex"/>
            <pattern value="assets/secondary-dex-?.jar"/>
    
            <!--Warning, it is very very important, loader classes can't change with patch.-->
            <!--thus, they will be removed from patch dexes.-->
            <!--you must put the following class into main dex.-->
            <!--Simply, you should add your own application {@code tinker.sample.android.SampleApplication}-->
            <!--own tinkerLoader {@code SampleTinkerLoader}, and the classes you use in them-->
            <loader value="com.tencent.tinker.loader.*"/>
            <loader value="com.yunzhiyuan100.wish.WishApplication"/>
        </issue>

    另外,如果是正式包,需要修改签名配置为你项目的签名,还需要把签名文件yunzhiyuan.jks放到buildSDK的目录build下面

      <!--sign, if you want to sign the apk, and if you want to use 7zip, you must fill in the following data-->
        <issue id="sign">
            <!--the signature file path, in window use \, in linux use /, and the default path is the running location-->
            <path value="yunzhiyuan.jks"/>
            <!--storepass-->
            <storepass value="bgsb1709@hzyzy"/>
            <!--keypass-->
            <keypass value="bgsb1709@hzyzy"/>
            <!--alias-->
            <alias value="wish"/>
        </issue>

    (3)最后就可以执行patch命令打出差异包了

      命令行如下: 

      java -jar tinker-patch-cli-1.9.13.jar -old old.apk -new new.apk -config tinker_config.xml -out output

    注意tinker-patch-cli这个jar包的名字要和buildSdk/build/目录下的该jar包版本名称一致

    把打出来的差异包adb push 到sdcard目录下: adb push patch_sign.apk   /sdcard/

    然后在MainActivity中加载差异包,通过加入一个按钮的点击调用下面的loadFix()函数

    1 public void loadFix(){
    2   TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(),
    3   Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed.apk");
    4 }

    这里调用loadFix()之后,应用会被关闭,再次打开,测试得到想要的修改结果。

    大功告成了

    参考:

        https://blog.csdn.net/YANGDAHUAN/article/details/81021801

        https://blog.csdn.net/lmj623565791/article/details/54882693

        https://github.com/Tencent/tinker

        https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97

        https://blog.csdn.net/cjw8990/article/details/79117880

  • 相关阅读:
    小记---------idea新手操作
    超时问题
    python-post
    python之cookies
    python 爬虫--下载图片,下载音乐
    如何获取字符串中某个具体的数值--通过json.load转化成字典形式获取
    json
    斐波那契数列
    约瑟夫环
    python 求从1加到100的和,join的用法
  • 原文地址:https://www.cnblogs.com/linghu-java/p/10984255.html
Copyright © 2011-2022 走看看