本發(fā)明涉及計算機領域,具體是一種針對android應用的bug修復和持續(xù)交付方案。
背景技術(shù):
Android系統(tǒng)版本眾多,機型眾多,每次發(fā)布一個版本都是需要較長的時間。Android應用版本升級至少需要兩周才能達到80%的升級率,嚴重阻礙了版本迭代速度。也導致市場上App版本分散,處理bug和投訴等也越來越麻煩。
近一兩年采用Android熱補丁框架解決上述問題非常熱門。從開始360公司研發(fā)的動態(tài)下發(fā)lua腳本,到后來出現(xiàn)的各種方案。
早期的補丁框架偏向于以代碼修復為主,主要分為兩大類:nativehook方案和Multidex方案。
native hook方案如阿里巴巴的AndFix和Dexposed。Multidex方案如Qzone。切入點都是替換掉將要執(zhí)行的代碼?;赒zone方案的思路,出現(xiàn)了nuwa這個比較完善的庫,工具鏈比較完善。
但是上述兩種方案都存在一定的缺陷,AndFix只能修改方法、不能修改字段、不能新增類等問題,其庫本身難于維護(需要依賴外部開源力量進行維護),nuwa僅支持更新Java代碼,不能更新資源和so文件,滿足不了需求。
技術(shù)實現(xiàn)要素:
本發(fā)明的目的在于提供一種針對android應用的bug修復和持續(xù)交付方案,以解決上述背景技術(shù)中提出的問題。
為實現(xiàn)上述目的,本發(fā)明提供如下技術(shù)方案:
一種針對android應用的bug修復和持續(xù)交付方案,其主要步驟如下:
101:真實的Application類是MyApplication,在編譯期間自動修改AndroidManifest.xml文件,把MyApplication替換為MyNewApplication;
102:App啟動后由MyNewApplication加載相應的dex文件后,再將控制權(quán)交回給MyApplication。
作為本發(fā)明進一步的方案:所述MyNewApplication加載相應的dex文件的方法如下:假設Android安裝包中dex文件包含三個文件:classes.dex、classes2.dex和classes3.dex;dex文件的classes.dex充當?shù)慕巧褪羌虞d器,負責啟動App,并且從App加載資源加載后面的兩個dex文件,classes2.dex和classes3.dex;使App啟動需要用到的所有類都集中在classes.dex中。
作為本發(fā)明再進一步的方案:所述App加載資源是依賴Context#getResources函數(shù)返回的Resources對象。
與現(xiàn)有技術(shù)相比,本發(fā)明的有益效果是:
本發(fā)明通過把APP應用僅僅作為一個加載器。系統(tǒng)啟動App之后,加載器決定將要運行的代碼和資源的位置。當有新功能或者有bug修復補丁需要推送給用戶時,只需要下載對應的文件,通過替換加載器內(nèi)容即可。即將一個應用app的功能分解為多個部分,核心APP為一個加載模塊,其他功能均作為加載模塊的內(nèi)容,當某一個模塊出現(xiàn)了問題,或者需要增加刪除某一個模塊時,只需要通知加載器處理對應的模塊即可。此方法可以較為簡單便捷的解決業(yè)務模塊中的bug,以及版本的快速迭代。
具體實施方式
下面結(jié)合具體實施方式對本發(fā)明的技術(shù)方案作進一步詳細地說明。
一種針對android應用的bug修復和持續(xù)交付方案,其主要步驟如下:Android應用中Application類由于啟動就被加載而不能被更新,我們通過代理Application,控制Application從新dex文件中加載。
101:真實的Application類是MyApplication,在編譯期間自動修改AndroidManifest.xml文件,把MyApplication替換為MyNewApplication;所述MyNewApplication是App的入口Application;
102:App啟動后由MyNewApplication加載完相應的dex文件后,再將控制權(quán)交回給MyApplication;
所述MyNewApplication加載相應的dex文件的方法如下:
dex文件分成兩部分:patch庫的dex文件(->classes.dex)和業(yè)務代碼的dex文件(->classes[N].dex);其中patch庫的dex文件中僅包含了patch庫的全部代碼,并不包含任何其他業(yè)務代碼。
假設Android安裝包中patch庫的dex文件包含三個文件:classes.dex、classes2.dex和classes3.dex;patch庫的dex文件的classes.dex充當?shù)慕巧褪羌虞d器,負責啟動App,并且加載后面的兩個dex文件,classes2.dex和classes3.dex;這樣做的目的是,App啟動需要用到的所有類都集中在classes.dex中,同理,業(yè)務代碼的dex文件所有類都集中在classes[N].dex中;
如果某次下發(fā)patch代碼把classes2.dex變更為classes2-1.dex,那么由加載器加載classes2-1.dex和classes3.dex即可實現(xiàn)更新包含MyApplication類在內(nèi)的所有代碼;
如果dex文件有更新,加載器會選擇加載更新后的文件。
我們最初采用了Google官方的Multidex方案,擴展DexPathList的dexElements字段。單純更新Java代碼的patch框架,實用性會受到很大的局限。開發(fā)需要仔細驗證提交內(nèi)容,確保提交中不包含資源文件的變更以及native so的改動,會導致本就復雜的開發(fā)流程變得更加繁瑣。所以我們在支持更新Java代碼的基礎之上,也支持更新資源和native so文件。
App加載資源是依賴Context#getResources函數(shù)返回的Resources對象。Resources內(nèi)部包裝了AssetManager,最終由AssetManager從Android安裝包文件中加載資源,所以我們反射了替換系統(tǒng)默認的Resources,讓AssetManager從我們更新后的apk中加載資源;現(xiàn)階段的實現(xiàn)支持比如string/anim/drawable/color/layout等資源文件的變更;由于Android系統(tǒng)在安裝apk時候已經(jīng)把AndroidManifest.xml文件解析并寫入到系統(tǒng)中,目前還不支持修改四大組件,比如增加Activity。
在Android項目中使用native函數(shù)前需要先調(diào)用System.loadLibrary(libName)。
首先想到的是在代碼中把加載so文件的代碼改成System.load(libFilePath),讓系統(tǒng)加載自己指定的libFilePath文件。
查找lib文件是通過調(diào)用PathClassLoader的findLibrary,最終調(diào)用到DexPathList的findLibrary。DexPathList會在自己維護的列表目錄中查找對應的lib文件是否存在。所以我們在發(fā)現(xiàn)patch文件中有so文件變更的時候,會在PathClassLoader的nativeLibraryDirectories(Android6.0以下)或者nativeLibraryPathElements(Android 6.0及以上)的最前面插入自定義的lib文件目錄。這樣ClassLoader在findLibrary的時候會先在自定義的lib目錄中查找,優(yōu)先加載變更過的so文件。
本發(fā)明的工作原理是:本發(fā)明通過把APP應用僅僅作為一個加載器。系統(tǒng)啟動App之后,加載器決定將要運行的代碼和資源的位置。當有新功能或者有bug修復補丁需要推送給用戶時,只需要下載對應的文件,通過替換加載器內(nèi)容即可。即將一個應用app的功能分解為多個部分,核心APP為一個加載模塊,其他功能均作為加載模塊的內(nèi)容,當某一個模塊出現(xiàn)了問題,或者需要增加刪除某一個模塊時,只需要通知加載器處理對應的模塊即可。此方法可以較為簡單便捷的解決業(yè)務模塊中的bug,以及版本的快速迭代。
上面對本發(fā)明的較佳實施方式作了詳細說明,但是本發(fā)明并不限于上述實施方式,在本領域的普通技術(shù)人員所具備的知識范圍內(nèi),還可以在不脫離本發(fā)明宗旨的前提下作出各種變化。