熱修復(fù)技術(shù)的實(shí)踐之旅——微信TinkerPatch熱修復(fù)結(jié)合Walle多渠道打包的詳解

本文導(dǎo)語(yǔ):

本文的核心內(nèi)容介紹:
(1)對(duì)比當(dāng)前市場(chǎng)上的熱修復(fù)方案手幢,對(duì)Tinker熱修復(fù)方案進(jìn)行了簡(jiǎn)單的介紹橘原。
(2)詳細(xì)講解了微信Tinker的完整接入過(guò)程,文末提供了一個(gè)自己寫(xiě)的非常輕量的Demo,可以幫助開(kāi)發(fā)者迅速實(shí)現(xiàn)自己項(xiàng)目中熱修復(fù)的接入著隆,將熱修復(fù)技術(shù)運(yùn)用到真實(shí)的項(xiàng)目中离唬,而不僅僅是Demo測(cè)試后专。
(3)加入了walle的多渠道打包方案,能迅速打出很多個(gè)渠道包输莺。詳細(xì)的介紹了真實(shí)項(xiàng)目上線(xiàn)時(shí)APK及補(bǔ)丁包的版本維護(hù)戚哎,如何通過(guò)單個(gè)補(bǔ)丁包,修復(fù)多個(gè)渠道嫂用,進(jìn)行熱修復(fù)的實(shí)現(xiàn)方案型凳。
(4)文章末尾總結(jié)了接入過(guò)程中可能遇到的坑,及相應(yīng)的解決方案嘱函,能幫助你無(wú)障礙的接入Tinker甘畅。以及簡(jiǎn)單的分享了一些關(guān)于熱修復(fù)技術(shù)方面需要儲(chǔ)備的一些技術(shù)知識(shí)。

希望讀完本文的朋友往弓,能對(duì)熱修復(fù)及相關(guān)的技術(shù)和概念疏唾,有比較深的理解。

一函似、Tinker熱修復(fù)方案原理簡(jiǎn)介

1槐脏、騰訊官方介紹:

Tinker is a hot-fix solution library for Android, it supports dex, library and resources update without reinstalling apk.

Tinker 是一個(gè)開(kāi)源項(xiàng)目(Github鏈接),它是微信官方的 Android 熱補(bǔ)丁解決方案撇寞,它支持動(dòng)態(tài)下發(fā)代碼准给、So 庫(kù)以及資源泄朴,讓?xiě)?yīng)用能夠在不需要重新安裝的情況下實(shí)現(xiàn)更新。

image.png

2露氮、Tinker原理理解:

Tinker將old.apk(也就是下面要講到的基準(zhǔn)包祖灰,上線(xiàn)發(fā)布時(shí)的APK)和new.apk,進(jìn)行對(duì)比畔规,得到patch.dex局扶,然后應(yīng)用程序通過(guò)在代碼中加入初始化tinker的代碼,可以實(shí)現(xiàn)在程序運(yùn)行的時(shí)候加載patch.dex(補(bǔ)丁文件)叁扫,然后patch.dex與本機(jī)APK的classex.dex合并三妈,生成新的classes.dex。運(yùn)行時(shí)通過(guò)反射將合并后的dex文件放置在加載的dexElements數(shù)組的前面莫绣。運(yùn)行時(shí)替代的原理畴蒲,其實(shí)和Qzone的方案差不多,都是去反射修改dexElements对室。

3模燥、為什么要使用熱修復(fù)?

(1) 看看傳統(tǒng)的App升級(jí)更新流程:


image.png

如上圖掩宜,隨著移動(dòng)端業(yè)務(wù)復(fù)雜程度的增加蔫骂,傳統(tǒng)的APP更新流程顯然無(wú)法滿(mǎn)足業(yè)務(wù)和開(kāi)發(fā)者的需求,無(wú)論是對(duì)于用戶(hù)還是開(kāi)發(fā)維護(hù)人員牺汤,過(guò)程過(guò)于繁瑣辽旋,不夠靈活。
主要存在以下幾個(gè)弊端:

  • 對(duì)于開(kāi)發(fā)者而言檐迟,重新發(fā)布版本代價(jià)太大补胚。
  • 用戶(hù)下載安裝成本太高,可能失去耐心而直接卸載追迟。
  • bug修復(fù)不及時(shí)糖儡,用戶(hù)體驗(yàn)差。
    (2) 再看看熱修復(fù)的開(kāi)發(fā)流程怔匣,明顯更加靈活。


    image.png

    熱修復(fù)的幾大優(yōu)勢(shì):

  • 無(wú)需重新發(fā)版桦沉,實(shí)時(shí)高效每瞒,開(kāi)發(fā)的維護(hù)成本降低。
  • 補(bǔ)丁靜默安裝纯露,用戶(hù)無(wú)感知就能實(shí)現(xiàn)Bug的修復(fù)剿骨,體驗(yàn)好。
  • 修復(fù)成功率高埠褪,把損失降到最低浓利。
4挤庇、為何選擇使用騰訊的Tinker修復(fù)方案?

當(dāng)前市面的熱補(bǔ)丁方案有很多贷掖,其中比較出名的有阿里的 AndFix嫡秕、美團(tuán)的 Robust 以及 QZone 的超級(jí)補(bǔ)丁方案。但它們都存在無(wú)法解決的問(wèn)題苹威。其中AndFix可能接入是最簡(jiǎn)單的一個(gè)(和Tinker命令行接入方式差不多)昆咽,不過(guò)兼容性還是是有一定的問(wèn)題的;QZone方案對(duì)性能會(huì)有一定的影響牙甫,且在Art模式下出現(xiàn)內(nèi)存錯(cuò)亂的問(wèn)題掷酗;美團(tuán)提出的思想方案主要是基于Instant Run的原理,兼容性比較好窟哺,但目前尚未開(kāi)源泻轰。

使用Tinker的原因:

Tinker熱補(bǔ)丁方案不僅支持類(lèi)、So 以及資源的替換且轨,它還是2.X-7.X的全平臺(tái)支持浮声。利用Tinker我們不僅可以用做 bugfix,甚至可以替代功能的發(fā)布。Tinker 已運(yùn)行在微信的數(shù)億 Android 設(shè)備上殖告,那么為什么你不使用 Tinker 呢阿蝶?

(偷偷告訴你:其實(shí)現(xiàn)在最好的熱修復(fù)方案,是阿里2017年6月份發(fā)布的新一代非侵入式Android熱修復(fù)方案——Sophix黄绩,不過(guò)本人是在去年上半年就開(kāi)始使用熱修復(fù)技術(shù)了羡洁,所以那會(huì)市面上的熱修復(fù)技術(shù),相較而言爽丹,Tinker是最優(yōu)的選擇筑煮,而且也經(jīng)過(guò)了本人實(shí)際項(xiàng)目中的使用,所以我覺(jué)得大家在項(xiàng)目中如果還沒(méi)有使用過(guò)熱修復(fù)粤蝎,那Tinker是很不錯(cuò)的選擇真仲,畢竟Tinker 已運(yùn)行在微信的數(shù)億 Android 設(shè)備上。對(duì)于阿里的Sophix初澎,有興趣的研究的朋友們秸应,推薦大家可以去研讀《Android熱修復(fù)技術(shù)原理》)

二、Tinker接入步驟詳解

①工程的根目錄的build.gradle中配置:

// TinkerPatch 插件
    classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:1.2.6"
    compile "com.android.support:multidex:1.0.1"

②app的build.gradle中添加TinkerPatch的SDK依賴(lài):

    compile "com.tinkerpatch.sdk:tinkerpatch-android-sdk:1.2.6"

③為了簡(jiǎn)單方便碑宴,我們將 TinkerPatch 相關(guān)的配置都放于tinkerpatch.gradle中, 我們需要在app的build.gradle中將其引入:

    apply from: 'tinkerpatch.gradle'

④tinkerpatch.gradle將其放在跟build.gradle同一級(jí)目錄即可软啼,tinkerpatch.gradle中的完整配置如下。


project-structure.png
apply plugin: 'tinkerpatch-support'

/**
 * TODO: 請(qǐng)按自己的需求修改為適應(yīng)自己工程的參數(shù)
 */
def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-1.0.0-0527-01-08-12"
def variantName = "release"

/**
 * 對(duì)于插件各參數(shù)的詳細(xì)解析請(qǐng)參考
 * http://tinkerpatch.com/Docs/SDK
 */
tinkerpatchSupport {
    /** 可以在debug的時(shí)候關(guān)閉 tinkerPatch **/
    /** 當(dāng)disable tinker的時(shí)候需要添加multiDexKeepProguard和proguardFiles,
     這些配置文件本身由tinkerPatch的插件自動(dòng)添加延柠,當(dāng)你disable后需要手動(dòng)添加
     你可以copy本示例中的proguardRules.pro和tinkerMultidexKeep.pro,
     需要你手動(dòng)修改'tinker.sample.android.app'本示例的包名為你自己的包名, com.xxx前綴的包名不用修改
     **/
    tinkerEnable = true
    reflectApplication = true
    /**
     * 是否開(kāi)啟加固模式祸挪,只能在APK將要進(jìn)行加固時(shí)使用,否則會(huì)patch失敗贞间。
     * 如果只在某個(gè)渠道使用了加固贿条,可使用多flavors配置
     **/
    protectedApp = false
    /**
     * 實(shí)驗(yàn)功能
     * 補(bǔ)丁是否支持新增 Activity (新增Activity的exported屬性必須為false)
     **/
    supportComponent = true

    autoBackupApkPath = "${bakPath}"

    appKey = "在tinkpatch管理后臺(tái)創(chuàng)建你的應(yīng)用雹仿,會(huì)有一個(gè)唯一的appkey值,填入此處即可"

    /** 注意: 若發(fā)布新的全量包, appVersion一定要更新 **/
    appVersion = "1.0.0"

    def pathPrefix = "${bakPath}/${baseInfo}/${variantName}/"
    def name = "${project.name}-${variantName}"

    baseApkFile = "${pathPrefix}/${name}.apk"
    baseProguardMappingFile = "${pathPrefix}/${name}-mapping.txt"
    baseResourceRFile = "${pathPrefix}/${name}-R.txt"

    /**
     *  若有編譯多flavors需求, 可以參照: https://github.com/TinkerPatch/tinkerpatch-flavors-sample
     *  注意: 除非你不同的flavor代碼是不一樣的,不然建議采用zip comment或者文件方式生成渠道信息(相關(guān)工具:walle 或者 packer-ng)
     **/
}

/**
 * 用于用戶(hù)在代碼中判斷tinkerPatch是否被使能
 */
android {
    defaultConfig {
        buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
    }
}

/**
 * 一般來(lái)說(shuō),我們無(wú)需對(duì)下面的參數(shù)做任何的修改
 * 對(duì)于各參數(shù)的詳細(xì)介紹請(qǐng)參考:
 * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
 */
tinkerPatch {
    ignoreWarning = false
    useSign = true
    dex {
        dexMode = "jar"
        pattern = ["classes*.dex"]
        loader = []
    }
    lib {
        pattern = ["lib/*/*.so"]
    }

    res {
        pattern = ["res/*", "r/*", "assets/*", "resources.arsc", "AndroidManifest.xml"]
        ignoreChange = []
        largeModSize = 100
    }

    packageConfig {
    }
    sevenZip {
        zipArtifact = "com.tencent.mm:SevenZip:1.1.10"
//        path = "/usr/local/bin/7za"
    }
    buildConfig {
        keepDexApply = false
    }
}
⑤打出基準(zhǔn)包整以。
image.png
⑥安裝基準(zhǔn)包的效果
baseapk.png
⑥模擬熱修復(fù)胧辽,修改代碼,打出補(bǔ)丁包:注意悄蕾,baseApk的信息一定要和生成的基準(zhǔn)包的路徑名稱(chēng)匹配票顾,否則無(wú)法成功打出補(bǔ)丁包。
image.png
⑦在TinkerPatch Platform帆调,創(chuàng)建你的應(yīng)用奠骄,發(fā)布補(bǔ)丁:
add_patch_version.png
realease_patch.png

watch.png
⑧點(diǎn)擊拉取補(bǔ)丁番刊,然后退出App含鳞,重新啟動(dòng),查看日志芹务,成功拉取補(bǔ)丁的日志及App運(yùn)行效果如下圖所示:
logcat.png

image.png
⑨查看后臺(tái)補(bǔ)丁監(jiān)控信息蝉绷,可以看到補(bǔ)丁下發(fā)的情況:
image.png

到此,接入Tinker就完成了枣抱。實(shí)際項(xiàng)目中熔吗,咱們的應(yīng)用肯定是要在各大應(yīng)用市場(chǎng)上線(xiàn)的,那么肯定要打多個(gè)渠道包佳晶,按照常規(guī)桅狠,我們是采用productFlavors實(shí)現(xiàn)的。假設(shè)項(xiàng)目要打10個(gè)渠道包轿秧,那么得針對(duì)每個(gè)渠道包中跌,分開(kāi)打10個(gè)補(bǔ)丁包,這顯然是不合理的菇篡。針對(duì)這種需求漩符,Tinker官方給我們提供了多渠道打包的方案,如下圖:

image.png

所以我今天要介紹的就是官方推薦的一種方案:使用walle實(shí)現(xiàn)多渠道打包驱还。

三嗜暴、Tinker結(jié)合Walle多渠道打包的使用詳解

Walle(瓦力):是美團(tuán)開(kāi)源的Android Signature V2 Scheme 簽名下的新一代渠道包打包神器,跟gradle打包不一樣议蟆,walle是在APK Signature Block區(qū)塊添加自定義的渠道信息來(lái)生成渠道包闷沥,從而提高了渠道包生成效率,可以作為單機(jī)工具來(lái)使用咪鲜,也可以部署在HTTP服務(wù)器上來(lái)實(shí)時(shí)處理渠道包Apk的升級(jí)網(wǎng)絡(luò)請(qǐng)求。 ---Walle的介紹

1.在項(xiàng)目根目錄的bulid,gradle文件中添加Walle插件的依賴(lài):
 classpath 'com.meituan.android.walle:plugin:1.1.6'
2.在當(dāng)前App的 build.gradle 文件中apply這個(gè)插件撞鹉,并添加上用于讀取渠道號(hào)的AAR
apply plugin: 'walle'

dependencies {
    compile 'com.meituan.android.walle:library:1.1.6'
}
//配置插件
walle {
    // 指定渠道包的輸出路徑
    apkOutputFolder = new File("${project.buildDir}/outputs/channels");
    // 定制渠道包的APK的文件名稱(chēng)
    apkFileNameFormat = '${appName}-${packageName}-${channel}-${buildType}-v${versionName}-${versionCode}-${buildTime}.apk';
    // 渠道配置文件
    channelFile = new File("${project.getProjectDir()}/channel.txt")
}
3.配置項(xiàng)具體解釋?zhuān)?/h5>
  • apkOutputFolder:指定渠道包的輸出路徑疟丙, 默認(rèn)值為new File("${project.buildDir}/outputs/apk")

  • apkFileNameFormat:定制渠道包的APK的文件名稱(chēng), 默認(rèn)值為'${appName}-${buildType}-${channel}.apk'
    可使用以下變量:

      projectName - 項(xiàng)目名字
      appName - App模塊名字
      packageName - applicationId (App包名packageName)
      buildType - buildType (release/debug等)
      channel - channel名稱(chēng) (對(duì)應(yīng)渠道打包中的渠道名字)
      versionName - versionName (顯示用的版本號(hào))
      versionCode - versionCode (內(nèi)部版本號(hào))
      buildTime - buildTime (編譯構(gòu)建日期時(shí)間)
      fileSHA1 - fileSHA1 (最終APK文件的SHA1哈希值)
      flavorName - 編譯構(gòu)建 productFlavors 名
    
4.在App目錄下新建channel.txt配置所需要的渠道颖侄。具體內(nèi)容格式詳見(jiàn):渠道配置文件示例,支持使用#號(hào)添加注釋享郊。
5.生成渠道包——在Android Studio的控制臺(tái)—Teminal輸入:

①生成所有渠道的渠道: gradlew clean assembleReleaseChannels
②生成某一個(gè)渠道:gradlew clean assembleReleaseChannels -PchannelList=baidu
③生成指定的多個(gè)渠道包 ./gradlew clean assembleReleaseChannels -PchannelList=baidu,xiaomi

Build成功后的效果如下圖:


walle_build_apk_sucessful.png

生成的多渠道包的目錄如下圖:


image.png
6.針對(duì)多渠道打出適用所有渠道包的補(bǔ)丁包:使用tinkerPatchRelease打出補(bǔ)丁包览祖,具體如下圖所示。
image.png

適用于所有渠道的補(bǔ)丁包的位置如下:


image.png
7.獲取渠道信息
String channel = WalleChannelReader.getChannel(this.getApplicationContext());

四炊琉、接入Tinker熱修復(fù)和多渠道打包后展蒂,項(xiàng)目線(xiàn)上APK的發(fā)布及補(bǔ)丁包發(fā)布的維護(hù)。

(1)多渠道APK的發(fā)布:
每次上線(xiàn)時(shí)苔咪,只需要執(zhí)行上面生成渠道包的命令锰悼,打出多個(gè)渠道的APK即可,將各個(gè)渠道分發(fā)到各個(gè)應(yīng)用市場(chǎng)即可团赏。根據(jù)項(xiàng)目需求箕般,可以通過(guò)獲取渠道信息,進(jìn)行渠道統(tǒng)計(jì)舔清。切記每次發(fā)布新版本時(shí)丝里,一定要備份好bacApk目錄的文件,發(fā)布補(bǔ)丁的時(shí)候需要体谒。因?yàn)橐坏﹣G失杯聚,就失去了基準(zhǔn)包的信息了,就無(wú)法打出相應(yīng)基準(zhǔn)包的補(bǔ)丁包了抒痒。
(2)補(bǔ)丁包的發(fā)布:
當(dāng)線(xiàn)上APK出現(xiàn)bug需要修復(fù)時(shí)幌绍,在tinkerPatch.gradle中配置好你線(xiàn)上發(fā)布的基準(zhǔn)包的信息(之前備份的基準(zhǔn)包),使用tinkerPatchRelease打出補(bǔ)丁包评汰,在TinkerPatch管理后臺(tái)下發(fā)補(bǔ)丁纷捞。具體如上步驟6.

配置基準(zhǔn)包信息:
image.png

五、接入時(shí)可能遇到的問(wèn)題:

(1)接入Tinker時(shí)被去,打包的時(shí)候出現(xiàn)以下錯(cuò)誤com.tencent.tinker.loader.TinkerRuntimeException: Tinker Exception:applicationLike must not be null.:是因?yàn)槟愕?tinkerPatch.gradle中配置 reflectApplication = false主儡,但是你又沒(méi)有相應(yīng)的改造你的Application類(lèi)。本文介紹的是不改造我們的 Application 類(lèi)接入Tinker惨缆,所以配置應(yīng)該為:reflectApplication = ture糜值。

image.png

(2)多渠道打包時(shí),出現(xiàn)下面錯(cuò)誤

  • What went wrong:
    Execution failed for task ':app:compileReleaseJavaWithJavac'.
    Could not find tools.jar. Please check that D:\develop\JRE-New contains a valid JDK installation.

這個(gè)錯(cuò)誤是因?yàn)樵诎惭bJDK時(shí)坯墨,會(huì)安裝兩次寂汇,一次安裝JDK,一次安裝jre捣染,因?yàn)榈谝淮蜫DK的安裝就已經(jīng)安裝了一個(gè)jre骄瓣,而安裝時(shí)的提示會(huì)再次安裝一個(gè)jre。所以在第二次安裝jre時(shí)耍攘,先暫停榕栏,你需要將第一次安裝JDK的目錄下的一個(gè)/jre文件夾刪掉畔勤,然后在安裝另一個(gè)jre,這樣就可以了扒磁。再重新執(zhí)行walle打包的命令庆揪,就能成功打出多渠道包了。


image.png

(3)Demo打開(kāi)運(yùn)行時(shí)妨托,如果提示下面問(wèn)題缸榛, Rebuild一下工程或者將implementation 'com.android.support:appcompat-v7:26.1.0'改成 implementation 'com.android.support:appcompat-v7:27.1.1'即可:

Error:Execution failed for task ':app:preDebugAndroidTestBuild'.
Conflict with dependency 'com.android.support:support-annotations' in project ':app'. Resolved versions for app (26.1.0) and test app (27.1.1) differ. See https://d.android.com/r/tools/test-apk-dependency-conflicts.html for details.

(4)執(zhí)行多渠道打包命令(如gradlew clean assembleReleaseChannels)時(shí),若提示如下BUILD FAILED的信息兰伤,Rebuild一下工程再執(zhí)行打包命令即可正常打包内颗。

  • What went wrong:
    Execution failed for task ':app:clean'.
    Unable to delete file: C:\Users\18673\Desktop\TinkerPatchDemo-master\app\build\intermediates\manifests\full\debug\AndroidManifest.xml

知識(shí)儲(chǔ)備:

1、關(guān)于Dex
Dex是Android平臺(tái)上可執(zhí)行文件的類(lèi)型医清,是可以在Dalvik虛擬機(jī)上直接運(yùn)行的文件格式起暮。Java源代碼經(jīng)過(guò)ADT(Android Development Tools)的復(fù)雜編譯后轉(zhuǎn)換成Dex文件,這是一個(gè)逐步優(yōu)化的過(guò)程会烙。Dex文件的指令碼就是Dalvik虛擬機(jī)專(zhuān)有的一套指令集负懦,相比標(biāo)準(zhǔn)java的.class文件,它體積小柏腻,運(yùn)行效率高纸厉。

2、Android JVM的運(yùn)行過(guò)程

3五嫂、關(guān)于虛擬機(jī)Dalvik

  • 每一個(gè)Android應(yīng)用都運(yùn)行在一個(gè)Dalvik虛擬機(jī)實(shí)例里颗品,而每一個(gè)虛擬機(jī)實(shí)例都是一個(gè)獨(dú)立的進(jìn)程空間。虛擬機(jī)的線(xiàn)程機(jī)制沃缘,內(nèi)存分配和管理躯枢,Mutex等等都是依賴(lài)底層操作系統(tǒng)而實(shí)現(xiàn)的。
  • 所有Android應(yīng)用的線(xiàn)程都對(duì)應(yīng)一個(gè)Linux線(xiàn)程槐臀,虛擬機(jī)因而可以更多的依賴(lài)操作系統(tǒng)的線(xiàn)程調(diào)度和管理機(jī)制锄蹂。
  • 不同的應(yīng)用在不同的進(jìn)程空間里運(yùn)行,加之對(duì)不同來(lái)源的應(yīng)用都使用不同的Linux用戶(hù)來(lái)運(yùn)行水慨,可以最大程度的保護(hù)應(yīng)用的安全和獨(dú)立運(yùn)行得糜。

4、關(guān)于ART模式
ART模式英文全稱(chēng)為:Android runtime晰洒,谷歌Android 4.4系統(tǒng)新增的一種應(yīng)用運(yùn)行模式朝抖,與傳統(tǒng)的Dalvik模式不同,ART模式可以實(shí)現(xiàn)更為流暢的安卓系統(tǒng)體驗(yàn)谍珊。
Android系統(tǒng)是以L(fǎng)inux系統(tǒng)為底層構(gòu)建的治宣。谷歌為了降低應(yīng)用的開(kāi)發(fā)難度在Linux底層之上構(gòu)筑了一個(gè)名為“Dalvik”的虛擬機(jī)
因?yàn)镈alvik虛擬機(jī)的存在,Android系統(tǒng)的開(kāi)發(fā)者只需使用谷歌提供的SDK(軟件開(kāi)發(fā)工具包)即可較為輕松的按照一套“規(guī)則”創(chuàng)建APP侮邀,不用顧忌硬件缆巧、驅(qū)動(dòng)等問(wèn)題,在每次執(zhí)行應(yīng)用的時(shí)候Dalvik虛擬機(jī)都會(huì)將程序的語(yǔ)言由高級(jí)語(yǔ)言編譯為機(jī)器語(yǔ)言豌拙,這樣當(dāng)前設(shè)備才能夠運(yùn)行這一應(yīng)用。

ART模式與Dalvik模式最大的不同在于题暖,在啟用ART模式后按傅,系統(tǒng)在安裝應(yīng)用的時(shí)候會(huì)進(jìn)行一次預(yù)編譯,在安裝應(yīng)用程序時(shí)會(huì)先將代碼轉(zhuǎn)換為機(jī)器語(yǔ)言存儲(chǔ)在本地胧卤,這樣在運(yùn)行程序時(shí)就不會(huì)每次都進(jìn)行一次編譯了唯绍,執(zhí)行效率也大大提升。

本文完整Demo GitHub下載地址請(qǐng)戳:TinkerPatchDemo

本文參考:
Tinker源碼
TinkerPatch 接入及平臺(tái)使用文檔
Android 熱修復(fù) Tinker接入及源碼淺析—hongyang
MultiDex與熱修復(fù)實(shí)現(xiàn)原理
Tinker加入Walle多渠道打包

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末枝誊,一起剝皮案震驚了整個(gè)濱河市况芒,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌叶撒,老刑警劉巖绝骚,帶你破解...
    沈念sama閱讀 216,651評(píng)論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異祠够,居然都是意外死亡压汪,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)古瓤,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)止剖,“玉大人,你說(shuō)我怎么就攤上這事落君〈┫悖” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 162,931評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵绎速,是天一觀的道長(zhǎng)皮获。 經(jīng)常有香客問(wèn)我,道長(zhǎng)朝氓,這世上最難降的妖魔是什么魔市? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,218評(píng)論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮赵哲,結(jié)果婚禮上待德,老公的妹妹穿的比我還像新娘。我一直安慰自己枫夺,他們只是感情好将宪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般较坛。 火紅的嫁衣襯著肌膚如雪印蔗。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,198評(píng)論 1 299
  • 那天丑勤,我揣著相機(jī)與錄音华嘹,去河邊找鬼。 笑死法竞,一個(gè)胖子當(dāng)著我的面吹牛耙厚,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播岔霸,決...
    沈念sama閱讀 40,084評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼薛躬,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了呆细?” 一聲冷哼從身側(cè)響起型宝,我...
    開(kāi)封第一講書(shū)人閱讀 38,926評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎絮爷,沒(méi)想到半個(gè)月后趴酣,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,341評(píng)論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡坑夯,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評(píng)論 2 333
  • 正文 我和宋清朗相戀三年价卤,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片渊涝。...
    茶點(diǎn)故事閱讀 39,731評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡慎璧,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出跨释,到底是詐尸還是另有隱情胸私,我是刑警寧澤,帶...
    沈念sama閱讀 35,430評(píng)論 5 343
  • 正文 年R本政府宣布鳖谈,位于F島的核電站岁疼,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏缆娃。R本人自食惡果不足惜捷绒,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評(píng)論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望贯要。 院中可真熱鬧暖侨,春花似錦、人聲如沸崇渗。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,676評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至葫掉,卻和暖如春些举,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背俭厚。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,829評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工户魏, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人挪挤。 一個(gè)月前我還...
    沈念sama閱讀 47,743評(píng)論 2 368
  • 正文 我出身青樓绪抛,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親电禀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容

  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,079評(píng)論 25 707
  • 上一篇文章講到Tinker熱修復(fù)框架的接入教程:Android熱更新:微信Tinker框架的接入與測(cè)試 這一篇主要...
    滌生_Woo閱讀 5,585評(píng)論 10 58
  • 九月開(kāi)學(xué)季。 去年九月的時(shí)候店雅,我還是個(gè)高中畢業(yè)生政基,對(duì)大學(xué)生活有許多天真爛漫的憧憬: 宿舍呢,是上床下桌的闹啦,每個(gè)人有...
    枝青閱讀 694評(píng)論 1 7
  • 數(shù)學(xué)一直是我上學(xué)時(shí)代的最?lèi)?ài)沮明,步入社會(huì)后發(fā)現(xiàn)沒(méi)有好像沒(méi)有啥作用,但是讀了魔鬼數(shù)學(xué)后窍奋,改變了我的想法荐健。全書(shū)從線(xiàn)...
    李晏書(shū)閱讀 1,674評(píng)論 1 0
  • 2014年10月26號(hào),這個(gè)日期你我應(yīng)該都不會(huì)忘記 我們?cè)诿\(yùn)的安排下終于見(jiàn)面了 我等待了23年琳袄,這一天終于和你見(jiàn)...
    MUMENGYUN閱讀 174評(píng)論 0 1