1. 程式人生 > >Tinker的整合和多渠道打包

Tinker的整合和多渠道打包

Tinker是什麼

Tinker是微信官方的Android熱補丁解決方案,它支援動態下發程式碼、So庫以及資源,讓應用能夠在不需要重新安裝的情況下實現更新。當然,你也可以使用Tinker來更新你的外掛。

它主要包括以下幾個部分:

1.gradle編譯外掛: tinker-patch-gradle-plugin

2.核心sdk庫: tinker-android-lib

3.非gradle編譯使用者的命令列版本: tinker-patch-cli.jar

為什麼使用Tinker`

當前市面的熱補丁方案有很多,其中比較出名的有阿里的AndFix、美團的Robust以及QZone的超級補丁方案。但它們都存在無法解決的問題,這也是正是我們推出Tinker的原因。

總的來說:

AndFix作為native解決方案,首先面臨的是穩定性與相容性問題,更重要的是它無法實現類替換,它是需要大量額外的開發成本的;

Robust相容性與成功率較高,但是它與AndFix一樣,無法新增變數與類只能用做的bugFix方案;

Qzone方案可以做到釋出產品功能,但是它主要問題是插樁帶來Dalvik的效能問題,以及為了解決Art下記憶體地址問題而導致補丁包急速增大的。

特別是在Android N之後,由於混合編譯的inline策略修改,對於市面上的各種方案都不太容易解決。而Tinker熱補丁方案不僅支援類、So以及資源的替換,它還是2.X-7.X的全平臺支援。利用Tinker我們不僅可以用做bugfix,甚至可以替代功能的釋出。Tinker已執行在微信的數億Android裝置上,那麼為什麼你不使用Tinker呢?

Tinker的已知問題

由於原理與系統限制,Tinker有以下已知問題:

1.Tinker不支援修改AndroidManifest.xml,Tinker不支援新增四大元件;

2.由於Google Play的開發者條款限制,不建議在GP渠道動態更新程式碼;

3.在Android N上,補丁對應用啟動時間有輕微的影響;

4.不支援部分三星android-21機型,載入補丁時會主動丟擲   "TinkerRuntimeException:checkDexInstall failed";

5.由於各個廠商的加固實現並不一致,在1.7.6以及之後的版本,tinker不再支援加固的動態更新;

6.對於資源替換,不支援修改remoteView。例如transition動畫,notification icon以及桌面圖示。

Tinker的demo

1.先去Github上下載Tinker原始碼,裡面有tinker-sample-Android.

下好demo後,可能大家會迫不及待(其實就是我)跑起來,然後就回報這個錯Error:Execution failed for task ':app:tinkerProcessDebugManifest'.

> tinkerId is not set!!!

wtf!然後趕緊百度,去查詢wiki,哦哦,原來問題出在這裡

tinker的官方文件這麼寫,當時我是懵圈的。

tinkerId is not set:這是因為沒有正確的配置IDEgit路徑若不是通clone方式下tinker,需要本地手commit一次裡你也可以使用其他字元作tinkerId;

不過簡單,網上肯定給出了答案:

String gitRec =”自己定義一個字串”,不過建議這樣寫:(用你專案的versionName,也可以配置git路徑)

好了,這個問題搞定了,那我們再來跑一次,現在是見證奇蹟的時。。。wtf,什麼鬼啊。。。我要不要面子的啊。

Error:A problem occurred configuringproject ':app'.

> Failed to notify project evaluationlistener.

  > Tinker does not support instant run mode, please trigger build byassembleTestDebug or disable instant run in 'File->Settings...'.

  > Task with name 'tinkerPatchTestRelease' not found in project':app'.

奔潰中。。

這個錯誤是說tinket不支援install run 模式 ,請手動build assembleDebug 或者把 install run 模式禁用掉。

哇,終於成功了。

2驗證熱修復功能

我在MainActivity的佈局中加了一個Button:

<Button
   
android:id="@+id/btn_cool"
   
android:layout_width="wrap_content"
   
android:layout_height="wrap_content"
   
android:layout_alignParentLeft="true"
   
android:layout_alignParentStart="true"
   
android:layout_below="@+id/killSelf"
   
android:text="我很帥吧?"/>

findViewById(R.id.btn_cool).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View view) {
        Toast.makeText(view.getContext(), "不存在的", Toast.LENGTH_LONG).show();
    }
});

點選按鈕,彈出toast。嗯,很明顯這個是很嚴重的bug(純娛樂,這裡只是為了做演示)

假設這個是已經發布的版本,使用者體驗非常差,老闆要你在不更新app下,修復這個bug,那改怎麼辦?來用tinker搞定

首先,我們需要生存一個基礎包(也就是old apk)

在Android Studio右側Gradle的Gradle projects下點選assembieDebug,等待編譯debug包(如圖)

編包成功後,會在app/build/bakApk檔案下生成基礎包和R檔案(如圖)

app-debug-0324-10-50-29.apk就相當於當前使用者使用的APK(old apk),後面生成patch apk都是基於old apk和new apk的不同(diff)生成的。

app-debug-0324-10-50-29-R.txt當前APK的R檔案,也是用於生成patch apk的

然後需要在app的gradle下配置基礎包和R檔案(如圖),把我們需要的tinkerOldApkPath設定成上面介紹的app-debug-0324-10-50-29.apk,tinkerApplyResourcePath設定成app-debug-0324-10-50-29-R.txt

而tinkerApplyMappingPath指的是mapping 檔案,也就是你專案的混淆檔案。如果你專案開了混淆,那就把生存的mapping檔案配置上,這樣不僅能減少你補丁包的大小,也能加快你補丁包打到主程式的速度

tinkerBuildFlavorDirectory指的是多渠道打包,這裡先不做解釋,下面有詳細說明。這兩個地方可以先忽略,不去配置。

到這裡,基本的配置就介紹完了,現在我們需要去修復我們的bug,把toast中的文字改成“嗯,帥炸了!”(程式碼就不貼了)

要想熱修復成功,首先要有patch apk,這個patch apk是根據old apknew apk通過diff演算法得出的,老版本(old apk)bug,然後我們我們通過程式碼把這個bug修復了(new apk),通過Tinker diff演算法就得出了patch apk,然後oldapk(也就是使用者正在使用的版本)從遠端伺服器下載這個patch apk然後通過TinkeronReceiveUpgradePatch方法實現熱修復,如下所示:

TinkerInstaller.onReceiveUpgradePatch(getApplicationContext(), Environment.getExternalStorageDirectory().getAbsolutePath() + "/patch_signed_7zip.apk");
    }
});

既然知道修復的方式,那就來生成下patch包吧,如下圖所示,雙擊tinkerPatchDebug,等待編譯成功。

build成功後會在app/outpus/tinkerPatch/debug/下生成patch_signed_7zip.apk檔案,如圖所示:

然後我們只要把patch_signed_7zip.apk檔案放到手機的根目錄下,然後點選按鈕LOAD PATCH,不出意外的話,過一會兒就會彈Toast(patchsuccess,please restart process),然後殺死程序,重新進入app,點選Button(我很帥吧?),彈出Toast:

到這裡,通過Tinker實現了熱修復功能

Tinker的接入

gradle接入

gradle是推薦的接入方式,在gradle外掛tinker-patch-gradle-plugin中我們幫你完成proguard、multiDex以及Manifest處理等工作。

新增gradle依賴

在專案的build.gradle中,新增tinker-patch-gradle-plugin的依賴

buildscript {

    dependencies {

        classpath ('com.tencent.tinker:tinker-patch-gradle-plugin:1.7.7')

    }

}

然後在app的gradle檔案app/build.gradle,我們需要新增tinker的庫依賴以及apply tinker的gradle外掛.

dependencies {

    //可選,用於生成application

    provided('com.tencent.tinker:tinker-android-anno:1.7.7')

    //tinker的核心庫

    compile('com.tencent.tinker:tinker-android-lib:1.7.7')

}

...

...

//apply tinker外掛

apply plugin: 'com.tencent.tinker.patch'

Pactch生成

Patch生成有兩種方式:

*基於命令列的方式。

*gradle編譯的方式。

1.gradle編譯生成patch

 微信Tinker的gradle配置可以參照demo,具體引數請先瀏覽Tinker接入指南,點選檢視,同時這裡附上一份相對完整的gradle配置。

Api引入

自定義Application類

程式啟動時會載入預設的Application類,這導致我們補丁包是無法對它做修改了。如何規避?在這裡我們並沒有使用類似InstantRun hook Application的方式,而是通過程式碼框架的方式來避免,這也是為了儘量少的去反射,提升框架的相容性。

這裡我們要實現的是完全將原來的Application類隔離起來,即其他任何類都不能再引用我們自己的Application。我們需要做的其實是以下幾個工作:

將我們自己Application類以及它的繼承類的所有程式碼拷貝到自己的ApplicationLike繼承類中,例如SampleApplicationLike。你也可以直接將自己的Application改為繼承ApplicationLike;

Application的attachBaseContext方法實現要單獨移動到onBaseContextAttached中;

對ApplicationLike中,引用application的地方改成getApplication();

對其他引用Application或者它的靜態物件與方法的地方,改成引用ApplicationLike的靜態物件與方法;

這個是官方文件說的。具體的做法可以參照如下幾步:

第一步:

       可以把demo中一些需要的類拷貝到自己的工程中,放在一個資料夾中如圖:

第二步:修改SampleApplicationLike中生成Application的名字或者包名。

build後會在build/generated/souce/apt/檔案下生成你定義的Application,如圖:

第三步:如果我們專案中已經存在了自己定義的Application了,該怎麼辦呢?

直接讓你自己定義的Application繼承自Tinker生成的O2oInApplication即可,如果找不到這個類,請rebuild下。

第四步:

 我們需要在AndroidManifest.xml清單檔案中配置Tinker生成的Application(O2oInApplication)

同時需要配置Tinker Service:

寫完後如果報紅,此時只需要Build下即可解決報紅。Application配置就到此結束。接下來生成patch檔案。因為patch檔案是寫入到SDCrad的,所以我們需要在AndroidManifest中新增如下許可權(注:6.0及已上系統請動態設定許可權或者手動在設定中為專案設定):

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

具體生成patch步驟和demo中演示是一樣的,這裡不重複演示。

多渠道打包

官方文件也對這個進行了說明:如下

關於渠道包的問題,若使用flavor編譯渠道包,會導致不同的渠道包由於BuildConfig變化導致classes.dex差異。這裡建議的方式有:

將渠道資訊寫在AndroidManifest.xml或檔案中,例如channel.ini

將渠道資訊寫在apk檔案的zip comment中,種是建方式,例如可以使用或者可使用V2 Schemewalle

若不同渠道存在功能上的差異,建將差異部分放於獨的dex或採用相同代不同配置方式實現

事實上,tinker也支援多flavor直接編譯多個補丁包,具體可參考

這裡主要演示tinker支援的多flavor直接編譯多個補丁包

通過flavor編譯,這個時候我們可以看到bakApk路徑是一個按照flavor名稱區分的目錄;

我這裡只是做了一個渠道,大家可以測試多個。

將編譯目錄路徑填寫到gradletinkerBuildFlavorDirectory,其他的幾個欄位不需要填寫,這裡會自動根據路徑拼接;

3.執行tinkerPatchAllFlavorDebug或者tinkerPatchAllFlavorRelease即可得到所有flavor的補丁包。

最後會生成多了補丁包,根據你渠道名稱新建資料夾,放在其中

到這裡多渠道打包就完成了。雖然簡單,但是大家可以瞭解下多渠道打包的過程,以及我打包中遇到的問題

我在打多渠道補丁包的時候出現了這樣的一個問題

導致這個錯誤的我在release中重新定義了apk打包後的名稱:

所以在bakApk和outputs/apk下apk的名稱會變成我定義的包命TosO2O_v2.5.0.apk

在多渠道編包的時候會執行下面的程式碼

這裡會判斷是否存在多渠道,然後根據不同渠道的名稱在bakApk下輸出不同的渠道的R檔案和apk包,其中apk的名稱會根據outputs檔案下apk的名稱進行替換。所以我們可以在bakApk下看到Tos020_v2.5.0.apk的。重點來了,既然替換了,為什麼還是會報錯呢?好了,讓我們看下面的程式碼

執行tinkerPatchAllFlavorDebug或者tinkerPatchAllFlavorRelease時候查詢檔案其實是走了這兩段程式碼。其中紅框中的程式碼就是那到你要編譯補丁包的old-Apk,R檔案,mapping檔案。但是這裡的這行程式碼:

project.tinkerPatch.oldApk = "${originOldPath}/${flavorName}/${project.name}-${flavorName}-release.apk"

規定了old-Apk的名稱和路徑,和我們自己定義的apk名稱不一樣,所以報了

的錯誤。到這裡我們瞭解了多渠道編包的流程,也就找到了問題所在,只要我們把上面那行程式碼修改成

project.tinkerPatch.oldApk = "${originOldPath}/${flavorName}/TosO2O_v2.5.0.apk"

其實也就是報apk名稱改成我們自己的。就ok

重新編譯,問題解決。

這裡主要闡述tinker的整合和編譯,下篇文章將對tinker的原始碼進行淺析


相關推薦

Tinker整合多渠道打包

Tinker是什麼 Tinker是微信官方的Android熱補丁解決方案,它支援動態下發程式碼、So庫以及資源,讓應用能夠在不需要重新安裝的情況下實現更新。當然,你也可以使用Tinker來更新你的外掛。 它主要包括以下幾個部分: 1.gradle編譯外掛: tinke

Tinker整合多渠道打包

整合見官網 注意事項: 1.修改自定義application 有3個地方 ,換成自己的包名即可 2.修改打補丁apk,R,mapping檔案,和生成補丁檔案的位置 3.生成補丁,開啟Terminal ,執行命令 ./gradlew tinkerP

app打包、混淆、加固多渠道打包

1:打包步驟: 1:桌面建立一個資料夾,名字叫keystore 2:點選build下面的 ,如下: 3:會出現如下介面: 4:下一步: 5:如果有keystore,請點選 choose existing,選擇以前的keystore,

騰訊樂固的加固多渠道打包客戶端配置

1、概述 近日專案新版本上線,各大市場都正常,但是騰訊的應用寶稽核提示需要用樂固加固,因為之前一直用360加固並進行多渠道打包,但是提示如果不用樂固可能會稽核不通過,不給曝光率啥的,所以單

Android studio 多環境打包多渠道打包

1.多環境打包 在android開發中經常遇到要打不同環境的包,所謂不同環境就是介面連線的伺服器域名不同,如開發環境為devIP,測試環境為buildIP,uat環境為uatIP,release環境為releaseIP 。以前的做法是同過一個static變

android開發之Jenkins+Gradle實現android開發持續整合多渠道打包

需求: 我今天在專案上加了一個功能,那麼一個好的專案開發流程必然得跑單元測試,意思是:“改一次程式碼,需要手動跑一次單元測試,來檢驗程式碼在當前情況下是否能執行成功!”,但每次都需要手動跑的話就太累了,因為一個新增專案功能,我一天下來可能會改十幾次程

借騰訊開源 VasDolly,談談 Android 簽名多渠道打包的原理!

一、前言 Hi,大家好,我是承香墨影! 當我們需要釋出一款 App 到應用市場的時候,一般需要我們針對不同的市場生產不同的渠道包,它們使用的是同一套程式碼,只是會包含一些各自的渠道資訊,用於我們做資料分析。 前幾天,企鵝電競團隊開源了自己的 And

as中apk簽名多渠道打包

1.什麼是簽名: 數字簽名就是為你的程式打上一種標記,來作為你自己的標識,當別人看到簽名的時候會知道它是與你相關的 2.為什麼要簽名 防止盜版,app市場可以檢測簽名未簽名的apk無法安裝,也沒法釋出到應用市場包名相同,簽名不同的apk無法升級覆蓋 3.怎麼簽名 bu

騰訊Tinker 熱修復 Andriod studio 3.0 配置整合(二)多渠道打包補丁釋出

騰訊Tinker 熱修復 Andriod studio 3.0 多渠道打包和釋出補丁方式推薦 本文說明 在之前我已經分享了Tinker 熱修復的 Andriod studio3.0 初次配置和整合,時隔這麼久來寫一下我對Thinker多渠道打包的理解和記錄,希望對大家有幫助。這篇文

bugly整合Tinker熱修復,多渠道打包 簽名

自己記錄一下,對其他人有幫助更好 https://mp.weixin.qq.com/s/1kRTqyF4JC5lLwpxUae9NA   (感謝分享) 在這裡面使用的是博主說的第二種方式  快速打渠道包工具(Gradle)  walle 然後在git上找到 walle的專案

Android美團多渠道打包Walle整合

一、為什麼使用美團多渠道打包的方式? 打包更加快速 傳統的通過productFlavors渠道包的方式,渠道10個以內還可以接受,如果100個渠道包,每個包需要打5Min,就是將近10個小時的打包,而採用美團Walle多渠道打包的方式只需要打一個包的時間。 配置更加靈活 可以在APK渠道包中通過配

openinstall:多渠道打包統計的解決方法

現在市場上至少有十餘家主流安卓應用市場,這意味著App上架前Android工程師至少需要打十幾個包,在較少渠道的時候還能應付得過來,但在面對上千個渠道的時候,還需要再打上千個包,效率自然非常的低,甚至還有被抓包的可能,存在一定的資料誤差風險。此外,客戶端還需要把收集來的渠道碼通過介面傳送給服

Android熱更新Tinker + 多渠道打包 + 加固的流程詳解

一、Tinker熱修復 關於熱修復的作用,不用多說了,一句話概括就是通過讓使用者無感的方式來修復線上應用的bug。這裡介紹的是微信Tinker。 下面的接入方式都是參考自Tinker官方文件來。我這裡主要是把我接入的步驟(通過AndroidStudio +

Android Studio多渠道打包程式碼混淆教程

http://coolshell.info/blog/2015/03/android-studio-prefrence.html 什麼是Gradle Gradle是一種依賴管理工具,基於Groovy語言,面向Java應用為主,它拋棄了基於XML的各種繁瑣配置,取而

[Android Studio 權威教程]多渠道打包一鍵完成(全部產品)打包並簽名

好久沒有更新blog了,今天給大家帶來的是AS 的多渠道打包,並且我們還要驗證是否實現了多渠道打包的功能,最後在讓大家爽一下實現一鍵打包所有的渠道包並且給apk簽名 多渠道打包 方法1 第一步:新增渠道表示標籤

Android Studio使用Gradle實現自動打包,簽名,自定義apk檔名,多渠道打包整合系統簽名證書【附效果圖附原始碼】

        接觸Android Stuidio有一陣子了,之前用的時候有很多小問題,不過現在的版本感覺已經很好用了,所以準備徹底從Eclipse轉戰Android Stuidio,這段時間把以前經常使用的公用庫都從Eclipse移植過來了,今天研究了一下在Andro

熱修復框架Tinker最完整講解(02)——加入Walle多渠道打包

前言 上一篇文章 熱修復框架Tinker最完整講解(01)——整合之路 已經介紹我們的專案渠道包有20個,並且我們多渠道打包是採用productFlavors實現的。但是這種多渠道打包會造成20個渠道包的熱更新就需要20個補丁,這樣肯定是不合理的。那怎

Android實戰——Tinker整合使用

前言 對於熱修復我相信很多小夥伴都已經知道它們普遍的操作套路,Tinker主要是依賴自己的gradlePlugin生成拆分包,所以其拆分包的生成就由Gradle來完成,當然也可以通過命令列的方式,這裡就不對命令列做講解,Tinker接入指南 專案結構

Tinker熱修復 及walle多渠道打包流程

普通打包 1 Constants.isWalleChannel 設定成false 2 不要註釋掉    <meta-data             android:name="UMENG_CHANNEL"             android:value="${

Tinker整合步驟整合中所需要的問題

整合Tinker所需要的問題: 1,複製demo中的build.gradle 修改完成以後出現 Error:(9, 0) Could not get unknown property 'TINKER_VERSION' for object of type