Android外掛化:從入門到放棄
本文根據包建強在2016GMTC全球移動開發大會上的演講整理而成。
首先自我介紹一下,我叫包建強,是這個分場的主持人。我去年寫了一本書,叫《App研發錄》,相信有很多從事技術的朋友看過或買過。
引言
先簡單介紹一下Android外掛化。很早之前已經有公司在研究這項技術,淘寶做得比較早,但淘寶的這項技術一直是保密的。直到2015年才陸續出現很多框架,Android外掛化分成很多技術流派,實現的方式都不太一樣。我今天的主題就是,Android外掛化的不同流派、不同思想,以及做外掛化需要掌握哪些知識。
今天分享的題目是“從入門到放棄”。外掛化技術不是45分鐘演講能說清楚的,我大致算了一下,要真能講清楚這門技術起碼需要六個小時,每個小時講一個主題,包括Android底層系統與外掛化相關的類、四大元件的原理與相應外掛化實現方式、增量更新、AAPT等技術 。今天的分享濃縮成45分鐘,希望大家可以獲益。
分享內容分成七大部分。首先是前世今生,即外掛化的歷史。第二部分是入門知識,即與外掛化有關的Android系統底層的實現原理。第三部分是技術流派,即目前Android外掛化多種技術流派及其具體不同的實現方式。第四部分是周邊相關的技術實現。第五部分是目前國內流行的開源框架,包括各個公司正在使用的框架,還有流傳不是很廣但意義也很重大的框架。第六,是針對Android外掛化的一些問題的經驗分享。最後,是Android外掛化的未來——我們是否該放棄這門技術。
前世今生
Android外掛化的歷史,可能是本次演講最有價值的內容。我梳理了三年前到現在Android外掛化發展的一些規律。
首先,要記住2012年這個時間點。2012年的時候,就有人做外掛化技術,是大眾點評的屠毅敏,他推出了AndroidDynamicLoader框架,用Fragment來實現。大眾點評是國內做App比較早的公司,他們積累了很多的經驗,尤其是外掛化技術 。通過動態載入不同的Fragement,把想換的頁面都換掉。我們也是在這個專案中第一次看到了如何通過addAssetPath來讀取外掛中的資源。
2013年,出現了23Code。23Code提供了一個殼,在這個殼裡可以動態下載外掛,然後動態執行。可以在殼外編寫各種各樣的控制元件,放在這個框架下去執行。這就是Android外掛化技術。這個專案的作者和開源地址,目前不是很清楚。
2014年初,大家也許看過一個視訊,阿里一位員工做了一次技術分享,專門講淘寶的Altas技術,以及這項技術的大方向。但是很多技術細節沒有分享。
然後是任玉剛的里程碑式的專案。2014年底,玉剛釋出了一個Android外掛化專案,起名為dynamic-load-apk,這跟後續介紹的很多外掛化專案都不太一樣。它沒有Hook太多的系統底層方法,而是從上層,即App應用層解決問題,建立一個繼承自Activity的ProxyActivity類,然後讓外掛中的所有Activity都繼承自ProxyActivity,並重寫Activity所有的方法。之所以說這個專案是里程碑式的,是因為在2015年之前業界沒有太多資料可以參考。之後曾和玉剛聊天,他十分感慨當年如何舉步維艱地開發這個框架。我當時在途牛工作,使用了這個Android外掛化框架。
2015年4月,一個新框架推出來,叫OpenAltas,後來改名為ACDD。這個框架參考了淘寶App的很多經驗,主要就是Hook的思想,同時,還首次提出來通過擴充套件AAPT來解決外掛與宿主的資源id衝突的問題。
2015年8月,張勇釋出DroidPlugin。這是Android外掛化中第二個里程碑式的專案,這個專案太牛了,能把任意的App都載入到宿主裡。可以基於這個框架寫一個宿主App,然後就可以把別人寫的App都當作外掛來載入。這個框架的功能的確很強大,但強大的代價就是要改寫很多Android系統的底層程式碼,更別提這哥們還比較懶,沒有制訂任何說明文件,導致技術人員掌握這個框架不太容易。360的田維術曾編寫了一系列文章,專門介紹這個框架,後面我會介紹。
再之後就是百花齊放的時代了,GitHub上有很多外掛化框架,但這些框架影響都不大,我們這裡就略過了。
接下來登場的是熱修復技術。2015年5月,iOS推出了JSPatch,JSPatch通過Runtime的機制,能迅速修復線上App任何一個類的任何一個方法。而當時的Android系統沒有能迅速替換的方式。於是,在2015年9月,有人找到了實現迅速替換的途徑,就是Andfix,後面會講它的原理。
2015年10月,大眾點評的賈吉鑫做了一個專案,起名為Nuwa(女媧),主要思路跟Andfix差不多,都是解決Android的修復問題,能修復線上的任何一個方法。可惜後來沒有繼續維護。
最後,2015年底,仍然是Android外掛化框架,福建的林廣亮提出了一個新機制——Small框架,這個機制不太一樣的地方就是,通過指令碼的方式來解決資源衝突的問題。
入門知識
介紹完Android外掛化的歷史,接下來講一講Android外掛化需要的Android系統底層知識。在座的基本都是做Android開發出身,或許有一半到三分之一是資深的,還有的只做了一兩年,希望對外掛化有更深的認識。要想完全明白外掛化技術,首先需要了解Android系統的底層實現。
首先,做Android系統原始碼的人應該非常熟悉Binder,如果沒有它真的寸步難行。Binder涉及兩層技術。你可以認為它是一箇中介者模式,在客戶端和伺服器端之間,Binder就起到中介的作用,這是我這段時間對Binder的思考。要實現四大元件的外掛化,就需要在Binder上做修改。Binder服務端的內容沒辦法修改,只能改客戶端的程式碼。四大元件每個元件的客戶端都不太一樣,這個需要大家自己去發現,時間關係,這裡就不多說了。
學習Binder的最好方式就是AIDL。你可以讀到很多關於AIDL的資料,通過制訂一個aidl檔案自動生成一個Java類,研究一下這個Java類的每個方法和變數,然後再反過來看四大元件,其實都是跟AIDL差不多的方式。
其次,是App打包的流程。程式碼寫完了,執行一次打包操作,中途經歷了資源打包、dex生成、簽名等過程。其中最重要的就是資源的打包,即AAPT這一步,如果宿主和外掛的資源id衝突,一種解決辦法就是在這裡做修改。
第三,App在手機上的安裝流程也很重要。熟悉安裝流程不僅對外掛化有幫助,在遇到安裝bug的時候也非常重要。手機安裝App的時候,經常會有下載異常,提示資源包不能解析,這時需要知道安裝App的這段程式碼在什麼地方,這只是第一步。第二步需要知道,App下載到本地後,具體要做哪些事情。手機有些目錄不能訪問,App下載到本地之後,放到哪個目錄下,然後會生成哪些檔案。外掛化有個增量更新的概念,如何下載一個增量包,從本地具體哪個位置取出一個包,這個包的具體命名規則是什麼,等等。這些細節都必須要清楚明白。
第四,是App的啟動流程。Activity啟動有幾種方式?一種是寫一個startActivity,第二種是點選手機App,通過手機系統裡的Launcher機制,啟動App裡預設的Activity。通常,App開發人員喜聞樂見的方式是第二種。那麼第一種方式的啟動原理是什麼呢?另外,啟動的時候,main函式在哪裡?這個main函式的位置很重要,我們可以對它所在的類做修改,從而實現外掛化。
第五點更重要,做Android外掛化需要控制兩個地方。首先是外掛Dex的載入,如何把外掛Dex中的類載入到記憶體?另外是資源載入的問題。外掛可能是apk也可能是so格式,不管哪一種,都不會生成R.id,從而沒辦法使用。這個問題有好幾種解決方案。一種是是重寫Context的getAsset、getResource之類的方法,偷換概念,讓外掛讀取外掛裡的資源,但缺點就是宿主和外掛的資源id會衝突,需要重寫AAPT。另一種是重寫AMS中儲存的外掛列表,從而讓宿主和外掛分別去載入各自的資源而不會衝突。第三種方法,就是打包後,執行一個指令碼,修改生成包中資源id。
第六點,在實施外掛化後,如何解決不同外掛的開發人員的工作區問題。比如,外掛1和外掛2,需要分別下載哪些程式碼,如何獨立執行?就像機票和火車票,如何只執行自己的外掛,而不執行別人的外掛?這是協同工作的問題。火車票和機票,這兩個Android團隊的各自工作區是不一樣的,這時候就要用到Gradle指令碼了,每個專案分別有各自的倉庫,有各自不同的打包指令碼,只需要把自己的外掛跟宿主專案一起打包執行起來,而不用引入其他外掛,還有更厲害的是,也可以把自己的外掛當作一個App來打包並執行。
上面介紹了外掛化的入門知識,一共六點,每一點都需要花大量時間去理解。否則,在面對外掛化專案的時候,很多地方你會一頭霧水。而只要理解了這六點核心,一切可迎刃而解。
技術流派
接下來是技術流派。技術流派目前分三種。
第一種是動態替換,也就是Hook。可以在不同層次進行Hook,從而動態替換也細分為若干小流派。可以直接在Activity裡做Hook,重寫getAsset的幾個方法,從而使用自己的ResourceManager和AssetPath;也可以在更抽象的層面,也就是在startActivity方法的位置做Hook,涉及的類包括ActivityThread、Instrumentation等;最高層次則是在AMS上做修改,也就是張勇的解決方案,這裡需要修改的類非常多,AMS、PMS等都需要改動。總之,在越抽象的層次上做Hook,需要做的改動就越大,但好處就是更加靈活了。沒有哪一個方法更好,一切看你自己的選擇。
第二種是靜態代理,這是任玉剛的框架採取的思路。寫一個PluginActivity繼承自Activity基類,把Activity基類裡面涉及生命週期的方法全都重寫一遍,外掛中的Activity是沒有生命週期的,所以要讓外掛中的Activity都繼承自PluginActivity,這樣就有生命週期了。
第三種是Dex合併,Dex合併就是Android熱修復的思想。剛才說到了兩個專案——AndFix和Nuwa,它們的思想是相同的。原生Apk自帶的Dex是通過PathClassLoader來載入的,而外掛Dex則是通過DexClassLoader來載入的。但有一個順序問題,是由Davlik的機制決定的,如果宿主Dex和外掛Dex都有一個相同名稱空間的類的方法,那麼先載入哪個Dex,哪個Dex中的這個類的方法將會佔山為王,後面其他同名方法都替換了。所以,AndFix熱修復就是優先載入外掛包中的Dex,從而實現熱修復。由於熱修復的外掛包通常只包括一個類的方法,體量很小,和正常的外掛不是一個數量級的,所以只稱為熱修復補丁包,而不是外掛。
技術周邊
關於技術周邊的內容有三個部分。首先是AAPT,資源衝突,就是說預設App應用,外掛裡的資源和資料資源衝突,如果不引入這個資源,相安無事。很多時候就算有衝突也無所謂,問題就出在外掛引用資源的時候有衝突了,無法解決,怎麼辦?那就要立刻改寫App。有一個關於打包的App,可以加當前的字首,改成你想要的。比如,火車票和酒店分別取名,這樣就可以指定字首、打包,插進一個模組,資源的字首都不一樣。小米也承認,會佔用0x11這個字首。這是需要關注的一個點。
第二是增量更新。360目前最牛逼的地方是,把所有資料跟之前一個版本差,產生增量的資料。他們當然也更新了外掛化。360的劉存棟做了一個增量更新的框架。可以在後臺伺服器把兩個版本的Android App做拆分,然後把增量包下載到本地,再跟本地進行合併,提供一個STK,再合在一起,這就是增量更新。
第三是外掛管理平臺,要管理每個版本的差異、每個外掛最低資料的版本號。
尷尬困境
接下來是最近兩年出現的一些尷尬困境。
首先,外掛化已經淪落為修bug的工具。這跟外掛化的初衷不一樣,外掛化是實現新功能,而不是修復bug。
其次,外掛化現在有一個更好的替代品——RN。接下來,RN會是真正實現動態化的最佳方式,至少我是這麼認為的。
第三,外掛化技術只在中國有市場。國外的公司根本不看好這項技術,這可能是因為他們用GooglePlay,而谷歌官方不建議用外掛化這種方式。國外開發者不敢越雷池半步。
第四,四大元件都需要做外掛化嗎?根據我自己的經驗,做一款電商或旅遊類的App,有一兩百個Activity,Service用得很少,ContentProvider和BroadcastReceiver基本不用。所以,這種App實現Activity和Service的外掛化就夠了。像手機助手這樣的App,非常頻繁使用四大元件,所以四大元件都必須實現外掛化,這也是張勇當年在360開發出DroidPlugin支援四大元件的原因。
未來方向
最後講一下Android外掛化未來的方向。阿里一位技術專家馮森林曾說,外掛化最厲害的發展方向應該是每個Activity都是一個外掛。這個觀點在外掛化技術交流群裡一提出來之後,群裡所有人都沉默良久。仔細想想,外掛化的未來好像的確是這個發展方向,這樣就可以將任何一個出問題的Activity迅速替換。但當RN一經提出,這個觀點就慢慢消失了,RN比外掛化更輕量級,越來越多人選擇了RN。
其次,就是雙開技術。雙開技術是現在非常火的一項技術。如果想實現這種機制,一定要實現上面講的外掛化所涉及的內容。寧波一位高中生Lody,他從初三就開始研究這門技術,將很多不錯的雙開專案放在GitHub上。
第三,剛才講的所有資料都增量下載的機制,大家都可以實施一下,雖然做起來很麻煩,但是一旦實現,會讓你的App非常快。比如,你每次進入都需要重新整理城市列表嗎?大約幾百KB,即使你開gzip,重新整理速度仍然很慢,這時候增量更新就是一個很好的方式。
最後是內功的修煉。通讀一遍上面列出來的基礎知識,然後再去做App應用,你會清楚知道靜態廣播、動態廣播具體什麼時候用,什麼情況下可能出bug。AIDL可能會很少用,但真正做設計和實現的時候,這個基本功就非常重要了。所以,外掛化只是一門技術,你最應該關注的是其背後的本質,也就是內功修煉。
相關推薦
Android外掛化:從入門到放棄
本文根據包建強在2016GMTC全球移動開發大會上的演講整理而成。 首先自我介紹一下,我叫包建強,是這個分場的主持人。我去年寫了一本書,叫《App研發錄》,相信有很多從事技術的朋友看過或買過。 引言 先簡單介紹一下Android外掛化。很早之前已經有公司在研究這
【轉】Android外掛化:從入門到放棄
本文根據包建強在2016GMTC全球移動開發大會上的演講整理而成。 首先自我介紹一下,我叫包建強,是這個分場的主持人。我去年寫了一本書,叫《App研發錄》,相信有很多從事技術的朋友看過或買過。 引言 先簡單介紹一下Android外掛化。很早之前已經有公司在研究這項技
專訪包建強:為什麼我說Android外掛化從入門到放棄?
2016年6月24-25日,GMTC全球移動技術大會將在北京舉行,本屆大會,我們邀請了《App研發錄》的作者包建強老師,前來分享《Android外掛化:從入門到放棄》的內容。這個有趣的標題引起了大家的興趣,我們就來採訪一下包建強老師,看看他為什麼會取這個標題,以及對移動
包建強的培訓課程(10):Android外掛化從入門到精通
Android外掛化和熱修復 一.簡介 本課程結合講師多年來對Android外掛化技術的潛心研究,以及在千萬級使用者的App上長期實踐經驗,整理而成。本課程從四大元件的外掛化技術講起,中途會詳細剖析Android系統中與外掛化技術有關的底層概念,最後詳細介紹業界流行很廣的外
外掛化開發系列之三---Android外掛化從入門到放棄-最強合集
本人最近研究外掛化, 偶然發現此合集, 按照部分連結的文章實際簡單寫了些demo,受益良多, 覺得確實不錯,特轉載過來,給需要的人。 外掛化涉及的東西很多,所以我們需要多個維度去學習。大概分為5個部分:預備知識、入門、進階、系列、類庫。一步一步深入瞭解外掛的原理。 基礎1.Java 類載入器 類載入
(轉)Android開發書籍推薦:從入門到精通系列學習路線書籍介紹
成長 程序員 理論 targe base 官方 app als 自己的 Android開發書籍推薦:從入門到精通系列學習路線書籍介紹 轉自:http://blog.csdn.net/findsafety/article/details/52317506 很多時候我們都會
Android外掛化——Replugin入門(一)
一、360Replugin簡介 RePlugin是一套完整的、穩定的、適合全面使用的,佔坑類外掛化方案,由360手機衛士的RePlugin Team研發,也是業內首個提出”全面外掛化“(全面特性、全面相容、全面使用)的方案。 其主要優勢有: 極其靈活:主程式無需升級(無
【Android 熱修復與外掛化 一】帶你入門Android外掛化(附demo)
本文為博主Colin原創文章,歡迎轉載。 https://blog.csdn.net/colinandroid/article/details/79431502 一. 背景 Android外掛化作為每個合格的Android程式設計師都必須會的技術,被各大廠廣泛使用。隨著各大廠對
【 專欄 】- Android DataBinding詳解:從入門到深入
Android DataBinding詳解:從入門到深入 Android DataBinding(View Model繫結)技術詳解:從入門到深入。從簡單的Android DataBinding技術到複雜的雙向繫結,單向繫結和反向
Android外掛化的相容性(上):Android O的適配
首先宣告,《Android外掛化開發指南》這本書所介紹的Android底層是基於Android6.0(API level 23)的,而本書介紹的各種外掛化解決方案,以及配套的70多個例子,在Android7.0(API level 24)手機上測試都是能正常工作的。 如果讀者您的手機是
Android外掛化的相容性(中):Android P的適配
Android系統的每次版本升級,都會對原有程式碼進行重構,這就為外掛化帶來了麻煩。 Android P對外掛化的影響,主要體現在兩方面,一是它重構了H類中Activity相關的邏輯,另一個是它重構了Instrumentation。 3.1 H類的變身 3.1
Unix網路程式設計:從入門到放棄——一個簡單的時間獲取程式
我的Github個人部落格 ----------------------------------- 阮一峰的網路日誌 ----------------------------------- 劉未鵬 | Mind Hacks ---------------------------
Android-框架-Dagger2-Dagger2從入門到放棄再到恍然大悟
現在Dagger2在專案裡用的越來越多了,最近花了些時間學習了一下Dagger2,這篇文章主要幫助理解Dagger2的注入實現過程,如有錯誤,還請指正! 什麼是Dagger2 Dagger2是Dagger的升級版,是一個依賴注入框架,現在由Google接手維護。 恩
《Android 外掛化框架VirtualAPK :(一)基本整合》
一、VirtualAPK 介紹 VirtualAPK 是我們推出的一款Android平臺上的外掛化方案,通過VirtualAPK,可以讓APP無需重新發版即可上線新功能。 之所以做這件事,是因為傳統的開發流程中,APP進行版本迭代的時候,有著嚴格的時間週期的
[Android-ARCore開發]ARCore從入門到放棄2-Demo介紹和擴充套件
昨天只是簡單運行了官方的Demo,今天抽時間看了下文件和程式碼,大概瞭解一下原理。Demo功能很簡單,開啟之後自動檢測平面,手指觸控平面會在觸控位置放置一個機器人。檢測平面成功後如下面截圖所示,可以看到
動態規劃:從入門到放棄
Dynamic programming is a method for solving a complex pro
《Python編程:從入門到實踐》第10章 筆記
import 我沒 r+ 數據結構 中新 1.5 err 因此 重構 備註:以下按照Python 2的規則編寫代碼。 在jupyter notebook中運行直接顯示結果。 10 文件和異常 10.1 文件中讀取數據 10.1.1 讀取整個文件 """file_reade
Python編程:從入門到實踐——【作業】——第十一章(測試代碼)
stc 增加 收集 得到 width .com ast 接受 ted 第十一章 11-1 城市和國家 : 編寫一個函數, 它接受兩個形參: 一個城市名和一個國家名。 這個函數返回一個格式為City, Country 的字符串, 如Santiago, Chile 。 將這個函
《Python編程:從入門到實踐》【PDF】完整版免費下載
基礎知識 3.3 列表 else python 2 ccna 5.4 中文 開始 《Python編程:從入門到實踐》.pdf: pdf 完整版免費下載 https://u253469.ctfile.com/fs/253469-298090768 更多電子書下載:
Python編程:從入門到實踐——【作業】——第十四章(記分)
wid ont elif pac rom ext splay 添加 能夠 第十四章 14-1 按P開始新遊戲 : 鑒於遊戲《外星人入侵》 使用鍵盤來控制飛船, 最好讓玩家也能夠通過按鍵來開始遊戲。 請添加讓玩家在按P時開始遊戲的代碼。 也許這樣做會有所幫助: 將check_