Bugly熱更新集成記錄

官方文檔:Bugly Android熱更新使用指南, 補(bǔ)丁打包配置詳解

官方Demo: Bugly-Android-Demo

應(yīng)用配置

1.添加插件依賴

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
        // tinkersupport插件, 其中l(wèi)astest.release指拉取最新版本秩冈,也可以指定明確版本號蕴潦,例如1.0.4
        classpath "com.tencent.bugly:tinker-support:1.1.2"
    }
}

2.app module 添加SDK

// 依賴插件腳本
apply from: 'tinker-support.gradle'

android {
    defaultConfig {
        ...
        // 開啟multidex
        multiDexEnabled true    

        /*ndk {
            //設(shè)置支持的SO庫架構(gòu)
            abiFilters 'armeabi' //, 'x86', 'armeabi-v7a', 'x86_64', 'arm64-v8a'
        }*/
    }
    
    // 簽名配置
    signingConfigs {
        release {
            try {
                storeFile file("G:/workspace/key/huiming.jks")
                storePassword "test123"
                keyAlias "huiming"
                keyPassword "test123"
            } catch (ex) {
                throw new InvalidUserDataException(ex.toString())
            }
        }

        debug {
            //storeFile file("G:/workspace/key/huiming.jks")
        }
    }
    
    buildTypes {
        release {
            minifyEnabled true
            signingConfig signingConfigs.release
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
        debug {
            debuggable true
            minifyEnabled false
            // signingConfig signingConfigs.debug
        }
    }
}
dependencies {
    compile "com.android.support:multidex:1.0.1" // 多dex配置
    //注釋掉原有bugly的倉庫
    //compile 'com.tencent.bugly:crashreport:latest.release'//其中l(wèi)atest.release指代最新版本號布蔗,也可以指定明確的版本號瘦锹,例如1.3.4
    compile 'com.tencent.bugly:crashreport_upgrade:1.3.5'
    // 指定tinker依賴版本(注:應(yīng)用升級1.3.5版本起放棒,不再內(nèi)置tinker)
    compile 'com.tencent.tinker:tinker-android-lib:1.9.6'
    //按需要添加,如有需要native支持
    //compile 'com.tencent.bugly:nativecrashreport:latest.release' //其中l(wèi)atest.release指代最新版本號,也可以指定明確的版本號,例如2.2.0
}

3. app gradle同級目錄下新建 tinker-support.gradle 文件

apply plugin: 'com.tencent.bugly.tinker-support'

def bakPath = file("${buildDir}/bakApk/")

/**
 * 此處填寫每次構(gòu)建生成的基準(zhǔn)包目錄
 */
def baseApkDir = "app-0726-11-48-25"

/**
 * 對于插件各參數(shù)的詳細(xì)解析請參考
 */
tinkerSupport {

    // 開啟tinker-support插件邓线,默認(rèn)值true
    enable = true

    // 自動生成tinkerId, 你無須關(guān)注tinkerId,默認(rèn)為false
    autoGenerateTinkerId = true

    // 指定歸檔目錄煌恢,默認(rèn)值當(dāng)前module的子目錄tinker
    autoBackupApkDir = "${bakPath}"

    // 是否啟用覆蓋tinkerPatch配置功能骇陈,默認(rèn)值false
    // 開啟后tinkerPatch配置不生效,即無需添加tinkerPatch
    overrideTinkerPatchConfiguration = true

    // 編譯補(bǔ)丁包時瑰抵,必需指定基線版本的apk你雌,默認(rèn)值為空
    // 如果為空,則表示不是進(jìn)行補(bǔ)丁包的編譯
    // @{link tinkerPatch.oldApk }
    baseApk = "${bakPath}/${baseApkDir}/app-release.apk"
//    baseApk =  "${bakPath}/${baseApkDir}/app-debug.apk"

    // 對應(yīng)tinker插件applyMapping
    baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-release-mapping.txt"
//    baseApkProguardMapping = "${bakPath}/${baseApkDir}/app-debug-mapping.txt"

    // 對應(yīng)tinker插件applyResourceMapping
    baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-release-R.txt"
//    baseApkResourceMapping = "${bakPath}/${baseApkDir}/app-debug-R.txt"

    // 構(gòu)建基準(zhǔn)包跟補(bǔ)丁包都要修改tinkerId二汛,主要用于區(qū)分
//    tinkerId = "1.0.3-ccc"

    // 打多渠道補(bǔ)丁時指定目錄
    // buildAllFlavorsDir = "${bakPath}/${baseApkDir}"

    // 是否使用加固模式婿崭,默認(rèn)為false
    // isProtectedApp = true

    // 是否采用反射Application的方式集成,無須改造Application
    enableProxyApplication = true

    // 支持新增Activity
    supportHotplugComponent = true

}

/**
 * 一般來說,我們無需對下面的參數(shù)做任何的修改
 * 對于各參數(shù)的詳細(xì)介紹請參考:
 * https://github.com/Tencent/tinker/wiki/Tinker-%E6%8E%A5%E5%85%A5%E6%8C%87%E5%8D%97
 */
tinkerPatch {
    tinkerEnable = true
    ignoreWarning = false
    useSign = false
    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
//      tinkerId = "base-2.0.1"
    }
}

4.初始化SDK

class MyApp : Application() {

    override fun onCreate() {
        super.onCreate()
        
        initUpdate()
    }

    fun initUpdate() {
        setStrictMode()
        // 設(shè)置是否開啟熱更新能力肴颊,默認(rèn)為true
        Beta.enableHotfix = true
        // 設(shè)置是否自動下載補(bǔ)丁
        Beta.canAutoDownloadPatch = true
        // 設(shè)置是否提示用戶重啟
        Beta.canNotifyUserRestart = true
        // 設(shè)置是否自動合成補(bǔ)丁
        Beta.canAutoPatch = true

        /**
         * 全量升級狀態(tài)回調(diào)
         */
        Beta.upgradeStateListener = object : UpgradeStateListener {
            override fun onUpgradeFailed(b: Boolean) {

            }

            override fun onUpgradeSuccess(b: Boolean) {

            }

            override fun onUpgradeNoVersion(b: Boolean) {
                Toast.makeText(applicationContext, "最新版本", Toast.LENGTH_SHORT).show()
            }

            override fun onUpgrading(b: Boolean) {
                Toast.makeText(applicationContext, "onUpgrading", Toast.LENGTH_SHORT).show()
            }

            override fun onDownloadCompleted(b: Boolean) {

            }
        }

        /**
         * 補(bǔ)丁回調(diào)接口氓栈,可以監(jiān)聽補(bǔ)丁接收、下載苫昌、合成的回調(diào)
         */
        Beta.betaPatchListener = object : BetaPatchListener {
            override fun onPatchReceived(patchFileUrl: String) {
                Toast.makeText(applicationContext, patchFileUrl, Toast.LENGTH_SHORT).show()
            }

            override fun onDownloadReceived(savedLength: Long, totalLength: Long) {
                Toast.makeText(applicationContext, String.format(Locale.getDefault(),
                        "%s %d%%",
                        Beta.strNotificationDownloading,
                        (if (totalLength == 0L) 0 else savedLength * 100 / totalLength).toInt()), Toast.LENGTH_SHORT).show()
            }

            override fun onDownloadSuccess(patchFilePath: String) {
                Toast.makeText(applicationContext, patchFilePath, Toast.LENGTH_SHORT).show()
                //                Beta.applyDownloadedPatch();
            }

            override fun onDownloadFailure(msg: String) {
                Toast.makeText(applicationContext, msg, Toast.LENGTH_SHORT).show()
            }

            override fun onApplySuccess(msg: String) {
                Toast.makeText(applicationContext, msg, Toast.LENGTH_SHORT).show()
            }

            override fun onApplyFailure(msg: String) {
                Toast.makeText(applicationContext, msg, Toast.LENGTH_SHORT).show()
            }

            override fun onPatchRollback() {
                Toast.makeText(applicationContext, "onPatchRollback", Toast.LENGTH_SHORT).show()
            }
        }

        val start = System.currentTimeMillis()
        Bugly.setUserId(this, "falue")
        Bugly.setUserTag(this, 123456)
        Bugly.putUserData(this, "key1", "123")
        Bugly.setAppChannel(this, "bugly")


        // 這里實現(xiàn)SDK初始化颤绕,appId替換成你的在Bugly平臺申請的appId,調(diào)試時將第三個參數(shù)設(shè)置為true
        Bugly.init(this, "你的APPID", true)
        val end = System.currentTimeMillis()
        Log.e("init time--->", (end - start).toString() + "ms")
    }

    override fun attachBaseContext(base: Context?) {
        super.attachBaseContext(base)
        // you must install multiDex whatever tinker is installed!
        MultiDex.install(base)

        // 安裝tinker
        Beta.installTinker()
    }


    @TargetApi(9)
    protected fun setStrictMode() {
        StrictMode.setThreadPolicy(StrictMode.ThreadPolicy.Builder().permitAll().build())
        StrictMode.setVmPolicy(StrictMode.VmPolicy.Builder().detectAll().penaltyLog().build())
    }
}

5.AndroidManifest.xml配置

  • 權(quán)限配置

    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.READ_LOGS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    

補(bǔ)丁打包

1.編譯基準(zhǔn)包

注意:請確認(rèn)tinker-support.gradle文件中是否有配置 autoGenerateTinkerId = true 自動生成tinkerId

如果沒有,請手動修改tinkerId

打開AS右邊的Gradle 執(zhí)行assembleRelease編譯生成基準(zhǔn)包:

1532585447385

這個會在build/outputs/bakApk路徑下生成每次編譯的基準(zhǔn)包祟身、混淆配置文件奥务、資源Id文件,如下圖所示:

image

注意:app-release-mapping如果沒有生成袜硫,請檢查是否配置了簽名

請先安裝好并啟動一次基準(zhǔn)包apk

否則發(fā)布上傳補(bǔ)丁包時會出現(xiàn)未找到包的情況

2.生成升級補(bǔ)丁

  • 修改 tinker-support.gradle 文件下基準(zhǔn)包目錄地址

    /**
     * 此處填寫每次構(gòu)建生成的基準(zhǔn)包目錄
     */
    def baseApkDir = "app-0726-11-48-25"
    
  • 使用buildTinkerPatchRelase 進(jìn)行編譯生成補(bǔ)丁包

    1532585447385
  • 編譯完成后氯葬,將會在./build/outputs/patch/release目錄下生成補(bǔ)丁包

    補(bǔ)丁包路徑.png
  • 將補(bǔ)丁包上傳至bugly中下發(fā)補(bǔ)丁

問題記錄

1. 錯誤:Tinker.DefaultLoadReporter: patch loadReporter onLoadPatchListenerReceiveFail: patch receive fail: /data/user/0/xxxxxxxx/app_tmpPatch/tmpPatch.apk, code: -5

這個是因為這個手機(jī)在6.0的時候編譯選項打開了JIT,可能會對patch產(chǎn)生影響婉陷,會對這部分手機(jī)關(guān)閉patch功能

GitHubIssues解釋

2.assembleRelease編譯時出現(xiàn)錯誤 BUILD FAILED

Warning: com.qihancloud.opensdk.function.unit.MediaManager: can't find referenced class org.jetbrains.annotations.NotNull

Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt
Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt
Warning: okhttp3.internal.platform.ConscryptPlatform: can't find referenced class org.conscrypt.Conscrypt

...

FAILURE: Build failed with an exception.

* What went wrong:
Execution failed for task ':app:transformClassesAndResourcesWithProguardForRelease'.
> Job failed, see logs for details

* Try:
Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights.

* Get more help at https://help.gradle.org

BUILD FAILED in 45s

解決方案:在proguard-rules.pro中添加相對應(yīng)的混淆

-keep class com.qihancloud.opensdk.** {*;}
-dontwarn okio.**
-dontwarn retrofit2.Call
-dontnote retrofit2.Platform$IOS$MainThreadExecutor
#忽略所有警告
-ignorewarnings
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末帚称,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子秽澳,更是在濱河造成了極大的恐慌闯睹,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,188評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件担神,死亡現(xiàn)場離奇詭異楼吃,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評論 3 395
  • 文/潘曉璐 我一進(jìn)店門孩锡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來酷宵,“玉大人,你說我怎么就攤上這事躬窜〗娇眩” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評論 0 356
  • 文/不壞的土叔 我叫張陵荣挨,是天一觀的道長男韧。 經(jīng)常有香客問我,道長垦沉,這世上最難降的妖魔是什么煌抒? 我笑而不...
    開封第一講書人閱讀 58,893評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮厕倍,結(jié)果婚禮上寡壮,老公的妹妹穿的比我還像新娘。我一直安慰自己讹弯,他們只是感情好况既,可當(dāng)我...
    茶點故事閱讀 67,917評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著组民,像睡著了一般棒仍。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上臭胜,一...
    開封第一講書人閱讀 51,708評論 1 305
  • 那天莫其,我揣著相機(jī)與錄音,去河邊找鬼耸三。 笑死乱陡,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的仪壮。 我是一名探鬼主播憨颠,決...
    沈念sama閱讀 40,430評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼积锅!你這毒婦竟也來了爽彤?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評論 0 276
  • 序言:老撾萬榮一對情侶失蹤缚陷,失蹤者是張志新(化名)和其女友劉穎适篙,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體箫爷,經(jīng)...
    沈念sama閱讀 45,801評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡匙瘪,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,976評論 3 337
  • 正文 我和宋清朗相戀三年铆铆,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片丹喻。...
    茶點故事閱讀 40,115評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖翁都,靈堂內(nèi)的尸體忽然破棺而出碍论,到底是詐尸還是另有隱情,我是刑警寧澤柄慰,帶...
    沈念sama閱讀 35,804評論 5 346
  • 正文 年R本政府宣布鳍悠,位于F島的核電站,受9級特大地震影響坐搔,放射性物質(zhì)發(fā)生泄漏藏研。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,458評論 3 331
  • 文/蒙蒙 一概行、第九天 我趴在偏房一處隱蔽的房頂上張望蠢挡。 院中可真熱鬧,春花似錦凳忙、人聲如沸业踏。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽勤家。三九已至,卻和暖如春柳恐,著一層夾襖步出監(jiān)牢的瞬間伐脖,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評論 1 272
  • 我被黑心中介騙來泰國打工乐设, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留讼庇,地道東北人。 一個月前我還...
    沈念sama閱讀 48,365評論 3 373
  • 正文 我出身青樓伤提,卻偏偏與公主長得像巫俺,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子肿男,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,055評論 2 355

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

  • 前言 熱更新能力是Bugly為解決開發(fā)者緊急修復(fù)線上bug介汹,而無需重新發(fā)版讓用戶無感知就能把問題修復(fù)的一項能力。B...
    Smile__EveryDay閱讀 24,862評論 31 19
  • 以下文章記錄bugly熱更新的過程(傻瓜式教程舶沛,被那人較懶嘹承,直接貼圖吧):集成第三方,首先肯定是去官網(wǎng)注冊如庭,申請資...
    忘塵And閱讀 374評論 0 4
  • 前言 之前發(fā)過一篇文章——Bugly熱更新SDK你需要知道的一些事叹卷,那是Bugly集成Tinker之后正式發(fā)布的第...
    IT_xiao小巫閱讀 6,370評論 4 25
  • 建立一個student數(shù)據(jù)庫包括:學(xué)生:S(Sno,Sname,Ssex,Sage,Sdept),課程:C(Cno...
    J丶MyDream閱讀 916評論 0 1
  • 1):【產(chǎn)品創(chuàng)意】用推送作為信息的主要載體撼港,“即刻”能進(jìn)一步降低信息獲取成本嗎? 即刻定位為“基于興趣的極簡信息推...
    波_洛閱讀 289評論 0 1