Android熱更新利器Tinker接入

參考

騰訊Tinker官方文檔

建議大家先使用demo實(shí)驗(yàn),成功后再集成到真正項(xiàng)目中。。。因?yàn)?。。。你懂的?。。?/h1>

寫在前面

好久沒(méi)有寫博客了,都用筆記的形式記錄了所學(xué)的東西。最近面試跟面試官聊起,發(fā)現(xiàn)寫博客真的是一個(gè)好習(xí)慣,希望堅(jiān)持下去吧。本文的目的就一個(gè),讓應(yīng)用接入Tinker熱更新,我們不去探究這東西怎么實(shí)現(xiàn),本文僅僅作為工具使用指南。
類似的原理性文章可以參考下拙作:
Android黑科技動(dòng)態(tài)加載(一)之Java中的ClassLoader
Android黑科技動(dòng)態(tài)加載(二)之Android中的ClassLoader
Android黑科技動(dòng)態(tài)加載(三)之動(dòng)態(tài)加載資源
Android黑科技動(dòng)態(tài)加載(四)之插件化開發(fā)

基準(zhǔn)包

例如有一個(gè)版本A,但是這時(shí)A是有Bug的,然后修復(fù)Bug后的生成的版本我們稱為B。A和B之間的區(qū)別產(chǎn)生一個(gè)差分包(這里也稱為補(bǔ)丁包),那么我們就可以說(shuō)這個(gè)差分包是以A作為基準(zhǔn)包相對(duì)B生成的。參考增量更新文章:Android NDK開發(fā)兩部曲(二)之應(yīng)用篇(增量更新也就那樣)

基本步驟

1、注冊(cè)Tinker賬號(hào)并新建項(xiàng)目,傳送門
2、配置gradle和代碼
3、生成基準(zhǔn)包
4、修復(fù)Bug
5、生成補(bǔ)丁包
6、發(fā)布補(bǔ)丁包

Tinker做了什么

1、1-2步是APP開發(fā)的基本步驟,完成1-3步,那么你的APP就集成了Tinker。
集成Tinker后,Tinker會(huì)根據(jù)各個(gè)版本的配置信息去自動(dòng)加載補(bǔ)丁。可配置強(qiáng)制更新,也可配置輪詢更新。

2、第3步則是保留一個(gè)之前版本副本,用于后面生成補(bǔ)丁。為什么要這樣做?因?yàn)?.0.2的相對(duì)于1.0.1的補(bǔ)丁包只能作用在1.0.1版本上。如果想要處理1.0.0那么有兩種方法,使用1.0.0->1.0.1和1.0.1->1.0.2兩個(gè)補(bǔ)丁包。但是也可以生成1.0.0->1.0.2的補(bǔ)丁包。所以副本保留還是有必要的。
3、4-6部就是真正應(yīng)用到生產(chǎn)環(huán)境上了,真正達(dá)到熱修復(fù)的作用。

一、注冊(cè)Tinker賬號(hào)

這個(gè)就不說(shuō)了,Tinker注冊(cè)和新建項(xiàng)目都好簡(jiǎn)單,也沒(méi)有什么需要注意的。拿到appKey

二、配置Gradle和代碼

這個(gè)推薦我們的拷貝粘貼代碼

1、配置Tinker版本信息

我們使用配置文件去配置版本信息,易于統(tǒng)一版本和后面更換版本
編輯根目錄的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腳本

在項(xiàng)目根目錄新建tinkerpatch.gradle文件

apply plugin: 'tinkerpatch-support'

/**
 * TODO: 請(qǐng)按自己的需求修改為適應(yīng)自己工程的參數(shù)
 */
def bakPath = file("${buildDir}/bakApk/")
def baseInfo = "app-1.0.0-1213-19-52-36"
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
    /**
     * 是否開啟加固模式,只能在APK將要進(jìn)行加固時(shí)使用,否則會(huì)patch失敗。
     * 如果只在某個(gè)渠道使用了加固,可使用多flavors配置
     **/
    protectedApp = false
    /**
     * 實(shí)驗(yàn)功能
     * 補(bǔ)丁是否支持新增 Activity (新增Activity的exported屬性必須為false)
     **/
    supportComponent = true

    autoBackupApkPath = "${bakPath}"

    appKey = "c6a00cf4aafa2ab2"

    /** 注意: 若發(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)
     **/
}

/**
 * 用于用戶在代碼中判斷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
    }
}

注意幾個(gè)字段內(nèi)容,主要是后面生成補(bǔ)丁需要用到的,除了AppKey外其他暫時(shí)不用改
baseInfo : 這個(gè)是基準(zhǔn)包的名稱,使用Tinker腳本編譯在模塊的build/bakApk生成編譯副本
variantName : 這個(gè)一般對(duì)應(yīng)buildTypes里面你基準(zhǔn)包生成的類型,release、debug或其他
appKey : 這個(gè)就是Tinker新建項(xiàng)目時(shí)拿到的appKey
appVersion : 配置和Tinker后臺(tái)新建補(bǔ)丁包的一致

4、配置模塊下的buidle.gradle

A、配置應(yīng)用簽名

這個(gè)百度搜都有,大概就這樣

    signingConfigs {
        release {//發(fā)布版本的簽名配置
            storeFile file('key.jks')
            keyAlias 'test'
            storePassword '123456789'
            keyPassword '123456789'
        }
        debug {//調(diào)試版本的簽名配置
            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需要單獨(dú)引用,對(duì)于tinker的其他庫(kù)都無(wú)需再引用
        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章節(jié)中的,初始化SDK
        TinkerPatch.init(tinkerApplicationLike)
                .reflectPatchLibrary()
                .fetchPatchUpdate(true)
        // 強(qiáng)制更新
                .setPatchRollbackOnScreenOff(true)
                .setPatchRestartOnSrceenOff(true)
                .setFetchPatchIntervalByHours(3);

        // 每隔3個(gè)小時(shí)(通過(guò)setFetchPatchIntervalByHours設(shè)置)去訪問(wèn)后臺(tái)時(shí)候有更新,通過(guò)handler實(shí)現(xiàn)輪訓(xùn)的效果
        TinkerPatch.with().fetchPatchUpdateAndPollWithInterval();
    }
}

三、生成基準(zhǔn)包

其實(shí)到了這里就配置完成了,我們生產(chǎn)一個(gè)基準(zhǔn)包


生成基準(zhǔn)包

雙擊assembleRelease生成成功后安裝模塊/build/outputs/apk/release/app-release.apk就OK了,這時(shí)候進(jìn)去模塊/build/bakApk里面記錄一下類似app-1.0.0-1213-19-52-36的文件名稱,只生成一次基準(zhǔn)包,那么就會(huì)生成一個(gè)。但是如果手賤點(diǎn)太多生成太多的話確定不了剛剛生成的是哪個(gè),那么就選最新那個(gè)或者刪掉重新生成基準(zhǔn)包,真實(shí)環(huán)境并不允許這樣搞。。。

安裝包
基準(zhǔn)包名稱

四、修復(fù)bug

隨便修改點(diǎn)代碼

五、生成補(bǔ)丁包

這時(shí)候我們就需要去修改一些tinkerpatch.gradle文件的信息了。
baseInfo :還記得app-1.0.0-1213-19-52-36這個(gè)東西嗎?換成自己上面記錄的就OK了
variantName : 因?yàn)閯倓偽覀兪褂?code>assembleRelease生成的補(bǔ)丁,所以我們只需要使用release就OK了

生成差分包

雙擊TinkerPatchRelease生成差分包,patch_signed_7zip.apk就是補(bǔ)丁包了

補(bǔ)丁包

六、發(fā)布補(bǔ)丁包

回到Tinker后臺(tái),選中我們開始新建的項(xiàng)目,補(bǔ)丁下發(fā)->添加APP版本。然后上傳剛剛的patch_signed_7zip.apk

發(fā)布補(bǔ)丁包

APP開啟強(qiáng)制更新的話那么重啟應(yīng)用就會(huì)更新,否則會(huì)通過(guò)輪詢?nèi)ジ隆?yīng)用重啟才生效。Tinker太強(qiáng)大了,本文目的就是把項(xiàng)目跑通,相信后面的很多功能大家有興趣的話一起發(fā)現(xiàn),一起討論。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容