摘要:在爬坑之路一文中講了在接入之后,中的一些坑,由此,熱修復(fù)算告一段落,但是,在直接模式運行時,程序會報出如下錯誤好吧,使用時不能開啟上也有一個同樣的,引入之后如何在模式下開啟,這里我將我的方法講述一下,給大家一個參考。
在《Tinker + Bugly + Jenkins 爬坑之路》一文中講了在接入 Tinker 之后,Jenkins 中的一些坑,由此,熱修復(fù)算告一段落,但是,在直接 Run 模式運行時,程序會報出如下錯誤:
Tinker does not support instant run mode, please trigger build by assembleDebug or disable instant run in "File->Settings...".
好吧,使用 TInker 時不能開啟 Instant Run  ̄□ ̄||
GitHub 上也有一個同樣的 issue,引入Tinker之后如何在Debug模式下開啟Instant Run ,這里我將我的方法講述一下,給大家一個參考。
1. 使用變量標記是否使用 Tinker在 project 的 build.gradle 文件的 ext 中定義變量 tinkerEnabled 用來標記是否使用 TInker,代碼如下所示:
ext { /** * 是否啟用tinker參與編譯 * 開發(fā)時,根據(jù)需要修改值來開啟 * Jenkins 構(gòu)建時,會替換該值 */ tinkerEnabled = rootProject.properties["tinkerEnable"] if (null == tinkerEnabled) { tinkerEnabled = "false" } }
看過《Tinker + Bugly + Jenkins 爬坑之路》的同學(xué)應(yīng)該知道,我司的項目是使用 Jenkins 打包的,所以我這里先通過 rootProject.properties["tinkerEnable"] 從 Gradle 命令中取 tinkerEnabled 參數(shù)的值,然后在構(gòu)建腳本的打包命令行中加入該參數(shù):
sh gradlew assembleRelease -PtinkerEnable=true --stacktrace
這樣,就確保了 Jenkins 構(gòu)建時 tinkerEnable 的值為 true。在開發(fā)過程中,本地運行或者構(gòu)建 apk 就可以通過修改 tinkerEnabled = "false" 來決定是否使用 Tinker 構(gòu)建。
2. 通過標記值決定是否使用 TInker 構(gòu)建接下來在 module 的 build.gradle 文件中,通過 tinkerEnabled 值來判斷是否引入 tinker-support.gradle 構(gòu)建項目,代碼如下:
// 依賴插件腳本-tinker if (Boolean.parseBoolean(rootProject.ext.tinkerEnabled)) { apply from: rootProject.file("gradle/tinker-support.gradle") }3. Java/Kotlin 代碼中通過標記值決定是否初始化 Tinker
在 Java/Kotlin 代碼中,是無法直接使用 gradle 文件中的變量值的,那么在 Java/Kotlin 代碼中,怎么通過上面定義的標記量來決定是否初始化 Tinker 呢?總不能在 Java/Kotlin 代碼中也定義一個全局變量來控制吧,那樣本地開發(fā)時一改就得改兩個地方,不但麻煩而且可能出錯,另外,Jenkins 打包時也無法確定 Java/Kotlin 會初始化 Tinker。
那,怎么辦呢?我們來個“曲線救國”的方法。通過自定義 BuildConfig 屬性來解決,首先,在 module 的 build.gradle 文件中,將 tinkerEnabled 的值傳遞到 BuildConfig 的自定義屬性中,代碼如下:
android { compileSdkVersion rootProject.ext.compileSdkVersion buildToolsVersion rootProject.ext.buildToolsVersion defaultConfig { /** =============自定義 BuildConfig 屬性========================*/ buildConfigField "boolean", "BuildConfig", rootProject.ext.tinkerEnabled /** =============自定義 BuildConfig 屬性========================*/ } }
然后,在自定義的 application 類中添加根據(jù) BuildConfig.BuildConfig 判斷是否初始化 Tinker 的代碼:
package com.cy.sample import android.app.Application import android.content.Context import android.widget.Toast import com.tencent.bugly.Bugly import com.tencent.bugly.beta.Beta import com.tencent.bugly.beta.interfaces.BetaPatchListener import com.tencent.bugly.beta.tinker.TinkerManager.getApplication import java.util.* /** * 類描述。 * * @author cspecialy * @version v1.0.0 */ class MyApplication : Application() { override fun onCreate() { super.onCreate() if (BuildConfig.TINKER_ENABLE) { initTinker() } } /** * 初始化 Tinker */ private fun initTinker() { // 設(shè)置是否開啟熱更新能力,默認為true Beta.enableHotfix = true // 設(shè)置是否自動下載補丁,默認為true Beta.canAutoDownloadPatch = true // 設(shè)置是否自動合成補丁,默認為true Beta.canAutoPatch = true // 設(shè)置是否提示用戶重啟,默認為false Beta.canNotifyUserRestart = true // 補丁回調(diào)接口 Beta.betaPatchListener = object : BetaPatchListener { override fun onPatchReceived(patchFile: String) { Toast.makeText(getApplication(), "補丁下載地址$patchFile", Toast.LENGTH_SHORT).show() } override fun onDownloadReceived(savedLength: Long, totalLength: Long) { Toast.makeText(getApplication(), String.format(Locale.getDefault(), "%s %d%%", Beta.strNotificationDownloading, (if (totalLength == 0L) 0 else savedLength * 100 / totalLength).toInt()), Toast.LENGTH_SHORT).show() } override fun onDownloadSuccess(msg: String) { Toast.makeText(getApplication(), "補丁下載成功", Toast.LENGTH_SHORT).show() } override fun onDownloadFailure(msg: String) { Toast.makeText(getApplication(), "補丁下載失敗", Toast.LENGTH_SHORT).show() } override fun onApplySuccess(msg: String) { Toast.makeText(getApplication(), "補丁應(yīng)用成功", Toast.LENGTH_SHORT).show() } override fun onApplyFailure(msg: String) { Toast.makeText(getApplication(), "補丁應(yīng)用失敗", Toast.LENGTH_SHORT).show() } override fun onPatchRollback() { } } // 設(shè)置開發(fā)設(shè)備,默認為false,上傳補丁如果下發(fā)范圍指定為“開發(fā)設(shè)備”,需要調(diào)用此接口來標識開發(fā)設(shè)備 Bugly.setIsDevelopmentDevice(getApplication(), true) // 多渠道需求塞入 // String channel = WalleChannelReader.getChannel(getApplication()); // Bugly.setAppChannel(getApplication(), channel); // 這里實現(xiàn)SDK初始化,appId替換成你的在Bugly平臺申請的appId Bugly.init(getApplication(), "2a1dc56c3a", true) } override fun attachBaseContext(base: Context) { super.attachBaseContext(base) // you must install multiDex whatever tinker is installed! MultiDex.install(base) if (BuildConfig.TINKER_ENABLE) { // 安裝tinker Beta.installTinker() } } }
以上代碼相信大家也注意到了,是的,我這里 TInker 是使用 enableProxyApplication = true 開啟反射代理的方式,大家如果使用 enableProxyApplication = false 方式的話,方向也一樣,我這里就不贅述了,大家因地制宜哈~~~ O(∩_∩)O哈哈~
接下來,開發(fā)時只需要將 tinkerEnabled 變量的值設(shè)置為 false,就可以愉快的使用 Instant Run 了。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/69706.html
摘要:不過它確實各方面都做了大量的優(yōu)化,本文中的很多知識點也來源于阿里的熱修復(fù)技術(shù)原理一書,本書值得一讀,里面就是基于框架來編排的。 前言;本文框架什么是熱修復(fù)?熱修復(fù)框架分類技術(shù)原理及特點Tinker框架解析各框架對比圖總結(jié)通過閱讀本文,你會對熱修復(fù)技術(shù)有更深的認知,本文會列出各類框架的優(yōu)缺點以及技術(shù)原理,文章末尾簡單描述一下Tinker的框架結(jié)構(gòu)。 一、什么是熱修復(fù)?1.正常開發(fā)流程showI...
閱讀 3004·2021-11-23 09:51
閱讀 1012·2021-09-26 09:55
閱讀 3963·2021-09-22 14:58
閱讀 1493·2021-09-08 09:35
閱讀 1084·2021-08-26 14:16
閱讀 888·2019-08-23 18:17
閱讀 2070·2019-08-23 16:45
閱讀 706·2019-08-23 15:55