maven(android-maven-plugin3.8.0)打包apk无法启动,apklib依赖包的资源索引出错(R文件与主模块冲突)问题解析
近期在用maven,遇到了一個(gè)問題,用maven打出的apk有問題無法啟動(dòng),但是用idea打包的就是正常的。
日志中顯示的問題是,一個(gè)apklib形式的依賴包中的一個(gè)資源出現(xiàn)了問題。反編譯對(duì)比maven包和idea包,找到了問題所在。
假設(shè): 主模塊包名為com.android.main
? ? ? ? ? ? apklib依賴包包名為com.android.apklib
? ? ? ? ? ??出問題的資源(layout)名為MyView
問題: apk打包后apklib依賴包的資源文件會(huì)與主模塊的資源整合到一起,依賴包引用資源實(shí)際上是在主模塊的R文件中查找對(duì)應(yīng)資源。
1)maven包中: 在com.android.main下的R文件中MyView的值為0x7f050001;而在com.android.apklib下的R文件中MyView的值為0x7f070001,而且程序內(nèi)使用該資源時(shí)的索引也是0x7f070001。這樣程序運(yùn)行到這段代碼時(shí),會(huì)去主模塊的R文件中找0x7f070001,然而主模塊中0x7f070001對(duì)應(yīng)的資源并不是一個(gè)layout,所以就會(huì)出錯(cuò)。
2)idea包中:倆個(gè)R文件中MyView的值相同,所以能夠正確的找到資源,程序不會(huì)出錯(cuò)。
這樣就知道了問題,但是問題是如何出現(xiàn)的?
經(jīng)過對(duì)maven打印日志查看,整理了一個(gè)打包的過程如下:
1)將所有依賴包拷貝到項(xiàng)目 /target/unpacked-libs 下,整合資源文件,然后生成主模塊和各依賴包的R.java等文件
2)編譯class文件,包括剛才生成的對(duì)應(yīng)包的R文件。注意:編譯com.android.apklib下的java文件時(shí),代碼中對(duì)應(yīng)資源的索引與(1)生成的com.android.apklib包下的R文件一致
3)生成dex
4)生成apk
(maven打包可以用"mvn clean package"即可。不過也可以像上面那樣細(xì)分成四步"mvn clean android:generate-sources compile android:dex android:apk")
這樣我們就注意到,雖然運(yùn)行時(shí)依賴包會(huì)在主模塊R文件中查找資源,但是編譯時(shí)還是會(huì)根據(jù)自己包下的R文件來編譯。
用maven只處理資源(mvn clean android:generate-sources),以便查看生成的R.java文件,發(fā)現(xiàn)問題產(chǎn)生的原因:
生成的R.java文件,主模塊與依賴包是有沖突的,同一個(gè)資源對(duì)應(yīng)不同的索引。這樣編譯的時(shí)候依賴包代碼中的資源索引就是有問題的,就會(huì)導(dǎo)致問題的出現(xiàn)。那么說明maven在生成R.java文件時(shí)是有問題的。
繼續(xù)查看maven打印日志,找到了生成R,java文件對(duì)應(yīng)的日志部分,是執(zhí)行了aapt的命令。如下:
aapt.exe package -f --no-crunch -I D:\AndroidSDK\sdk\platforms\android-16\android.jar -M D:\項(xiàng)目目錄\AndroidManifest.xml -S D:\項(xiàng)目目錄\res -S D:\項(xiàng)目目錄\target\unpacked-libs/依賴包名/res -A D:\項(xiàng)目目錄\target\generated-sources\combined-assets\assets -m -J D:\項(xiàng)目目錄\target\generated-sources\r --output-text-symbols D:\項(xiàng)目目錄\target --auto-add-overlay aapt.exe package --non-constant-id -m -J D:\項(xiàng)目目錄\target\generated-sources\r --custom-package 主模塊包名 -M D:\項(xiàng)目目錄\target\unpacked-libs\依賴包名\AndroidManifest.xml -S D:\項(xiàng)目目錄\target\unpacked-libs\依賴包名\res --auto-add-overlay -A D:\項(xiàng)目目錄\target\unpacked-libs\依賴包名\combined-assets -I D:\AndroidSDK\sdk\platforms\android-16\android.jar;?
?
第一個(gè)命令就是生成主模塊R文件的,第二個(gè)命令則生成依賴包R文件。
(這里簡(jiǎn)單介紹一下命令的主要組成:“-m -J D:\項(xiàng)目目錄\target\generated-sources\r”是R.java文件生成的路徑;“-M D:\項(xiàng)目目錄\AndroidManifest.xml”是獲取包名;“-A D:\項(xiàng)目目錄\target\generated-sources\combined-assets\assets”是assets目錄;“-S D:\項(xiàng)目目錄\res”是res目錄,有依賴包的話有多個(gè),并注意順序;“--non-constant-id”生成的R.java文件中字段不是final類型;“--auto-add-overlay”資源文件自動(dòng)覆蓋)
查看發(fā)現(xiàn)主模塊的R文件一切正常,那么就是第二條命令出的問題。由于自己之前沒有研究過打包,對(duì)aapt命令很不熟悉,所以一時(shí)也不知道該怎么修改。經(jīng)過在網(wǎng)上查找,慢慢熟悉這條命令每部分的作用。第二條命令僅僅是生成依賴包的R文件,并未與主模塊進(jìn)行關(guān)聯(lián),這樣其實(shí)是單獨(dú)生成的,所以會(huì)起沖突。修改很簡(jiǎn)單,如下:
aapt.exe package --non-constant-id -m -J D:\項(xiàng)目目錄\target\generated-sources\r --custom-package 主模塊包名 -M D:\項(xiàng)目目錄\target\unpacked-libs\依賴包名\AndroidManifest.xml -S D:\項(xiàng)目目錄\res -S D:\項(xiàng)目目錄\target\unpacked-libs\依賴包名\res --auto-add-overlay -A D:\項(xiàng)目目錄\target\unpacked-libs\依賴包名\combined-assets -I D:\AndroidSDK\sdk\platforms\android-16\android.jar;?
?
多加了主模塊的res進(jìn)去,這樣其實(shí)生成的依賴包R文件與主模塊的是一摸一樣的,里面包含了所有資源,并不僅僅是依賴包的資源。這樣再編譯就不會(huì)有沖突的現(xiàn)象。
但是這僅僅是在命令層面解決問題,maven打包使用的是android-maven-plugin(com.jayway.maven.plugins.android.generation2),上面的命令都是由這個(gè)插件來執(zhí)行的。不過還好這個(gè)插件是開源的,在github上可以找到。在github上找到這個(gè)開源項(xiàng)目,找到對(duì)應(yīng)部分的代碼后發(fā)現(xiàn)構(gòu)建的命令是正確的,原來已經(jīng)有高手在5月中旬解決這個(gè)問題了。。。
原來是我的插件版本落后了,去中心倉庫查看發(fā)現(xiàn)android-maven-plugin最新版本是3.9.0-rc.3,這個(gè)版本已經(jīng)解決該bug了。更新一下打包測(cè)試,一切正常。
雖然最后只是更新一下版本就解決了,但是也學(xué)到了不少東西,熟悉了打包流程,另外有興趣的話可以看看github上對(duì)應(yīng)部分的代碼,
?
超強(qiáng)干貨來襲 云風(fēng)專訪:近40年碼齡,通宵達(dá)旦的技術(shù)人生總結(jié)
以上是生活随笔為你收集整理的maven(android-maven-plugin3.8.0)打包apk无法启动,apklib依赖包的资源索引出错(R文件与主模块冲突)问题解析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android Lint 去除重复资源
- 下一篇: eclipse开发cocos2dx 3.