Tinker是一款优秀的热修复框架,它是基于TINKER_ID来对基准包进行修复的,比如旧版本的包(即安装在手机的包)和新旧版本包的补丁,它们的TINKER_ID应该是一样的,那么它就可以修复。
配置apt选项
javaCompileOptions {
// Tinker需要
annotationProcessorOptions {
includeCompileClasspath = true
}
}
代码混淆
multiDexKeepProguard file("tinker_multidexkeep.pro")
修复逻辑
比如Host+补丁A,会换成Host+补丁B,而不是Host+A+B
关键类
class MusicApp(private val application: Application?) : Application(), AppConfig {
var mediaManager: MediaManager? = null
private set
private var refWatcher: RefWatcher? = null
companion object {
@JvmStatic var instance: MusicApp? = null
private set
}
override fun attachBaseContext(base: Context) {
super.attachBaseContext(base)
//dex分包
MultiDex.install(base)
}
}
import android.annotation.TargetApi
import android.app.Application
import android.content.Context
import android.content.Intent
import android.os.Build
import androidx.multidex.MultiDex
import com.tencent.tinker.anno.DefaultLifeCycle
import com.tencent.tinker.entry.DefaultApplicationLike
import com.tencent.tinker.lib.tinker.Tinker
import com.tencent.tinker.lib.tinker.TinkerInstaller
import com.tencent.tinker.loader.shareutil.ShareConstants
import site.doramusic.app.MusicApp
import site.doramusic.app.base.conf.AppConfig
import site.doramusic.app.tinker.log.TinkerLog
import site.doramusic.app.tinker.util.TinkerManager
/**
* because you can not use any other class in your application, we need to
* move your implement of Application to [ApplicationLifeCycle]
* As Application, all its direct reference class should be in the main dex.
*
* We use tinker-android-anno to make sure all your classes can be patched.
*
* application: if it is start with '.', we will add SampleApplicationLifeCycle's package name
*
* flags:
* TINKER_ENABLE_ALL: support dex, lib and resource
* TINKER_DEX_MASK: just support dex
* TINKER_NATIVE_LIBRARY_MASK: just support lib
* TINKER_RESOURCE_MASK: just support resource
*
* loaderClass: define the tinker loader class, we can just use the default TinkerLoader
*
* loadVerifyFlag: whether check files' md5 on the load time, defualt it is false.
*
*/
@DefaultLifeCycle(application = "site.doramusic.app.AppLoader", flags = ShareConstants .TINKER_ENABLE_ALL, loadVerifyFlag = false)
class TinkerApplicationLike(application: Application, tinkerFlags: Int, tinkerLoadVerifyFlag: Boolean, applicationStartElapsedTime: Long, applicationStartMillisTime: Long, tinkerResultIntent: Intent?) : DefaultApplicationLike(application, tinkerFlags, tinkerLoadVerifyFlag, applicationStartElapsedTime, applicationStartMillisTime, tinkerResultIntent) {
private var musicApp: MusicApp? = null
init {
musicApp = MusicApp(application)
}
override fun onCreate() {
super.onCreate() musicApp!!.onCreate()
}
/**
* 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 fun onBaseContextAttached(base: Context) {
super.onBaseContextAttached(base)
MultiDex.install(base)
TinkerManager.setTinkerApplicationLike(this)
TinkerManager.initFastCrashProtect()
TinkerManager.setUpgradeRetryEnable(true)
TinkerInstaller.setLogIml(TinkerLog())
TinkerManager.installTinker(this)
TinkerManager.loadPatch(AppConfig.FOLDER_PATCH + "/patch_signed.apk")
Tinker.with(application)
}
}