Tinker初体验


微信开源了自己的热修复Tinker库,一直没用过,所以想搞一个小Demo来体验一下

什么是Tinker?


Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。

Tinker 传送门:github主页 wiki介绍 Tinker的接入指南

开始接入


Tinker 的sample 的地址为 sample

1、gradle配置

参照 Tinker sample的做法 在 gradle.properties文件末尾添加

TINKER_VERSION=1.7.11

在项目的 build.gradle 中指定classpath

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        classpath 'com.android.tools.build:gradle:2.2.2'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
        classpath "com.tencent.tinker:tinker-patch-gradle-plugin:${TINKER_VERSION}"
    }
}

参考 sample 的build.gradle 进行配置

1、在android {}标签中添加 签名配置

signingConfigs {
        release {
            try {
                storeFile file("./keystore/release.keystore")
                storePassword "testres"
                keyAlias "testres"
                keyPassword "testres"
            } catch (ex) {
                throw new InvalidUserDataException(ex.toString())
            }
        }

        debug {
            storeFile file("./keystore/debug.keystore")
        }
    }

2、在dependencies{}标签添加核心库

 compile("com.tencent.tinker:tinker-android-lib:${TINKER_VERSION}") { changing = true }
    provided("com.tencent.tinker:tinker-android-anno:${TINKER_VERSION}") { changing = true }

3、其余粘贴sample 中的 配置但是要进行修改

注意修改 ignoreWarning = true **
修改
tinkerId = "tinkerId" //getTinkerIdValue()**

如果涉及到 getTinkerIdValue 的都修改成 tinkerId

然后编译就能通过了

2、Application配置

与以往的很多库不同,这里并不是在自定义的Application 中进行初始化之类的‘

@SuppressWarnings("unused")
@DefaultLifeCycle(application = ".SampleApplication",
        flags = ShareConstants.TINKER_ENABLE_ALL,
        loadVerifyFlag = false)
public class SampleApplicationLike extends DefaultApplicationLike {
    private static final String TAG = "Tinker.SampleApplicationLike";

    public SampleApplicationLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag,
                                 long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
        super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
    }

    /**
     * install multiDex before install tinker
     * so we don't need to put the tinker lib classes in the main dex
     *
     * @param base
     */
    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    @Override
    public void onBaseContextAttached(Context base) {
        super.onBaseContextAttached(base);
        //you must install multiDex whatever tinker is installed!
        MultiDex.install(base);

        TinkerInstaller.install(this);
    }

    @TargetApi(Build.VERSION_CODES.ICE_CREAM_SANDWICH)
    public void registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks callback) {
        getApplication().registerActivityLifecycleCallbacks(callback);
    }

}

AndroidManifest.xml 文件进行配置




  
      

      
    
        
            
                

                
            
        
    


3、配置结束开始测试使用

module 执行DeBug 运行,将项目打包生成 apk 文件,运行在手机中。以App为例,会 在 build-> badApk->生成Apk文件 文件是以 日期时间来命名的 ,比较好区分

Tinker初体验_第1张图片
bad_apk_gen

修改配置 build.gradle 文件

//for normal build
//old apk file to build patch apk
tinkerOldApkPath = "${bakPath}/app-debug-0629-17-10-31.apk"   //这里配置  刚刚生成的  oldApk 文件
//proguard mapping file to build patch apk
tinkerApplyMappingPath = "${bakPath}/app-debug-1018-17-32-47-mapping.txt" //proguard的map映射文件
//resource R.txt to build patch apk, must input if there is resource changed
tinkerApplyResourcePath = "${bakPath}/app-debug-0629-17-10-31-R.txt"   //如果修改了 resource内容,将该文件也更新到最新

修改项目中的代码,并构建 差异包

修改MainActivity 中的代码

public class MainActivity extends AppCompatActivity {

    private TextView test_main;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        test_main = (TextView) findViewById(R.id.test_main);
        //在差异包中修改了  界面中的显示文本   "I am In Path Apk"
        test_main.setText("I am In Patch Apk");
    }

    public void loadPath(View view) {
        String path = Environment.getExternalStoragePublicDirectory(DOWNLOAD_SERVICE).getAbsolutePath() + "/patch_signed_7zip.apk";
        File file = new File(path);
        if (file.exists()) {
            Toast.makeText(this, "补丁存在", Toast.LENGTH_SHORT).show();
            TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), path);
        } else {
            Toast.makeText(this, "补丁不存在", Toast.LENGTH_SHORT).show();
        }
    }
}

修改完成执行 tinker 的 gradle 命令 tinkerPatchDebug

可以在命令行或者这里点击运行,然后等待 构建生成 patch 包

Tinker初体验_第2张图片

在此过程中可能会失败,重试一次,生成的差异包会在该目录下:

Tinker初体验_第3张图片

将生成的 patch_signed_7zip.apk 文件 导入到sd卡中,但是导入到哪个目录呢?看下面的代码

    public void loadPath(View view) {
      //这里制定了  加载差异包的文件名和目录
        String path = Environment.getExternalStoragePublicDirectory(DOWNLOAD_SERVICE).getAbsolutePath() + "/patch_signed_7zip.apk";
        File file = new File(path);
        if (file.exists()) {
            Toast.makeText(this, "补丁存在", Toast.LENGTH_SHORT).show();
            TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), path);
        } else {
            Toast.makeText(this, "补丁不存在", Toast.LENGTH_SHORT).show();
        }
    }

导入的目录要与 代码中的目录保持一致

再次运行刚刚打包到手机中的应用 点击 loadPath按钮看效果如下

Tinker初体验_第4张图片

这里只是体验了一下Tinker的简单实用,具体在项目中的使用还需要进一步的去研究,相信还有很多坑在等着我!

Tinker初体验_第5张图片

你可能感兴趣的:(Tinker初体验)