如今的Android项目,大部分都离不开热更新这项技术。因为公司须要,入坑Tinker,结果发现dex以及资源文件,能够替换。而So文件,Log日志提示替换成功,而使用时很差使。因此有了该文章。也算时把我踩的坑记录一下,给你们加快点效率。android
更新Dex,资源文件,以及So库文件git
简单说下Tinker的原理。经过算法,将新的更新的APK和原版的BaseApk之间的差别生成一个Patch补丁包。将补丁包发送到手机本地,在用户打开手机时将补丁包加载进手机。更加具体的原理,此处不作叙述。程序员
classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.9.1')
复制代码
//application为生成的Application的名称。flags为能够替换的类型,这里TINKER_ENABLE_ALL为全均可以替换(dex,资源文件,so库)
@DefaultLifeCycle(application = ".TestTinkerApplication",flags = ShareConstants.TINKER_ENABLE_ALL
)
public class TestTinkerLike extends DefaultApplicationLike {
private static TestTinkerLike mTestTinkerLike;
public TestTinkerLike(Application application, int tinkerFlags, boolean tinkerLoadVerifyFlag, long applicationStartElapsedTime, long applicationStartMillisTime, Intent tinkerResultIntent) {
super(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent);
mTestTinkerLike=this;
}
/**
* 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); TinkerManager.fastInstallAll(this); } public static TestTinkerLike getmTestTinkerLike(){ return mTestTinkerLike; } } 复制代码
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
} else {
TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk");
}
复制代码
String CPU_ABI = android.os.Build.CPU_ABI;
// 将tinker library中的 CPU_ABI架构的so 注册到系统的library path中。
TinkerLoadLibrary.installNavitveLibraryABI(MainActivity.this, CPU_ABI);
复制代码
String CPU_ABI = android.os.Build.CPU_ABI;
boolean a=TinkerLoadLibrary.loadLibraryFromTinker(getApplicationContext(), "lib/" + CPU_ABI, "native-lib");
复制代码
TinkerLoadLibrary.loadArmLibrary(getApplicationContext(), "native-lib");
复制代码
TinkerApplicationHelper.loadArmV7aLibrary(TestTinkerLike.getmTestTinkerLike(), "native-lib");
复制代码
这里有两个类能够加载So文件,TinkerLoadLibrary和TinkerApplicationHelper 不过他们的原理时同样的,不知道做者为何封了两个。github
so文件是打补丁的时候自动加载的,可是却须要手动的链一下,至关于,基础apk自己的so文件A。在打补丁的时候加载了so文件B。此时有两个so文件。你每次都要手动的用上面的方法加载so库B。不然默认调用的仍是基础APK的so文件A中的方法。一旦你在加载so库前,调用了A中的方法,默认加载的是so库A。此时你要调用so库B中 新增的方法(so库B中有,可是so库A中没有的方法)。就会报错。算法
基础文件,以及补丁包。如图所示! 切记,第一次的时候因为没有权限,须要手动打补丁。 bash
若是文章有什么错误,请及时指正。好比权限的问题,我这里是必须申请的。好比so文件同时存在,而不是替换,也是我的猜想,有时间我会去证明。但愿你们一同进步。架构
特别注意中这个简单的逻辑,却难了我3天的时间,因为大部分集成tinker的,只要替换资源文件和dex便可。因此几乎很难找到so没法生效的缘由。也算是为后来人,铺了个路。后续会上代码和图片。但愿你们点个喜欢,关注。仍是老话,风力雨里,都在这里等你,大家的关注是我最大的动力。感谢各位了,一个入坑JNI开发的小Android程序员的诉求。感谢各位大佬啦。app