參考
建議大家先使用demo實驗,成功后再集成到真正項目中。。。因為。。。你懂的!!!
寫在前面
好久沒有寫博客了,都用筆記的形式記錄了所學的東西。最近面試跟面試官聊起,發現寫博客真的是一個好習慣,希望堅持下去吧。本文的目的就一個,讓應用接入Tinker熱更新,我們不去探究這東西怎么實現,本文僅僅作為工具使用指南。
類似的原理性文章可以參考下拙作:
Android黑科技動態加載(一)之Java中的ClassLoader
Android黑科技動態加載(二)之Android中的ClassLoader
Android黑科技動態加載(三)之動態加載資源
Android黑科技動態加載(四)之插件化開發
基準包
例如有一個版本A,但是這時A是有Bug的,然后修復Bug后的生成的版本我們稱為B。A和B之間的區別產生一個差分包(這里也稱為補丁包),那么我們就可以說這個差分包是以A作為基準包相對B生成的。參考增量更新文章:Android NDK開發兩部曲(二)之應用篇(增量更新也就那樣)
基本步驟
1、注冊Tinker賬號并新建項目,傳送門
2、配置gradle和代碼
3、生成基準包
4、修復Bug
5、生成補丁包
6、發布補丁包
Tinker做了什么
1、1-2步是APP開發的基本步驟,完成1-3步,那么你的APP就集成了Tinker。
集成Tinker后,Tinker會根據各個版本的配置信息去自動加載補丁。可配置強制更新,也可配置輪詢更新。
2、第3步則是保留一個之前版本副本,用于后面生成補丁。為什么要這樣做?因為1.0.2的相對于1.0.1的補丁包只能作用在1.0.1版本上。如果想要處理1.0.0那么有兩種方法,使用1.0.0->1.0.1和1.0.1->1.0.2兩個補丁包。但是也可以生成1.0.0->1.0.2的補丁包。所以副本保留還是有必要的。
3、4-6部就是真正應用到生產環境上了,真正達到熱修復的作用。
一、注冊Tinker賬號
這個就不說了,Tinker注冊和新建項目都好簡單,也沒有什么需要注意的。拿到appKey
二、配置Gradle和代碼
這個推薦我們的拷貝粘貼代碼
1、配置Tinker版本信息
我們使用配置文件去配置版本信息,易于統一版本和后面更換版本
編輯根目錄的gradle.properties
,加入
TINKER_VERSION=1.9.2
TINKERPATCH_VERSION=1.2.2
2、配置根目錄下的build.gradle文件
使用Tinker插件
classpath "com.tinkerpatch.sdk:tinkerpatch-gradle-plugin:${TINKERPATCH_VERSION}"
3、配置Tinker的gradle腳本
在項目根目錄新建tinkerpatch.gradle
文件
apply plugin: 'tinkerpatch-support'
/**
* TODO: 請按自己的需求修改為適應自己工程的參數
*/
def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-1.0.0-1213-19-52-36"
def variantName = "release"
/**
* 對于插件各參數的詳細解析請參考
* http://tinkerpatch.com/Docs/SDK
*/
tinkerpatchSupport {
/** 可以在debug的時候關閉 tinkerPatch **/
/** 當disable tinker的時候需要添加multiDexKeepProguard和proguardFiles,
這些配置文件本身由tinkerPatch的插件自動添加,當你disable后需要手動添加
你可以copy本示例中的proguardRules.pro和tinkerMultidexKeep.pro,
需要你手動修改'tinker.sample.android.app'本示例的包名為你自己的包名, com.xxx前綴的包名不用修改
**/
tinkerEnable = true
reflectApplication = true
/**
* 是否開啟加固模式,只能在APK將要進行加固時使用,否則會patch失敗。
* 如果只在某個渠道使用了加固,可使用多flavors配置
**/
protectedApp = false
/**
* 實驗功能
* 補丁是否支持新增 Activity (新增Activity的exported屬性必須為false)
**/
supportComponent = true
autoBackupApkPath = "${bakPath}"
appKey = "c6a00cf4aafa2ab2"
/** 注意: 若發布新的全量包, 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或者文件方式生成渠道信息(相關工具:walle 或者 packer-ng)
**/
}
/**
* 用于用戶在代碼中判斷tinkerPatch是否被使能
*/
android {
defaultConfig {
buildConfigField "boolean", "TINKER_ENABLE", "${tinkerpatchSupport.tinkerEnable}"
}
}
/**
* 一般來說,我們無需對下面的參數做任何的修改
* 對于各參數的詳細介紹請參考:
* 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
}
}
注意幾個字段內容,主要是后面生成補丁需要用到的,除了AppKey外其他暫時不用改
baseInfo
: 這個是基準包的名稱,使用Tinker腳本編譯在模塊的build/bakApk生成編譯副本
variantName
: 這個一般對應buildTypes
里面你基準包生成的類型,release、debug或其他
appKey
: 這個就是Tinker新建項目時拿到的appKey
appVersion
: 配置和Tinker后臺新建補丁包的一致
4、配置模塊下的buidle.gradle
A、配置應用簽名
這個百度搜都有,大概就這樣
signingConfigs {
release {//發布版本的簽名配置
storeFile file('key.jks')
keyAlias 'test'
storePassword '123456789'
keyPassword '123456789'
}
debug {//調試版本的簽名配置
storeFile file('key.jks')
keyAlias 'test'
storePassword '123456789'
keyPassword '123456789'
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
signingConfig signingConfigs.release
}
debug {
signingConfig signingConfigs.debug
}
}
B、配置依賴
//若使用annotation需要單獨引用,對于tinker的其他庫都無需再引用
annotationProcessor("com.tinkerpatch.tinker:tinker-android-anno:${TINKER_VERSION}") {
changing = true
}
compileOnly("com.tinkerpatch.tinker:tinker-android-anno:${TINKER_VERSION}") {
changing = true
}
implementation("com.tinkerpatch.sdk:tinkerpatch-android-sdk:${TINKERPATCH_VERSION}") {
changing = true
}
C、使用插件
在模塊的build.gradle加入
apply from: 'tinkerpatch.gradle'
3、代碼配置
最后一步配置,把代碼集成到App里,別忘了在AndroidManifest里面配置APP。。。
public class App extends Application {
private ApplicationLike tinkerApplicationLike;
@Override
public void onCreate() {
super.onCreate();
tinkerApplicationLike = TinkerPatchApplicationLike.getTinkerPatchApplicationLike();
// 初始化TinkerPatch SDK, 更多配置可參照API章節中的,初始化SDK
TinkerPatch.init(tinkerApplicationLike)
.reflectPatchLibrary()
.fetchPatchUpdate(true)
// 強制更新
.setPatchRollbackOnScreenOff(true)
.setPatchRestartOnSrceenOff(true)
.setFetchPatchIntervalByHours(3);
// 每隔3個小時(通過setFetchPatchIntervalByHours設置)去訪問后臺時候有更新,通過handler實現輪訓的效果
TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
}
}
三、生成基準包
其實到了這里就配置完成了,我們生產一個基準包
雙擊assembleRelease生成成功后安裝模塊/build/outputs/apk/release/app-release.apk
就OK了,這時候進去模塊/build/bakApk
里面記錄一下類似app-1.0.0-1213-19-52-36
的文件名稱,只生成一次基準包,那么就會生成一個。但是如果手賤點太多生成太多的話確定不了剛剛生成的是哪個,那么就選最新那個或者刪掉重新生成基準包,真實環境并不允許這樣搞。。。
四、修復bug
隨便修改點代碼
五、生成補丁包
這時候我們就需要去修改一些tinkerpatch.gradle
文件的信息了。
baseInfo
:還記得app-1.0.0-1213-19-52-36
這個東西嗎?換成自己上面記錄的就OK了
variantName
: 因為剛剛我們使用assembleRelease
生成的補丁,所以我們只需要使用release
就OK了
雙擊TinkerPatchRelease
生成差分包,patch_signed_7zip.apk
就是補丁包了
六、發布補丁包
回到Tinker后臺,選中我們開始新建的項目,補丁下發->添加APP版本。然后上傳剛剛的patch_signed_7zip.apk
。
APP開啟強制更新的話那么重啟應用就會更新,否則會通過輪詢去更新。應用重啟才生效。Tinker太強大了,本文目的就是把項目跑通,相信后面的很多功能大家有興趣的話一起發現,一起討論。