分享自己在項目中如何更好的使用阿里SopHix進行熱修復

前言

本文最主要的是講解下自己是如何在在項目中更恰當合理的運用SopHix,當然這只是我團隊兩個人的做法而已。經驗總是要踩出來的,對同學有幫助就最好了。

以下分為六部分

  • 引言
  • 官方使用步驟
  • 測試開發中熱更新修復操作五部曲
  • 下發補丁步驟
  • 如何處理加載補丁成功后的彈窗強制更新提醒
  • 如何爬坑

一、引言

熱修復技術可謂是百花齊放,許多產品都聲稱自己可以做到全方位全功能的熱修復。不過他們各自有自身的局限性,或者不夠穩定,或者補丁過大,或者效率低下,或者使用起來過于繁瑣,大部分技術上看起來似乎可行,但實際體驗并不好。而在我們看來,有很多技術細節能夠做得更加完美。

終于在2017年6月11日,手淘技術團隊聯合阿里云正式發布了史上首個非侵入式移動熱更新解決方案——Sophix。

Sophix熱修復方案主要開發者,萬壑 就職于手機淘寶。

Sophix的橫空出世,將會打破各家熱修復技術紛爭的局面。我們可以滿懷信心地說,在Android熱修復的三大領域:代碼修復、資源修復、so修復方面,以及方案的安全性和易用性方面,Sophix都做到了業界領先。

文章介紹 https://yq.aliyun.com/articles/103527?spm=5176.8091938.0.0.l6pz1T
??下面的這張表格引用自[ 作者博文],從幾個熱修復最重要的維度,把Sophix和另外兩個主要商業化熱修復方案進行了比較。

Image.png

而其中唯一不支持的地方就是四大組件的修復,這是因為如果要修復四大組件,必須在AndroidManifest里面預先插入代理組件,并且盡可能聲明所有權限,而這么做就會給原先的app添加很多臃腫的代碼,對app運行流程的侵入性很強。可以插入幾個代理文件即可。我在項目中就這么做。

二、官方使用步驟

Android 接入流程請開發者務必仔細閱讀一遍官方文檔。文檔是最好的老師
先去創建應用
然后快速接入流程

三、測試開發中熱更新修復操作五部曲

  1. 打包區分的三個包
    Base_1.5.30 (基礎包用于對比)
    Safe_1.5.30(加固過后的包,發布給線上使用)
    Test_1.5.31(在打完Base包之后修改版本號,再打一個測試包,確保代碼一致,用于安裝,下發補丁首先下發到該版本,我是這么做的)

  2. Safe_1.5.30發布完上線之后 ,在你的Android Studio中修改版本號為1.5.33 繼續開發或者修復BUG,反正需要大于1.5.31(因為你做測試需要先在Sophix后臺下發補丁到1.5.31,你本地代碼沒有修改的話, build 運行時會收到Sophix服務器的下發的補丁,此時代碼覆蓋會讓你一臉懵逼)

  3. 這時你已經在 Dev_1.5.33 版本中修復了BUG,打包1.5.33之后,需要通過 Sophix工具上傳 基礎包 Base_1.5.30 進行比對生成 Sophix-Patch.jar 補丁包 ,(生成的補丁與版本號無關,工具只會對比代碼結構, so,資源等) 完成后將其上傳至Sophix后臺

  4. 指定下發對應版本號,先下發到Test_1.5.31 測試版本,補丁下發成功! 手機安裝 先測試驗收,驗收成功之后再指定下發到 正式的版本 1.5.30 即可

  5. Tips: 在Android Studio中 開發中的版本需要比Test1.5.31版本大,便于在 Build 運行項目時,不會因聯網下發到針對1.5.31的補丁 指示代碼收到下發的補丁 受影響

注意事項:

  • 下發補丁修復bug不要去修改 Manifest 的文件,發布補丁時的版本也最好不要去修改一些依賴庫的版本,會出現某些問題!

  • 還有打base包的 那份代碼需要備份這個分支,然后copy一個分支進行下一步的開發,以防萬一合成補丁出錯,進行代碼比對

  • 舊包內部版本號不能 比新包內部版本號大,不然會生成補丁出錯

??這里我并沒有使用官方的調試工具進行調試。而是直接在項目中查看日志補丁加載狀態。要多注意每個Code代表的意思 ,這里文檔也有描述到,詳情查看SDK中PatchStatus類的代碼,有具體說明

四、下發補丁步驟

生成補丁工具
??假設當前 版本為 1.5.30 為發布的包,而你要先進行更新測試包更新包版本為 1.5.31 ,這個時候你就要將最新代碼生成的apk文件包與base基線版本1.5.30做比對。此時生成的補丁文件 sophix-patch.jar 上傳至 Sophix 后臺。
??補丁版本為后臺自控的。會進行疊加。繼續上傳一個補丁則上一個版本的補丁自動停用.

  1. 添加版本號要注意格式1.X.X 或者 1.XXX
    ![~J$E2{$(6OFRBSI]WA7Y0MR.png](http://upload-images.jianshu.io/upload_images/956862-2a3012b0a3c770ab.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
  2. 上傳補丁文件,并且加點描述


    bing

官方管理后臺使用說明

五、如何處理加載補丁成功后的彈窗強制更新提醒

  • 強制更新補丁狀態說明:
    一般都會把查詢補丁的操作放在Application中去操作,Sophix啟動APP時會調用方法請求查詢最新的補丁,這句話一般在Application中的onCreate()方法的Super之前去進行調用,這里貼一下自己項目中的代碼

@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
initHotfix(base);
}

public void onCreate() {
SophixManager.getInstance().queryAndLoadNewPatch();
super.onCreate();
...
}
// 阿里熱修復
private void initHotfix(Context context) {
SophixManager.getInstance().setContext(this)
.setAppVersion(VersionUtils.getVersionName(this))
.setAesKey(null)
.setEnableDebug(false)
.setPatchLoadStatusStub((mode, code, info, handlePatchVersion) -> {
// 補丁加載回調通知
String s = "mode:" + mode + " code:" + code + "\npatchVersion:" + handlePatchVersion + "\ninfo:" + info;
hotfixController(context, code, handlePatchVersion, s);//這里是處理相對應的主要Code的操作,代碼就不貼完整了,你可以根據官方的來進行操作,建議多加一個對CODE_LOAD_NOPATCH 狀態碼14,沒有補丁的情況針對性的操作
}).initialize();
}
```

  • Q:收到Code 12 之后,有的包是需要提示用戶強制冷啟動的,而有的包是不用提示,等下次自己更新就好了。這樣的情況怎么判斷當前的包是處于哪種情況呢?
    需要提示 & 不需要再提示?
    A:官方給我的提示,需要自己加個推送什么的,回調中沒有這個標識。((__) 嘻嘻…… 如果Shophix后臺有支持就好了)

  • 這里主要講解下發成功 狀態為 1 "load new patch success."時,也就是補丁下發成功了,之后提醒用戶的操作。
    這里需要判斷兩個前提條件,都要提示用戶去重啟應用, 要注意回調狀態碼Code 等于12 “please relaunch app to load new patch” 的時候 就是冷啟動的提示。 這里我并沒有根據12去做判斷進行重啟。

下面說下我自己項目中的兩個必要重啟判斷條件,僅供參考。
     * 1、取得SopHix SDK啟動時返回的最新的補丁版本號(hotfixPatchVersion)和服務器返回的補丁版本號(hotfixMustUpdateVersion)相同,且大于當前最后一次強制重啟的補丁版本號(hotfixLastMustVersion 將每次返回的補丁版本寫入SP記錄) 

     * 2、或者第一次下載、數據被清除后,如果有新強制更新版本,則強制更新

 建議定義三個字段進行比較
public static final String hotfixPatchVersion = "hotfixPatchVersion"; // 阿里返回的補丁版本號
public static final String hotfixMustUpdateVersion = "hotfixMustUpdateVersion"; // 服務器返回的版本號
public static final String hotfixLastMustVersion = "hotfixLastMustVersion"; // 最后一次強制重啟的版本號

注意:

  1. 以上所說的這種方式,實際項目中加載了最新的補丁,需要把這個Sophix中最新的補丁版本號,告知后臺進行修改為最新更新的補丁號。一般在版本更新的接口中多加入一個字段(downloadPatchCode ),請求時用于進行比對。

  2. 提示用戶關閉時的處理,可以在PatchLoadStatusListener監聽到CODE_LOAD_RELAUNCH后在合適的時機,調用此方法殺死進程。注意,不可以直接Process.killProcess(Process.myPid())來殺進程,這樣會擾亂Sophix的內部狀態。因此如果需要殺死進程,建議使用這個方法,它在內部做一些適當處理后才殺死本進程。本人是直接在一個透明的 彈窗提示判斷中關閉時調用的此方法進行關閉。

 SophixManager.getInstance().killProcessSafely(); 

六、如何爬坑

以下是我所遇到過的兩個問題,遇到問題心態不要蹦,先去查看日志,再去查看官方文檔,或者QA,百分之七八十都可以解決,若你還不能解決你就去官方釘釘群交流:11734260 進行交流。

問題1

熱修復Android SDK:在4.x的手機系統上崩潰

在4.x的系統上出現IllegalAccessException:class ref in pre-verified異常,應用崩潰

問題原因
??這個是由于我們是完整dex修復,所以會出現新dex中的類和老dex中的類沖突,所以要在Sophix初始化前避免加載原有apk中的類,而對于4.x版本的系統,如果在Sophix初始化之前有加載原有apk中的類,則會影響修復的過程,造成崩潰

解決方案
https://help.aliyun.com/knowledge_detail/55414.html?spm=5176.7851422.2.4.SyAVhp
??Sophix初始化在Application最前面,同時盡量用系統類及盡量不使用log等,或者把initialize寫到attachBaseContext里面,但query還是在onCreat的最前面;如果有用到MultiDex,直接繼承Application,在attachBaseContext里寫MultiDex.install(base),然后在onCreat的最前面initialize和query,如果還會出現這個崩潰,把initialize寫到attachBaseContext的MultiDex.install(base)后面,但query還是在onCreat的最前面

問題2

這個問題很奇怪,項目老大解決的。我現在只知道不能這么做而已。
??在4.X的設備上,用OkHttp作為Fresco的網絡加載器的時候,如果發布新的包(比如只修改一個Toast),
在下載完重啟后會直接崩潰報如下錯誤:
Process: com.newtest.myapplication, PID: java.lang.IllegalAccessError: Class ref in pre-verified class resolved to unexpected implementation
而其他機型則不會。 很明顯和第一個錯誤是一樣的。

Sophix對4.X的機型有Bug: 在一個外部引用的包里,自帶的實例,需要去調用這個包里的另一個實例方法時,會報上面這個錯; 但把這個包里的實例移到App里創建,再去調用相同的那個方法里就不會了。 就是說4.X的引用包里的方法不能再次調用引用包里的別的方法。 現在已經解決了,但5.0及以上的機型卻不會有這個Bug,這只是很奇葩的問題,如果沒遇到過同學略過吧~

以上兩個問題也屬于同一個問題,詳細閱讀作者這邊文章會有些啟示。

  • 由于是直接在項目分支中引入的Sophix 所以沒有寫個Demo。
    有空補上(這是我聽過過最大的笑話)
    貼一個官方Demo

以上僅是自己的處理方式,寫的不好的地方還望指正,有問題還望同學們指點一二,O(∩_∩)O謝謝!
學會分享~

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,739評論 6 534
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,634評論 3 419
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,653評論 0 377
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,063評論 1 314
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,835評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,235評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,315評論 3 442
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,459評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,000評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,819評論 3 355
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,004評論 1 370
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,560評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,257評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,676評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,937評論 1 288
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,717評論 3 393
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,003評論 2 374

推薦閱讀更多精彩內容