Tinker,是微信开源的Android热修复框架,也时在不久前才开源的,之前开源的框架也有很多,比如QZone,AndFix,Dexposed,不过Dexposed不支持全平台,AndFix无法实现类替换,QZone主要是插桩带来的Dalvik的性能问题,而Tinker不仅支持类替换,还支持全平台2.x-7.x,补丁的大小也远远小于其他方案,这都是TInker的优点。Github上Tinker的Demo写的有点复杂,一开始没看懂怎么用的,弄了前前后侯加起来快一天的时间。下面给他打介绍下Tinker的简单用法。
市热修复框架对比:
使用步骤:
1.在project的build.gradle中添加:classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.7.1')
在app的gradle中添加:
compile("com.tencent.tinker:tinker-android-lib:1.7.1")
compile("com.tencent.tinker:tinker-android-anno:1.7.1")
2.在app的dependencies外面添加配置信息:
//添加配置
apply plugin: 'com.tencent.tinker.patch'
//全局信息相关的配置项
tinkerPatch {
//有问题的apk的地址 准apk包的路径,必须输入,否则会报错
oldApk = "C://Users/Admin/Desktop/HotFix/apkSource/app_old.apk"
//
ignoreWarning = false
//在运行过程中,需要验证基准apk包与补丁包的签名是否一致,我们是否需要为你签名
useSign = true
//编译相关的配置项
buildConfig {
//在运行过程中,我们需要验证基准apk包的tinkerId是否等于补丁包的tinkerId。
// 这个是决定补丁包能运行在哪些基准包上面,一般来说我们可以使用git版本号、versionName等等。
tinkerId = "1.0"
}
//用于生成补丁包中的'package_meta.txt'文件
packageConfig {
//onfigField("key", "value"), 默认我们自动从基准安装包与新安装包的Manifest中读取tinkerId,并自动写入configField。
// 在这里,你可以定义其他的信息,在运行时可以通过TinkerLoadResult.getPackageConfigByName得到相应的数值。
// 但是建议直接通过修改代码来实现,例如BuildConfig。
configField("TINKER_ID", "1.0")
}
//dex相关的配置项
dex {
//只能是'raw'或者'jar'。
//对于'raw'模式,我们将会保持输入dex的格式。
//对于'jar'模式,我们将会把输入dex重新压缩封装到jar。
// 如果你的minSdkVersion小于14,你必须选择‘jar’模式,而且它更省存储空间,但是验证md5时比'raw'模式耗时()
dexMode = "jar"
//需要处理dex路径,支持*、?通配符,必须使用'/'分割。路径是相对安装包的,例如/assets/...
pattern = ["classes*.dex", "assets/secondary-dex-?.jar"]
//它定义了哪些类在加载补丁包的时候会用到。这些类是通过Tinker无法修改的类,也是一定要放在main dex的类。
loader = ["com.tencent.tinker.loader.*", "com.tinkertest.Application"]
/**
* 这里需要定义的类有:
1. 你自己定义的Application类;
2. Tinker库中用于加载补丁包的部分类,即com.tencent.tinker.loader.*;
3. 如果你自定义了TinkerLoader,需要将它以及它引用的所有类也加入loader中;
4. 其他一些你不希望被更改的类,例如Sample中的BaseBuildInfo类。这里需要注意的是,
这些类的直接引用类也需要加入到loader中。或者你需要将这个类变成非preverify。
*/
}
//lib相关的配置项
lib {
//需要处理lib路径,支持*、?通配符,必须使用'/'分割。与dex.pattern一致, 路径是相对安装包的,例如/assets/...
pattern = ["lib/armeabi/*.so", "lib/arm64-v8a/*.so", "lib/armeabi-v7a/*.so", "lib/mips/*.so", "lib/mips64/*.so", "lib/x86/*.so", "lib/x86_64/*.so"]
}
//res相关的配置项
res {
pattern = ["res/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
//对于修改的资源,如果大于largeModSize,我们将使用bsdiff算法。
// 这可以降低补丁包的大小,但是会增加合成时的复杂度。默认大小为100kb
largeModSize = 100
}
//7zip路径配置项,执行前提是useSign为true
sevenZip {
//例如"com.tencent.mm:SevenZip:1.1.10",将自动根据机器属性获得对应的7za运行文件,推荐使用。
zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
}
}
3.建立自己的application:
@DefaultLifeCycle(
application = "cn.tinker.com.mytinker.Application",
flags = ShareConstants.TINKER_ENABLE_ALL
)
//
其中application属性中的内容是包名加上类名,类名由自己随便定义,只要到时候与manifest中的声明一致就行, * Application是有TInker来自动生成的,application="com.xxxx.Application"就是被自动生成的Application;public class MyApp extends DefaultApplicationLike {
public MyApp(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent, Resources[] resources, ClassLoader[] classLoader, AssetManager[] assetManager) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent, resources, classLoader, assetManager);
}
/**
* 重写DefaultApplicationLike方法
* @param base
*/
@Override
public void onBaseContextAttached(Context base) {
super.onBaseContextAttached(base);
TinkerInstaller.install(this);
}
}
4.配置manifest:
配置完manifest 会报错 构建下项目就好了;
5.
public class MainActivity extends AppCompatActivity {
private Button btn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btn= (Button) findViewById(R.id.btn);
TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), Environment.getExternalStorageDirectory().getAbsolutePath() + "/HotFix/patch_signed_7zip.apk");
btn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(MainActivity.this, "错误的《《《", Toast.LENGTH_SHORT).show();
}
});
}
}
6.
下一步就是打包项目,运行apk在手机上;点击按钮 肯定toast“错误的<<<”内容;
然后修改toast里面的内容 保存;
根据上图指示操作 双击tinkerPatchDebug;
等生成差异文件成功!
找到图中选中的文件;
Tinker输出文件详解和接入中文指南:点击打开
在MainActivity中 为了加载方便,我把文件放在了手机HotFix目录下;
对源码和原理感兴趣的可以去看看:点击查看