Apk2Aar,關(guān)于如何用Apk轉(zhuǎn)Aar

探討apk轉(zhuǎn)aar的可行性

碎碎念

最近不忙了诡壁,閑下來就有時間去思考济瓢,如何讓打包更輕松(寫更少的腳本,做更少的事情)妹卿。因為工作的原因旺矾,日常不是在打包就是在修改打包腳本的路上榄檬。這邊想采用apk轉(zhuǎn)aar的主要原因是想直接通過AS來出包了遍坟,在我的猜想下,打包速度應(yīng)該會提升逾苫,并且不需處理目前使用apktool解包替換資源回編铺纽,遇到的各種問題扒吁。但是現(xiàn)實往往與想象差距甚遠,打包速度并沒有明顯的提升(哪怕少了解包的這個過程室囊,對比apktool的完成流程并沒有占據(jù)較大的優(yōu)勢)雕崩。而且轉(zhuǎn)aar本身也需要使用到apktool(畢竟有人維護,而且一直以來也是用他 )融撞。

前期查資料階段盼铁,先給出我覺得有用的資料

庫配置不正確

如果您的應(yīng)用依賴于使用舊版 Android SDK Build Tools 構(gòu)建的第三方庫,您的應(yīng)用可能會在運行時崩潰尝偎,且不會顯示任何錯誤或警告饶火。之所以會發(fā)生此崩潰鹏控,可能是因為在創(chuàng)建庫的過程中,將 R.java 字段聲明為 final肤寝,從而導(dǎo)致所有資源 ID 都被內(nèi)嵌在該庫的類中当辐。

AAPT2 依賴于在構(gòu)建應(yīng)用時能夠?qū)?ID 重新分配給庫資源。如果該庫將這些 ID 視為 final 并將其內(nèi)嵌在庫 dex 中鲤看,便會出現(xiàn)運行時不匹配的情況缘揪。

如需解決此錯誤,請與庫創(chuàng)建者聯(lián)系义桂,以使用最新版本的 Android SDK Build Tools 重新構(gòu)建該庫找筝,然后重新發(fā)布該庫。

從 res/ 讀取資源的唯一方法是使用資源 ID

保存在 assets/ 目錄中的文件沒有資源 ID慷吊,因此您無法通過 R 類或在 XML 資源中引用它們袖裕。您可以改為采用類似普通文件系統(tǒng)的方式查詢 assets/ 目錄中的文件,并利用 AssetManager 讀取原始數(shù)據(jù)溉瓶。

不過急鳄,如果您只需要讀取原始數(shù)據(jù)(例如視頻文件或音頻文件)的能力,則可將文件保存在 res/raw/ 目錄中堰酿,并利用 openRawResource() 讀取字節(jié)流攒岛。

結(jié)論

根據(jù)上面分析可知,如果我們通過修改apk胞锰,把dex里面視為 'final', 的代碼 修改為引用R.java文件灾锯,并把分散在不同路徑的R文件合并為一個(把不同的引用都指向同一個), 并生成R.txt 嗅榕, 那么Apk文件是可以轉(zhuǎn)化為AAR的
轉(zhuǎn)換為AAR的好處主要就是顺饮,可以直接通過AS出包(免去處理拆分dex,65536的煩惱凌那, 替換資源文件兼雄,以及理論上應(yīng)該能提升打包速度==》指二次打包,并且as能幫我們處理合并AndroidMainfests)
誠然帽蝶,如果cp能直接提供aar是最好的赦肋,但是很多時候拿到我們手里的都是apk,為此以往都是采用apk二次打包励稳,運用apktool解包佃乘,大部分都是通過python腳本來修改文件。

與 JAR 文件不同驹尼,AAR 文件會為 Android 應(yīng)用提供以下功能:
  • AAR 文件可以包含多項 Android 資源和一個清單文件趣避,讓您除了能夠在 Java 類和方法中進行捆綁以外,還能夠在布局和可繪制對象等共享資源中進行捆綁新翎。
  • AAR 文件可以包含 C/C++ 庫程帕,供應(yīng)用模塊的 C/C++ 代碼使用住练。
庫模塊開發(fā)注意事項

在開發(fā)庫模塊和相關(guān)應(yīng)用時,請注意以下行為和限制愁拭。

向 Android 應(yīng)用模塊添加對庫模塊的引用后讲逛,您可以設(shè)置它們的相對優(yōu)先級。在構(gòu)建時岭埠,庫會按照優(yōu)先級由低到高的順序逐一與應(yīng)用合并盏混。

  • 資源合并沖突

    構(gòu)建工具會將庫模塊中的資源與相關(guān)應(yīng)用模塊的資源合并。如果這兩個模塊中都定義了給定的資源 ID枫攀,系統(tǒng)會使用應(yīng)用中的資源括饶。

    如果多個 AAR 庫之間發(fā)生沖突株茶,系統(tǒng)會使用依賴項列表中首先列出的庫(靠近 dependencies 塊頂部)中的資源来涨。

    為了避免常用的資源 ID 發(fā)生資源沖突,請考慮使用對模塊具有唯一性(或在所有項目模塊之間具有唯一性)的前綴或其他一致的命名方案启盛。

  • 在多模塊構(gòu)建中蹦掐,系統(tǒng)會將 JAR 依賴項視為傳遞依賴項

    在向輸出 AAR 的庫項目添加 JAR 依賴項時,JAR 會由庫模塊進行處理僵闯,并與其 AAR 打包在一起卧抗。

    不過,如果您的項目包含庫模塊鳖粟,并且此模塊已被應(yīng)用模塊使用社裆,應(yīng)用模塊便會將庫的本地 JAR 依賴項視為傳遞依賴項。在這種情況下向图,本地 JAR 將由使用它的應(yīng)用模塊進行處理泳秀,而不是由庫模塊進行處理。這是為了加快庫代碼更改導(dǎo)致的增量構(gòu)建的速度榄攀。

    由本地 JAR 依賴項導(dǎo)致的所有 Java 資源沖突都必須在使用相應(yīng)庫的應(yīng)用模塊中解決嗜傅。

  • 庫模塊可以依賴于外部 JAR 庫

    您可以開發(fā)一個依賴于外部庫(例如 Google 地圖外部庫)的庫模塊。在這種情況下檩赢,相關(guān)應(yīng)用必須針對包含此外部庫的目標(例如 Google API 插件)進行構(gòu)建吕嘀。另外也要注意,庫模塊和相關(guān)應(yīng)用都必須在其清單文件的 <uses-library> 元素中聲明外部庫贞瞒。

  • 應(yīng)用模塊的 minSdkVersion 必須等于或大于庫定義的版本

    庫是作為相關(guān)應(yīng)用模塊的一部分進行編譯的偶房,因此,庫模塊中使用的 API 必須與應(yīng)用模塊支持的平臺版本兼容军浆。

  • 每個庫模塊都會創(chuàng)建自己的 R 類

    在您構(gòu)建相關(guān)應(yīng)用模塊時蝴悉,庫模塊會先編譯到 AAR 文件中,然后再添加到應(yīng)用模塊中瘾敢。因此拍冠,每個庫都有自己的 R 類尿这,并根據(jù)庫的軟件包名稱命名。所需的所有軟件包中都會創(chuàng)建從主模塊和庫模塊生成的 R 類庆杜,包括主模塊的軟件包和庫的軟件包射众。

  • 庫模塊可以包含自己的 ProGuard 配置文件

    如果有用于構(gòu)建和發(fā)布 AAR 的庫項目晃财,您可以向庫的構(gòu)建配置添加 ProGuard 配置文件叨橱,并且 Android Gradle 插件規(guī)則適用于您指定的 ProGuard 規(guī)則。構(gòu)建工具會將此文件嵌入到為庫模塊生成的 AAR 文件中断盛。在您將庫添加到應(yīng)用模塊后罗洗,庫的 ProGuard 文件會附加到應(yīng)用模塊的 ProGuard 配置文件 (proguard.txt)。

    通過將 ProGuard 文件嵌入到庫模塊中钢猛,您可以確保依賴于相應(yīng)庫的應(yīng)用模塊不必手動更新其 ProGuard 文件即可使用此庫伙菜。當 Android Studio 構(gòu)建系統(tǒng)構(gòu)建您的應(yīng)用時,它會同時使用來自應(yīng)用模塊和庫的指令命迈。因此無需按照單獨的步驟在庫上運行代碼縮減器贩绕。

    如需向庫項目添加 ProGuard 規(guī)則,您必須使用 consumerProguardFiles 屬性(位于庫的 build.gradle 文件的 defaultConfig 塊內(nèi))指定文件名稱壶愤。例如淑倾,以下代碼段會將 lib-proguard-rules.txt 設(shè)為庫的 ProGuard 配置文件:

    不過,如果庫模塊是要編譯到 APK 中的多模塊構(gòu)建的一部分征椒,并且不會生成 AAR娇哆,您應(yīng)該只在使用相應(yīng)庫的應(yīng)用模塊上運行代碼縮減。如需詳細了解 ProGuard 規(guī)則及其用法勃救,請參閱縮減碍讨、混淆處理和優(yōu)化應(yīng)用

  • 測試庫模塊的方法與測試應(yīng)用的方法相同

    主要區(qū)別在于剪芥,庫及其依賴項會作為測試 APK 的依賴項自動包含在內(nèi)垄开。這意味著測試 APK 不僅包含自己的代碼,還包含庫的 AAR 及其所有依賴項税肪。由于沒有單獨的“被測應(yīng)用”溉躲,因此 androidTest 任務(wù)只會安裝(和卸載)測試 APK。

    合并多個清單文件時益兄,Gradle 會遵循默認的優(yōu)先級順序锻梳,并將庫的清單合并到測試 APK 的主清單中。

AAR 文件詳解

AAR 文件的文件擴展名為 .aar净捅,Maven 工件類型應(yīng)該也是 aar疑枯。此文件本身是一個 zip 文件。唯一的必需條目是 /AndroidManifest.xml蛔六。

此外荆永,AAR 文件可能包含以下一個或多個可選條目:

  • /classes.jar
  • /res/
  • /R.txt
  • /public.txt
  • /assets/
  • /libs/name.jar
  • /jni//abi_name/name.so(其中abi_name是 Android 支持的 ABI 之一)
  • /proguard.txt
  • /lint.jar
  • /api.jar
  • /prefab/(用于導(dǎo)出原生庫

開始

在查閱了大量資料废亭,并思考后,我得出了apk可以轉(zhuǎn)換成aar的結(jié)論.并手動通過apk生成了一個aar然后導(dǎo)入到工程里面具钥,并成功運行后豆村,開始著手編碼的過程。

首先骂删,隨便搞個apk和aar然后進行對比(同一個工程的同一個model)


aar.png
apk.png

大部分文件都認識掌动,除了R.txt ,于是雙擊

R.txt.png

這看起來有點類似public.xml的文件,那就根據(jù)public.xml來生成R.txt吧宁玫,然后用Sublime來用public.xml生成R.txt粗恢,然后悲催的發(fā)現(xiàn)行數(shù)對不上,對比發(fā)現(xiàn)少了styleable (之前修正ApkIdTool填坑也是這個老朋友)
image.png

事已至此欧瘪,不能簡單的由public.xml生成R.txt眷射,所以我不由得開始琢磨起這R文件是用來干嘛的了。

官方關(guān)于aar的說明

官方文檔關(guān)于aar上明確說明aar文件本身是一個 zip 文件恋追。唯一的必需條目是 /AndroidManifest.xml凭迹。
那就直接刪掉aar的R.txt然后直接運行項目罚屋,結(jié)果就是程序崩毀日志顯示找不到對應(yīng)的R文件苦囱,那么這個R文件應(yīng)該是用來生成R.java的吧

畫重點

在查閱了大量資料與實踐之后得出R.txt 是決定在aar的包名下生成R文件的內(nèi)容, 所以有無R.txt將決定是否在aar文件的AndroidMainFest.xml的packageName下的路徑下創(chuàng)建R.java

那么脾猛?撕彤!嗯?

可能有的小伙伴已經(jīng)想到了我要干嘛了猛拴。apk文件本身就包含了常量化的資源id羹铅,如果我按照as生成的aar的方式生成aar,那我就需要把常量化的資源id改成動態(tài)引用包名下的R文件的對應(yīng)id愉昆,并生成R.txt职员。然后我還需要把用來固定資源id的apk解包后生成的public.xml文件給刪除掉。單單就對資源id由final改成動態(tài)引用跛溉,我就要做這么多操作!

既然apk已經(jīng)分配了id而且也有了固定資源id的public.xml焊切,那么我能不能直接就用這些常量化的id呢?于是芳室,我又手動合成了一個aar专肪,運行沒有任何問題。

其實理論上也是不存在任何問題的堪侯,因為最后都是調(diào)用aapt2來生成資源id嚎尤,當項目引用aar的時候,res里面包含public.xml伍宦,那也就是提前固定了對應(yīng)的資源id而已芽死,當不存在public.xml的資源也就不存在固定乏梁,也就重新生成資源id。并沒有任何問題关贵。(在寫游戲sdk方面掌呜,一般都不使用R.id的方式來獲取資源id。很大一部分原因就是為了規(guī)避資源id重新分配坪哄,導(dǎo)致的id錯亂問題质蕉。關(guān)于為什么使用動態(tài)方式獲取id就不會有這個問題,可以參考抖音的分享翩肌,文中稱為資源文件反射我更愿意稱動態(tài)獲取資源id

有了上述的理論支持模暗,那么由apk2aar可以簡化成如下圖所示

apk2aar.png

1.關(guān)于AndroiManifest.xml的修改,可以參考合并aar念祭,主要按照as生成 aar的AndroidManifest.xml的形式去修改
2.關(guān)于unknown文件兑宇,我之所以這么做是基于引入了okhttp后,apk解包后會在unknown下有publicsuffixes.gz粱坤,而我這么做也是根據(jù)引用okhttp后生成的aar來的(用fat-aar隶糕,為我節(jié)省了思考的時間,感謝)
3.用dex2jar提取jar站玄,并刪除需要替換的類(因為需要更新這部分代碼)枚驻,資源不用做處理,因為如果多個 AAR 庫之間發(fā)生沖突株旷,系統(tǒng)會使用依賴項列表中首先列出的庫(靠近 dependencies 塊頂部)中的資源再登。

所以我又寫了代碼,整合到了tool里面,使用請參考晾剖。因為代碼還很粗糙锉矢,按照最開始的設(shè)想轉(zhuǎn)aar只需運行一次所以并沒有過多考慮性能。并且由于使用aar用as出包并沒有速度上的優(yōu)勢齿尽,已經(jīng)失去了繼續(xù)的動力(按照最開始的想法沽损,因為轉(zhuǎn)aar一次性的耗費的時間先忽略,那么打包因為沒了apktool的解包回編循头,理論上只有編譯apk這步绵估,速度應(yīng)該明顯提升。但是事與愿違贷岸,實測并沒有優(yōu)勢)壹士,所以,也就沒必要優(yōu)化偿警,而且由于躏救,缺少大量樣本,可能存在,我認知外的情況盒使。
希望能起到拋磚引玉的作用崩掘,共勉。

ps:
補充說明:AS的aar之所以不用固定id是因為多個aar的話可能有沖突少办,我目前的使用因為我能確保只有一個aar是用固定id的所以不會出現(xiàn)問題

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苞慢,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子英妓,更是在濱河造成了極大的恐慌挽放,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,378評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蔓纠,死亡現(xiàn)場離奇詭異辑畦,居然都是意外死亡,警方通過查閱死者的電腦和手機腿倚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,356評論 2 382
  • 文/潘曉璐 我一進店門纯出,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人敷燎,你說我怎么就攤上這事暂筝。” “怎么了硬贯?”我有些...
    開封第一講書人閱讀 152,702評論 0 342
  • 文/不壞的土叔 我叫張陵焕襟,是天一觀的道長。 經(jīng)常有香客問我澄成,道長胧洒,這世上最難降的妖魔是什么畏吓? 我笑而不...
    開封第一講書人閱讀 55,259評論 1 279
  • 正文 為了忘掉前任墨状,我火速辦了婚禮,結(jié)果婚禮上菲饼,老公的妹妹穿的比我還像新娘肾砂。我一直安慰自己,他們只是感情好宏悦,可當我...
    茶點故事閱讀 64,263評論 5 371
  • 文/花漫 我一把揭開白布镐确。 她就那樣靜靜地躺著,像睡著了一般饼煞。 火紅的嫁衣襯著肌膚如雪源葫。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,036評論 1 285
  • 那天砖瞧,我揣著相機與錄音息堂,去河邊找鬼。 笑死,一個胖子當著我的面吹牛荣堰,可吹牛的內(nèi)容都是我干的床未。 我是一名探鬼主播,決...
    沈念sama閱讀 38,349評論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼振坚,長吁一口氣:“原來是場噩夢啊……” “哼薇搁!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起渡八,我...
    開封第一講書人閱讀 36,979評論 0 259
  • 序言:老撾萬榮一對情侶失蹤啃洋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后屎鳍,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體裂允,經(jīng)...
    沈念sama閱讀 43,469評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,938評論 2 323
  • 正文 我和宋清朗相戀三年哥艇,在試婚紗的時候發(fā)現(xiàn)自己被綠了绝编。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,059評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡貌踏,死狀恐怖十饥,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情祖乳,我是刑警寧澤逗堵,帶...
    沈念sama閱讀 33,703評論 4 323
  • 正文 年R本政府宣布,位于F島的核電站眷昆,受9級特大地震影響蜒秤,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜亚斋,卻給世界環(huán)境...
    茶點故事閱讀 39,257評論 3 307
  • 文/蒙蒙 一作媚、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧帅刊,春花似錦纸泡、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,262評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至栏饮,卻和暖如春吧兔,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背袍嬉。 一陣腳步聲響...
    開封第一講書人閱讀 31,485評論 1 262
  • 我被黑心中介騙來泰國打工境蔼, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 45,501評論 2 354
  • 正文 我出身青樓欧穴,卻偏偏與公主長得像民逼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子涮帘,可洞房花燭夜當晚...
    茶點故事閱讀 42,792評論 2 345

推薦閱讀更多精彩內(nèi)容