成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

從大團隊并肩作戰到小團隊帶頭沖鋒,蘇寧App插件化應用實踐

原創
開發 架構 開發工具
從大團隊并肩作戰到小團隊帶頭沖鋒,高效的研發模式使得 App 本身的整體崩潰率始終維持在 0.02% 以下。

【51CTO.com原創稿件】從大團隊并肩作戰到小團隊帶頭沖鋒,高效的研發模式使得 App 本身的整體崩潰率始終維持在 0.02% 以下。

簡介

從大團隊并肩作戰到小團隊帶頭沖鋒,高效的研發模式使得 App 本身的整體崩潰率始終維持在 0.02% 以下。

本著以用戶為中心、以開發者為出發點,根據現有開源方案取長補短,蘇寧易購移動開發部于 2017 年初自主研發出了新型插件化技術——APNP(Android Plugin And Play),旨在讓研發更敏捷,讓發布更靈活,最終滿足用戶對產品的極速體驗、按需下載、動態更新。

需求分析

技術的引入來自于實際業務場景對技術的需求,插件化亦是如此,那么到底是什么原因推動了蘇寧易購 App 的插件化,又是什么原因讓蘇寧易購開發者走上自研插件化的道路?

為什么蘇寧易購 App 需要插件化?

發布周期長,產品迭代跟不上市場需求

對于一個電商 App,不同的時間、地點,伴隨著用戶千變萬化、稍縱即逝的消費需求,誰能在***時間滿足這些需求,誰就能把握住需求帶來的銷量。

而傳統的 App 開發模式周期過長,我們需要更敏捷的發布方案,所以我們做了插件化,這也是蘇寧易購對插件化最原始的需求。

單線研發,管理、協作成本過高

隨著蘇寧易購業務的不斷拓展、項目參與人員數量的增多,單線 App 開發模式所隱藏的問題日益凸顯:一面從需求分析到研發測試,需要監管的內容越來越多;另一方面從方案決策到流程審批,協作溝通越來越頻繁,成本越來越高。

因此我們需要多線、小團隊的研發模式,這讓我們進一步確認了插件化。

安裝***大,運營推廣效率走低

需求在日益增長的同時,安裝包體積也在同步膨脹。面對耗時、耗流量的安裝包下載,新用戶體驗、老用戶升級的阻力也越來越大。

為了解決這個問題,我們需要拆包、需要動態下載、需要局部更新,因此我們正式引入了插件化。

什么選擇自研而不是使用開源方案?

沒有***無暇的開源方案,卻有層出不窮的接入問題

移動團隊在一開始選擇過幾種開源方案,個別方案的可用性也比較高,但是在接入之后,測試環節總會出現些疑難雜癥,修復起來相對困難,一方面是源碼本身的掌握成本較高,另一方面就是開源方案本身存在的缺陷。

要么另起爐灶,要么藕斷絲連

現有的開源方案,要么就是對現有工程的改造較大,開發有心無力;要么就是插件工程和宿主工程相互依賴,牽一發而動全身,成本、風險都很高。

插件方案選型

基于上述種種原因,我們決定自研插件化技術,于是就有了 APNP。APNP采用的插件方案是直接加載 APK 文件(APK 格式不變,內容有所修改),原因有如下幾點:

兼容性高

APK 文件的格式非常穩定,它包含一個 App 正常運行的必要資源;任何版本的 Android 系統,都應該正常解析并運行任意版本匹配的 APK 文件,無論這個 APK 文件是何時產生的;我們只要正確模仿系統加載 APK 的行為,就可以加載任意一個插件 APK 文件。

研發隔離

既然是直接加載 APK 文件,所以在 APNP 的設計方案中,每個插件都是一個單獨工程,這就意味著除了***的集成測試階段,插件對應的整個軟件生命周期都是獨立的,既降低了管理、協作成本,又促使插件產品的發布更加靈活。

接入簡單

既然是獨立工程,無論現有的工程是如何運轉的,開發者唯一要做的就是把插件工程從現有工程中抽離出來。

核心手段及原理

如果直接加載一個原始插件的 APK 文件,絕大多數情況下是無法運行的,如 Class pre-verified 異常、ResourceNotFound 等。

因此 APNP 在保持 APK 格式不變的情況下,對APK里面的內容做了針對性修改,核心手段如下:

共同 Dependency 剔除

在研發過程中,經常需要第三方依賴 Library(Dependency),而當插件工程(以下簡稱 Plugin)和宿主工程(以下簡稱 Host)包含相同的 Dependency 時,就需要剔除 Plugin 中的 Dependency。

這樣一方面可以避免 Class pre-verified 異常,另一方面也可以減少插件包的大小,提升插件包的下載 & 加載速度。

實現方案(以下都默認 IDE 為 Android Studio):通過 Gradle 插件,在 Plugin 的 Transform 過程中,剔除與 Host 相同 Dependency 的所有資源。

Package ID 修改

在 Android 系統中,App 對應的 Package ID 是固定的,也就是說如果我們不人為干預,Plugin 和 Host 打包生產的 APK 文件中,所有 Resource ID 中的 Package ID 都是一樣的,即(0x7f)。

這時如果直接加載 Plugin APK,必然會出現 Resource 類型不匹配、顯示錯亂等異常,所以我們修改 Plugin 的 APK 的 Package ID。(Package ID 滿足 0x01 < PID < 0x7f 即可)

實現方案:業內關于修改 Package ID 的方案有很多(如修改 aapt 源碼等),APNP 采用的方案是直接修改***生成的 APK 文件。

先看下一個簡單 APK 的文件結構,如下圖:

涉及 Package ID 修改的地方有 3 處:

  • R.class(classes.dex)
  • resources.arsc
  • xml 文件

修改 R.class 中的 Package ID

在 Gradle assemble 之后,會在 build/generated/source/r 文件下生成相應的 R.java 文件,如下圖:

此時我們將 R 文件中的 0x7f 直接替換成目標 Package ID ,然后繼續交給 Gradle 做后續操作。

這樣在最終的 classes.dex 中,里面的 R.class 文件對應的 Package ID 就是我們想要設置的 Package ID。

修改 arsc + xml 中的 Package ID

不同于上面通過 Hook Gradle 過程修改中間生成的 R 文件,arsc + xml 則是直接解壓最終的 APK 并修改目標文件,然后重新簽名。

首先我們需要對 APK 文件中的 arsc + xml 的文件格式有一定的認識,Android 為了充分減少 APK 自身的大小,在編譯的過程中會對所有的資源進行重組 + 壓縮。

例如 values 文件下的內容會被統一收集到 arsc 文件中,而不再以文件的形式存在;而 xml 也不再是原始的 xml 文件,xml 中內容會被進一步整合 + 復用。

而無論是 arsc 文件,還是 xml 文件,在它們內部都是通過一個個固定數據結構的 ResChunk 以嵌套 + 組合的形式各自存儲著。

資源信息:每段 ResChunk 的內容都以 8 字節的 ResChunk_header 開頭,用于描述 ResChunk 的類型 + 長度,如下圖:

也就是說 arsc + xml 中的所有內容都可以被反向解析出來,當充分了解每個 ResChunk 的數據結構以及掌握 ResChunk 中哪些內容是需要修改的 Package ID,就可以相對輕松的完成對二進制文件的修改。

 Library Chunk 插入

修改完 Package ID 后,還需要在 resources.arsc 文件中插入一段 Library Chunk ,如下圖:

Library Chunk 在 Android 5.0 之后才出現,對應的類型如下圖:

那么為什么需要插入 Library Chunk?原因是在 Android 5.0 之后,ResTable在獲取資源信息時,如果資源含有 Parent(ResTable_map_entry,如 style),會驗證 Parent 的 Package ID 是否合法,也就是 Package ID 是不是已經注冊過了。

如果 lookupResourceId 沒有返回 NO_ERROR,則報錯,繼續跟進,如下圖:

由于在上一環節中,我們已經把 Plugin 中的 Package ID 修改了,上圖中的局部變量 packageId 肯定不會是 APP_PACKAGE_ID 。

***會在 mLookupTable 數組中尋找 packageId 是否有對應的值,如果沒有(值為 0)則拋出異常。

所以我們需要把自定義的 Package ID 注冊到 mLookupTable 數組中,那么注冊的動作是在什么時候發生的?

在 App 啟動并資源***加載時,會調用下面的方法去解析 arsc 文件,如下圖:

如果發現是 Library Chunk 會調用 addMapping,如下圖:

在 addMapping 中,我們會把 Library Chunk 中的 packageId 在 mLookupTable 數組中進行注冊(就是簡單的賦值),注冊之后我們自定義的 Package ID 才會被系統認可,從而確保含有 Parent 資源的正常解析。

 Attr ID 替換

完成上面 3 步后,APK 就已經可以加載了,但是插件涉及到自定義屬性的 View ,自定義屬性總是無法正常賦值,這又是什么原因呢?

以 ConstraintLayout 為例,假如 Plugin 和 Host 的 Layout 布局中都包含 ConstraintLayout,并同時都設置了 ConstraintLayout 的自定義屬性如下:

那么在 App 運行的過程中,ConstraintLayout 會通過 android.support.constraint.R.class 獲取解析自定義屬性,如下圖:

而 android.support.constraint.R.class 在內存中只有一份,并且會優先加載 Host,因此在實際的運行內存中,R.class 來自于 Host。

由于 Host 中 R.class 里面的 Package ID 都是 0x7f ,而在上面第二節的修改 Package ID 環節中,Plugin 里面的 xml 的 Package ID 已經被我們修改了(包括 xml 中所引用的 Attr ID)。

因此當 Plugin 通過 Host 的 R.class 去解析 ConstrainLayout 時,必然會出現自定義屬性無法正常解析的異常。

所在 APNP 在修改 Plugin xml 文件 Package ID 的同時,如果發現 Attr 同樣存在于 Host 中,會把 Plugin xml 文件中的 Attr ID 替換成 Host 中的 Attr ID,從而保證 Plugin 中所有的自定義屬性能夠正常解析(紅框:0x7f01000f,0x7f010022,0x7f010026,0x7f01002b),如下圖:

否則直接修改 Package ID(藍框:0x7e010000,0x7e010001,0x7e010002)。

實踐成果

在 APNP 實際應用之后,通過蘇寧云跡平臺的實時數據監控,并沒有發現因 APNP 本身引起的明顯異常。

從大團隊并肩作戰到小團隊帶頭沖鋒,高效的研發模式也使得 App 本身的整體崩潰率始終維持在 0.02% 以下。

相比之前的研發流程,APNP 帶來的影響主要有下面幾個點:

產品更精細、定位更明確 

APNP 是產品精細劃分和明確定位的技術支撐,小團隊的研發模式,加快了產品的落實與升級。

研發周期短、發布更靈活

插件可單獨升級、可獨立發布的特征,配合獨立團隊的專人專職,單一產品可以達到一周一版本。

管理更輕松、研發更高效

同步產品線的精細劃分,研發團隊也趨于更小、更獨立,管理也顯得更加輕松;同時明確的責任分工,也促進了研發人員的工作效率。

發展前景

Google 在今年的 IO 大會上推出了一種動態加載方案——App Bundles,可以讓用戶通過 Google Play 動態下載應用功能,而且 App Bundles 采用的方案也是直接加載 APK 文件。

通過分析最終的 Feature Master APK 文件,你會發現 App Bundles 對 APK 做了和 APNP 相同的操作:剔除 Dependency、修改 Package ID、插入 Library Chunk、替換 Attr ID。

這看似巧合實則必然,因為 App Bundles 和 APNP 都是直接加載 APK 文件,所以面對的問題都是一樣的。

在方案上 APNP 可以說有了官方保障,而且 APNP 在后面還可以借鑒 App Bundles 的實現細節,讓插件加載更加高效、安全。

而由于 Android P 對隱藏 API 調用的限制,很多人認為插件化方案將不再可行。

但是 Google 也同時提供了 light greylist,并且國內手機廠商肯定不允許讓主流 App 無法使用的情況發生,所以我覺得在很長一段時間內,插件化依然可以正常運轉。

作者:李呈武

簡介:蘇寧易購前端技術專家,資深Android 開發者,深度掌握 Android 虛擬機、插件化、Weex 等技術,熟悉移動網絡的特質,對移動端的架構設計有獨特的見解,一直致力于通過優秀的架構設計,減少開發成本,提升開發質量。

【51CTO原創稿件,合作站點轉載請注明原文作者和出處為51CTO.com】

責任編輯:武曉燕 來源: 51CTO技術棧
相關推薦

2018-06-08 09:00:00

開發軟件程序員

2016-04-14 12:30:18

現場報道Google工程團隊

2018-11-12 12:45:19

2021-10-28 06:04:49

團隊作戰人才CIO

2022-10-27 10:33:48

敏捷開發開發

2019-04-09 08:00:00

蘇寧發票中心系統

2015-08-12 16:41:25

運維服務公共化

2022-02-20 22:16:44

ESLint工具JavaScript

2024-03-27 10:03:31

銳捷教育

2019-12-24 09:30:59

蘇寧高可用高并發

2023-10-25 16:56:51

新華三

2013-10-29 10:41:06

SAP

2017-09-13 16:46:38

敏捷站會團隊

2013-02-20 10:07:29

蘇寧電器蘇寧云商云服務

2017-08-10 16:59:21

蘇寧喬新亮英特爾

2019-02-25 09:30:00

微服務代碼小團隊

2018-05-25 22:56:14

AI技術短視頻蘇寧易購

2022-11-21 10:07:41

碼農裁員
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品国产乱码久久久久久丨区2区 | 亚洲一区二区三区在线 | 91精品国产91久久久久久 | 成人精品视频在线 | 91一区 | 亚洲精品一区二区三区 | 草久久 | 国产成人免费视频网站高清观看视频 | 久久综合九九 | 97视频精品 | 九九九久久国产免费 | 特级毛片www | 久久免费观看一级毛片 | 97国产精品 | 久久蜜桃av一区二区天堂 | 国产三级大片 | 欧美激情 一区 | 一区二区欧美在线 | 一区二区三区视频在线观看 | 午夜影院中文字幕 | 欧美一区二区大片 | 在线播放国产一区二区三区 | 亚洲永久入口 | 视频一区二区三区在线观看 | 黄在线免费观看 | 国产精品美女一区二区三区 | 国产精品视频 | 国产高清一区二区三区 | 久久久久亚洲视频 | 欧美日韩专区 | 日韩有码一区 | 成人av电影在线 | 鲁一鲁资源影视 | 三级黄色片在线观看 | 午夜免费网站 | 日韩精品极品视频在线观看免费 | 99精品久久99久久久久 | 欧美日韩在线看 | 亚洲精品第一 | 日产久久 | 午夜精品一区二区三区免费视频 |