最近項目集成了Tinker,開始認爲集成會比較簡單,可是在實際操做的過程當中仍是遇到了一些問題,本文就會介紹在集成過程你們基本會遇到的主要問題。java
目先後臺功能能夠經過三種方式實現:android
一、本身搭建後臺布丁下發系統
二、第三方提供的服務,目前如原微信simsun大神的我的tinkerpatch平臺,目前出於內測階段,暫時免費。後期應該會按下發量對app進行收費。
三、騰訊Bugly提供的服務,提供了熱更新的下發後臺,集成到了bugly的升級sdk中。免費。
根據公司的精神,咱們選擇了Bugly做爲咱們的方案,這個你們都懂得。git
咱們有將近100個渠道,每一個渠道須要一個不一樣的渠道號,按product flavor的方式打出來的包的dex都有差別。這樣就形成100個渠道包的熱更新就須要100個補丁,這對管理簡直是一個災難。Tinker也對這種問題給出了推薦的方案,那就是使用開源項目packer-ng-plugin,它的原理是將渠道信息寫在apk文件的zip comment中,這樣在多渠道打包時就不會影響dex的內容。具體關於packer-ng-plugin的介紹,能夠參考文檔[Android打包工具packer-ng-plugin]。github
目前項目使用了資源混淆項目AndResGuard,關於AndResGuard的介紹,能夠參考文檔AndResGuard[Android混淆工具AndResGuard]。
也正是引入了資源混淆,熱更新和多渠道打包都必須依賴資源混淆後生成的apk包才行。因此咱們對編譯流程進行了整合。api
編譯:編譯直接使用AndResGuard提供的命令resguardRelease生成便可。resguardRelease生成的apk文件是沒有資源混淆的。微信
./gradlew resguardRelease
Tinker生成補丁:直接調用tinkerPatchRelease任務生成的Release文件沒有進行資源混淆app
./gradlew tinkerPatchRelease
多渠道打包:使用packer-ng的命令apkRelease生成多渠道文件沒有進行資源混淆工具
./gradlew apkRelease
主要解決兩個問題:測試
一、Tinker生成補丁的原始和新的apk,須要使用資源混淆後的apk
二、多渠道打包所使用的原始apk,須要使用資源混淆後的apkgradle
針對問題1:
當使用resguardRelease進行編譯,在編譯完成後,將生成的apk文件、R文件、map文件和resouce map文件拷貝到${buildDir}/bakApk/resguard目錄下;
當使用tinkerPatchRelease生成補丁時,在tinkerPatchRelease任務前加入resguardTask
任務,這樣生成補丁時使用的新舊apk都是資源混淆過的。核心的gradle代碼以下:
1 android.applicationVariants.all { variant -> 2 /** 3 * task type, you want to bak 4 */ 5 def taskName = variant.name 6 7 tasks.all { 8 if (variant.buildType.name == 'release') { 9 10 if ("tinkerPatch${taskName.capitalize()}".equalsIgnoreCase(it.name)) { 11 12 // find resguard task 13 def resguardTask 14 tasks.all { 15 if (it.name.startsWith("resguard")) { 16 resguardTask = it 17 } 18 } 19 it.doFirst({ 20 // change build apk path 21 it.buildApkPath = "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/${project.getName()}-${taskName}_signed.apk" 22 }) 23 24 // change task dependence to resguard task 25 it.dependsOn resguardTask 26 } 27 28 if ("resguard${taskName.capitalize()}".equalsIgnoreCase(it.name)) { 29 it.doLast { 30 copy { 31 def date = new Date().format("MMdd-HH-mm-ss") 32 from "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/${project.getName()}-${taskName}_signed_7zip_aligned.apk" 33 into file(bakPath.absolutePath + "/resguard") 34 rename { String fileName -> 35 fileName.replace("${project.getName()}-${taskName}_signed_7zip_aligned.apk", "${project.getName()}-${taskName}-${date}.apk") 36 } 37 38 from "${buildDir}/outputs/mapping/${taskName}/mapping.txt" 39 into file(bakPath.absolutePath + "/resguard") 40 rename { String fileName -> 41 fileName.replace("mapping.txt", "${project.getName()}-${taskName}-${date}-mapping.txt") 42 } 43 44 from "${buildDir}/intermediates/symbols/${taskName}/R.txt" 45 into file(bakPath.absolutePath + "/resguard") 46 rename { String fileName -> 47 fileName.replace("R.txt", "${project.getName()}-${taskName}-${date}-R.txt") 48 } 49 from "${buildDir}/outputs/apk/AndResGuard_${project.getName()}-${taskName}/resource_mapping_${project.getName()}-release.txt" 50 into file(bakPath.absolutePath + "/resguard") 51 rename { String fileName -> 52 fileName.replace("resource_mapping_${project.getName()}-release.txt", "${project.getName()}-${taskName}-${date}-resource_mapping.txt") 53 } 54 } 55 } 56 } 57 } 58 }
針對問題二、在AS中使用apkRelease任務打包的方式再也不適用,可直接使用packer-ng所提供的命令行方式進行生成渠道包,通過測試,100個渠道包的確在10s左右就能打完,速度至關之快。考慮到市場推廣人員會打不一樣渠道包,後期可作一個簡易工具提供給市場推廣人員。
整合後操做:
編譯:
./gradlew resguardRelease
生成的apk文件放在${app}\build\bakApk\resguard\目錄下
打補丁包:
./gradlew tinkerPatchRelease ./gradlew generateManifestForReleaseTinkerPatch
最終生成的補丁放在${app}\build\outputs\patch\目錄下
多渠道打包:
針對編譯後生成的包,使用packer-ng提供的命令行操做便可
java -jar PackerNg-x.x.x.jar apkFile marketFile outputDir
over~~