首先解释下tinker是什么,官方如是解释:Tinker是微信官方的Android热补丁解决方案,它支持动态下发代码、So库以及资源,让应用能够在不需要重新安装的情况下实现更新。当然,你也可以使用Tinker来更新你的插件。看到这,应该知道它的厉害了吧,支持动态下发代码、So库以及资源,第二它已经正式运用于有7、8亿用户的微信上了;比起阿里的andifx只能用作方法替换,这太强大了;因此作为app的开发,我们应该了解怎么使用tinker。
由于tinker的基本集成官方也有说明,https://github.com/Tencent/tinker,因此基本的配置方面我就不说明了,重点说明下大家需要注意的地方。
1,module的gradle依赖后面带了 chang true如下:
provided('com.tencent.tinker:tinker-android-anno:1.7.7') { changing true } compile('com.tencent.tinker:tinker-android-lib:1.7.7') { changing true }2,tinker插件照抄官方sample便可
if (buildWithTinker()) { apply plugin: 'com.tencent.tinker.patch' tinkerPatch {3,调试的时候如果 tinkerEnabled = true,而你的项目又没有使用git版本控制,记得修改此处,如下。否则编译不通过
def gitSha() { try { // String gitRev = 'git rev-parse --short HEAD'.execute(null, project.rootDir).text.trim() String gitRev = 100// 此参数变化,tinker会删除app下载过的patch4,为了便于发布补丁包,ext位置处建议修改如我。这样每次打补丁包就不用麻烦去修改tinkerOldApkPath、tinkerApplyMappingPath、tinkerApplyResourcePath、tinkerBuildFlavorDirectory 这些变量了。
def bakName="app-debug-0401-16-44-51"//每次编译了新apk,注意记得修改此处 ext { //for some reason, you may want to ignore tinkerBuild, such as instant run debug build? tinkerEnabled = true //for normal build //old apk file to build patch apk tinkerOldApkPath = "${bakPath}/${bakName}.apk" //proguard mapping file to build patch apk tinkerApplyMappingPath = "${bakPath}/${bakName}-mapping.txt" //resource R.txt to build patch apk, must input if there is resource changed tinkerApplyResourcePath = "${bakPath}/${bakName}-R.txt" //only use for build all flavor, if not, just ignore this field tinkerBuildFlavorDirectory = "${bakPath}/${bakName}" }
5,baseApk和相对应patch apk的gitRev要一致,tinker才会加载成功。每次发布新的版本(不是patch),记得修改gitRev的值,一般加1即可,新版本安装后tinker加载的时候就会把旧版本的patch删除
为了统计补丁下发的应用情况,我们需要做统计。看了下tinkerPatch的后台,感觉做的还听好的,试用挺好,就是免费版的使用次数有限,而付费版的公司又不愿意拿钱购买,因此打算自己实现下tinker的统计功能。
1,patch下载次数统计,这个因人而已,我的做法是通过downloadManager下载,下载成功后请求patch下载成功接口,更新下载成功数。
2,patch应用成功统计,自定义一个类MyTinkerResultService,以此统计patch加载成功数
package com.tinkertest; import com.tencent.tinker.lib.service.DefaultTinkerResultService; import com.tencent.tinker.lib.service.PatchResult; import com.tencent.tinker.lib.util.TinkerLog; /** * 补丁加载成功服务回调 * 切记在manifest文件注册此service,否则会报找不到service * Created by 黄海 on 2017/4/1. */ public class MyTinkerResultService extends DefaultTinkerResultService { private static final String TAG = "Tinker.MyTinkerResultService"; @Override public void onPatchResult(PatchResult result) { if (result != null) { TinkerLog.i(TAG, "补丁加载成功 patchInfo=" + result); /** * 补丁加载成功,note!此处不代表应用成功 *此处做的事情发送请求告诉服务器补丁加载成功(if need) */ } super.onPatchResult(result); } }判断服务器是否有最新补丁要加载,自定义一个类MyLoadReporter,
package com.tinkertest; import android.content.Context; import com.tencent.tinker.lib.reporter.DefaultLoadReporter; import com.tencent.tinker.lib.tinker.Tinker; import com.tencent.tinker.lib.util.TinkerLog; import com.tencent.tinker.loader.shareutil.ShareConstants; import java.io.File; /** * 补丁应用统计 * Created by 黄海 on 2017/4/1. */ public class MyLoadReporter extends DefaultLoadReporter { private static final String TAG = "Tinker.MyLoadReporter"; private Context context; public MyLoadReporter(Context context) { super(context); this.context = context; } @Override public void onLoadResult(File patchDirectory, int loadCode, long cost) { if (loadCode == ShareConstants.ERROR_LOAD_OK) { /** * currentVersion 就是应用成功的的patch file 的文件MD5 * 根据loadCode统计补丁应用情况:如果加载成功,则根据currentVersion与服务器最新的patch文件 * md5做对比,以此判断是否有最新patch需要下载;如果加载失败(一般此版本没有发布过补丁),则 * 请求服务器此版本是否有补丁,有则下载,无则不理会 */ String currentVersion = Tinker.with(context).getTinkerLoadResultIfPresent().currentVersion; TinkerLog.i(TAG, "当前补丁信息:md5=" + currentVersion); } super.onLoadResult(patchDirectory, loadCode, cost); } }然后在你的DefaultApplicationLike子类的onCreate方法把上面定义的两个类带入初始化tinker,
ok,这样就完成了tinker补丁的应用统计了,整体感觉下来难度中等。TinkerInstaller.install(this, new MyLoadReporter(getApplication()), new DefaultPatchReporter(getApplication()), new DefaultPatchListener(getApplication()) , MyTinkerResultService.class, new UpgradePatch());
下面附上本文的项目源码
https://github.com/haipinghuang/TinkerWithServer
再附上一个功能类似tinkerPatch服务端的代码,https://github.com/haipinghuang/tinkerServer
开发IDE是idea,采用spring+springmvc+mybatis+maven+mysql实现,数据库结构文件在webApp/static文件夹
欢迎大家star,提意见!!!