[toc]
關(guān)閉Tinker Gradle 編譯插件后 Android 5.0版本以下機(jī)型運(yùn)行Crash分析報(bào)告
一、再現(xiàn)場(chǎng)景
集成Tinker并使用tinkerEnabled = false關(guān)閉Tinker Gradle 編譯插件開關(guān))運(yùn)行在華為CHM-UL00( Android版本4.4.2)直接crash谱俭,根據(jù)目前手中測(cè)試機(jī)測(cè)試后奉件,Android版本5.0以下手機(jī)都會(huì)出現(xiàn)同樣的問(wèn)題宵蛀,5.0以上均運(yùn)行正常。
二术陶、錯(cuò)誤日志
Caused by: com.tencent.tinker.loader.TinkerRuntimeException: Tinker Exception:createDelegate failed
Tinker.UncaughtHandler: catch exception when loading tinker:java.lang.RuntimeException: Unable to instantiate application com.iflytek.elpmobile.smartlearning.ThisApplication: com.tencent.tinker.loader.TinkerRuntimeException: Tinker Exception:createDelegate failed
三、原因分析
故根據(jù) Android版本5.0前后現(xiàn)象不同和錯(cuò)誤日志分析煤痕,懷疑問(wèn)題與分Dex方案Multidex在Android 5.0前后版本引用策略不同有關(guān)摆碉。經(jīng)查詢:
Multidex支持Android 5.0之前的版本 : Android5.0版本的平臺(tái)之前巷帝,Android使用的是Dalvik Runtime執(zhí)行的程序代碼楞泼。默認(rèn)情況下驰徊,限制應(yīng)用到一個(gè)單一的classes.dex棍厂。Dalvik字節(jié)碼文件每APK超陆。為了繞過(guò)這個(gè)限制勋桶,你可以使用multidex支持庫(kù),成為你的應(yīng)用程序的主要部分和DEX文件進(jìn)行管理侥猬,獲得額外的dex文件,它們包含的代碼捐韩。
Multidex支持Android 5.0及更高版本 : Android 5.0和更高的Runtime 如art退唠,本身就支持從應(yīng)用的APK文件加載多個(gè)DEX文件。art支持預(yù)編譯的應(yīng)用程序在安裝時(shí)掃描類(..)荤胁。Dex文件編譯成一個(gè)單一的Android設(shè)備上執(zhí)行.oat文件瞧预。
- Tinker需要確保下述文件放在主dex中:
- ApplicationLike實(shí)現(xiàn)類以及它的直接引用類
- 在調(diào)用Multidex install之前加載的類
- com.tencent.tinker.loader.*類
- 自定義了TinkerLoader類
- 而關(guān)閉tinkerEnabled后,Tinker Gradle 編譯插件 中 生成需要放在主dex的keep規(guī)則和相關(guān)文件混淆的keep規(guī)則 的自動(dòng)處理腳本 均不會(huì)執(zhí)行仅政,所以需要手動(dòng)配置相關(guān)keep規(guī)則
四. 解決方案
- 方案一:打開tinkerEnabled = true垢油,測(cè)試均運(yùn)行正常。
- 方案二:關(guān)閉tinkerEnabled false圆丹,并如下手動(dòng)引入分包策略文件滩愁,測(cè)試均運(yùn)行正常,步驟如下:
- 首先暫時(shí)打開tinkerEnabled = true辫封,使插件生成需要放在主Dex的keep規(guī)則硝枉。
- 然后將app/build/intermediates/tinker_intermediates/tinker_multidexkeep.pro(生成的keep規(guī)則文件)拷貝到主Module目錄下廉丽,在主Module的app build中配置該規(guī)則:
defaultConfig { multiDexKeepProguard file("./tinker_multidexkeep.pro") }
五、keep規(guī)則
#tinker multidex keep patterns:
#proguardFiles adds
-keep public class * implements com.tencent.tinker.loader.app.ApplicationLifeCycle {
<init>(...);
void onBaseContextAttached(android.content.Context);
}
-keep public class * extends com.tencent.tinker.loader.TinkerLoader {
<init>(...);
}
-keep public class * extends android.app.Application {
<init>();
void attachBaseContext(android.content.Context);
}
-keep class com.tencent.tinker.loader.TinkerTestAndroidNClassLoader {
<init>(...);
}
-keep class com.iflytek.elpmobile.smartlearning.ThisApplication {
<init>(...);
}
-keep class com.tencent.tinker.loader.** {
<init>(...);
}