如今的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