Deprecated
本文已過時趾浅,最新文章:向大家推薦《使用 AS 開發(fā) System App》 https://xiaozhuanlan.com/system-app
0、前言:
Android原生系統(tǒng)帶有許多原生的App讹开,比如瀏覽器磨总、錄音機(jī)、計(jì)算器、設(shè)置
等,有些時候础芍,我們需要用到一些系統(tǒng)的功能,或者是對已有的功能做二次開發(fā)数尿,比如我上學(xué)時給一個公司做過一個Launcher和Wizard,就需要用到系統(tǒng)設(shè)置中的某些功能惶楼,比如Wifi右蹦、聲音、顯示等功能歼捐,于是就需要從Settings源碼中提取出需要的功能何陆。
特別是公司自己定制Android系統(tǒng),需要在上面做一些系統(tǒng)級的App
的時候豹储,原生App已有的功能就可以通過編譯其源碼的方式直接拿過來改改就能用贷盲,而且可用度很高。
以下內(nèi)容就以Settings為例剥扣,主要介紹如何編譯和運(yùn)行調(diào)試Settings源碼巩剖。
1、源碼:
這里有兩種情況钠怯,分為原生
的和公司定制
的系統(tǒng)佳魔。無論是原生的還是定制的,類似于Settings這樣需要使用到系統(tǒng)級或隱藏API
的App晦炊,都需要系統(tǒng)簽名文件和編譯系統(tǒng)源碼后得到相應(yīng)的jar包才可以在IDE中編譯鞠鲜,因?yàn)闃?biāo)準(zhǔn)SDK根本沒有那些API可供調(diào)用宁脊。
舉個栗子:
鬧鐘、計(jì)算器這類的不需要額外的Jar包贤姆,得到源碼后導(dǎo)入IDE就可以運(yùn)行的榆苞。由于包名沖突,想調(diào)試要么刪掉系統(tǒng)App霞捡,要么修改包名坐漏。
Settings、Launcher之類的就需要系統(tǒng)級的Jar包弄砍,SDK沒有提供相應(yīng)API仙畦。這類的想調(diào)試就必須刪掉同包名的系統(tǒng)App了,修改包名會有意想不到的亂七八糟的問題出現(xiàn)音婶。
(1)原生App:
網(wǎng)址:https://android.googlesource.com/
位置:platform/packages/apps/慨畸,可Ctrl+F搜索一下。點(diǎn)擊想要編譯的App衣式,比如Settings寸士。
使用Git克隆下來:比如 git clone https://android.googlesource.com/platform/packages/apps/Settings
需要額外的Jar就需要自己編譯系統(tǒng)源碼啦,這個是比較麻煩的碴卧,有興趣可以試試自己編譯定制自己的Android系統(tǒng)弱卡。
(2)定制:
跟公司的底層工程師要代碼。
首先是“out/target/common/obj/JAVA_LIBRARIES/”文件夾住册,讓底層人員整個文件夾壓縮了給到你婶博,雖然比較大(大概1G),但這是必須的荧飞,底層人員可能會說:你要什么再跟我說凡人,扯淡,不要聽他的叹阔,你就要全部挠轴。
再來是要Settings的源碼。
** 注意耳幢,既然是定制的岸晦,源碼、jar睛藻、簽名文件启上,還有系統(tǒng)都是一一對應(yīng)的,你不能拿其他公司的系統(tǒng)簽名來給你公司的系統(tǒng)app簽名店印,這樣無法運(yùn)行的碧绞。 **
2、編譯:
有了源碼吱窝,下一步當(dāng)然是要跑起來啦讥邻。
建議都使用Eclipse來編譯迫靖,不要使用AS,因?yàn)锳S編譯大型的原生App能卡到你吐血兴使,而且出錯提示也不友好系宜。但是用過AS的人都不想再碰Eclipse了有沒有?发魄?別急盹牧,可以先用Eclipse編譯過了,再貼到AS中励幼,這樣好很多汰寓,也很節(jié)省時間。
步驟:
初始化:
新建工程苹粟,Compile With 選最大有滑,Target和Min都選和你使用的系統(tǒng)一致,包名和原生app的包名一致嵌削,比如Settings的是com.android.settings毛好。
新建成功后,添加libs文件夾苛秕,刪掉AndroidManifest.xml肌访,清空res。使用Git初始化項(xiàng)目艇劫,添加ignore文件吼驶,提交init,方便出錯時回退店煞。
放入源碼:
拷貝Settings源碼的AndroidManifest.xml旨剥、src、res到工程浅缸,選擇Project -> Clean清理一下,在Console會得到很多錯誤魄咕。
git commit 提交一下衩椒,還是那句話,出錯方便回退哮兰。
修正res錯誤:
首先是res下的錯誤毛萌,可能每個語言的strings.xml文件都會報(bào)錯,建議刪掉其他不需要的語言喝滞,可以根據(jù)Console的報(bào)錯信息阁将,寫個小程序批量刪除,留下需要的右遭,并修正錯誤即可做盅。比如原生的代碼可能會有string重復(fù)缤削,去掉即可。我只留下了value和value-zh-rCN的strings.xml吹榴,因?yàn)槠渌Z言的用不到亭敢。
-
若是缺少Drawable文件,比如圖片图筹,有以下方式可以找回來:
* Google搜索文件名帅刀,不要使用百度,百度搜不出來远剩。
* 去SDK文件夾下全局搜索扣溺。
不要怕修改,以解決問題為優(yōu)先瓜晤。比如我編譯后發(fā)現(xiàn)缺少了@*android:drawable/XXX文件锥余,在SDK文件夾搜索后找到該文件,放到了res/drawable文件夾后活鹰,將其引用修改為@drawable/XXX即可哈恰。畢竟只是個資源文件而已。
如果是缺少style志群,可以把style的名稱貼到Google中着绷,一般都能得到正確的結(jié)果。
總之就是根據(jù)提示一直解決到res沒有提示錯誤為止锌云。解決完畢荠医,git commit。
修正src錯誤:
-
再來是src的錯誤桑涎,首先是必須導(dǎo)入的jar包彬向,解壓底層工程師給你的JAVA_LIBRARIES文件夾,里面有很多的子文件夾攻冷。
第一個包:
文件夾:framework_intermediates
第二個包:
文件夾:core_intermediates/core-libart_intermediates(也許是其他的名字)
第三個包:
文件夾:android-common_intermediates將以上文件夾中的classes.jar娃胆,為了好區(qū)分重命名為framework-classes.jar、core-classes.jar等曼、common-classes.jar里烦。放到一個方便查找的文件夾中,這三個jar包將作為User Library引用禁谦。不能作為常規(guī)的jar使用胁黑。如何引用請Google傅联。
需要注意的是:
引用后薄风,在Java Build Path/Order and Export中蝙泼,framework需排在第一耿币、core第二狈茉、common第三捅僵。然后再Clean一下慷妙,看看src還有什么錯誤眷昆,比方說com.android.setupwizard.Test類沒有找到,就去JAVA_LIBRARIES文件夾搜索Test冗懦,再定位到其目錄下爽冕,找到其classes.jar文件,重命名后放入libs中即可披蕉。其他的錯誤也是如此颈畸。
有個比較特殊的類EventLogTags,在文件夾中根本沒有找到想要的没讲,其使用的都是一些靜態(tài)變量眯娱。于是就直接在網(wǎng)上搜索靜態(tài)變量的名稱,比如EventLogTags.LOCK_SCREEN_TYPE爬凑,直接使用其值徙缴,雖然對不對,但是沒有辦法也只能先這樣了嘁信。
-
同理于样,也是一直解決到Clean后src沒有錯誤為止,再git commit潘靖。
建議不勾選: Window -> Preference -> Android -> Lint error Checking 的Run full error check .... 這樣有些warning和不影響運(yùn)行的Lint error就不會提示穿剖,反正沒事,眼不見心不煩卦溢。
3糊余、嘗試運(yùn)行:
編譯通過了,試著直接debug跑一下单寂,在安裝進(jìn)設(shè)備的時候贬芥,就會有以下錯誤:
報(bào)錯:
Unable to execute dex: Multiple dex files define Landroid/support/annotation/AnimRes;
Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Landroid/support/annotation/AnimRes;
這是因?yàn)锳nnotation曾經(jīng)是作為一個單獨(dú)的庫存在的,但是由于某些原因宣决,在最新的v4中蘸劈,已經(jīng)包含了Annotation了,所以尊沸,就不需要Annotation的包了威沫,如果你沒有導(dǎo)入Annotation的包,就說明你導(dǎo)入了SDK椒丧,通過Java Build Path/Libraries,Remove掉就可以了救巷。比如我使用的是Android N壶熏,就Remove掉AndroidN。
如果發(fā)現(xiàn)還有這個問題浦译,那就是v4和v13的包沖突了棒假,v13的包是包含v4的溯职,把v4的包去掉就可以了。-
Installation error: INSTALL_FAILED_VERSION_DOWNGRADE:
因?yàn)橄到y(tǒng)中已經(jīng)存在了Settings了帽哑,所以無法安裝谜酒。可以取得Root權(quán)限妻枕,刪掉/system/app/Settings/Settings.apk文件僻族,刪除前記得保存一下,萬一出錯可以恢復(fù)屡谐。或者述么,通過右鍵選擇 Android Tools -> Rename Application Package,重命名Package愕掏,如果你的項(xiàng)目是GBK編碼的度秘,重命名可能會失敗,可以通過右鍵選擇Properties -> Resource -> 選擇UTF-8即可重命名成功饵撑。此方法需慎重使用剑梳,不一定全部app都適用,如果沒有用到特殊的API就完全沒問題滑潘。因?yàn)橄馭ettings這樣的重命名后會有很多奇奇怪怪的問題垢乙。 如果要刪除Settings.apk,提示:override rw-r--r-- root:root for 'Settings.apk'?众羡,可以使用-rf: rm -rf Settings.apk 提示:rm: Settings.apk: Read-only file system的話侨赡,可以: mount -o rw,remount /system 重新掛載/system目錄,然后就可以刪除了粱侣,這里涉及到的跟Linux的文件權(quán)限系統(tǒng)有關(guān)羊壹,這里不再擴(kuò)展。 其實(shí)有個軟件可以操作齐婴,如果你的設(shè)備已經(jīng)Root油猫,那么可以下載X-plore這個app,打開設(shè)置柠偶,選擇Root權(quán)限訪問情妖,選擇超級用戶+掛載可寫,即可輕松刪除系統(tǒng)app诱担,不過在刪除之前毡证,建議備份。
Installation error: INSTALL_PARSE_FAILED_MANIFEST_MALFORMED:
AndroidMenifest.xml錯誤蔫仙,據(jù)說可能是包名有大寫字母料睛,反正我沒有。在網(wǎng)上查了一番,有人說是恤煞,把Activity之類的注冊寫上全名即可屎勘。但是我也沒有這樣的情況,后來找到有人說android:taskAffinity的問題居扒,這個是啥自己搜索概漱,我發(fā)現(xiàn)有些是"",有些是com.android.settings喜喂,我全更改了瓤摧,可還是有這個錯誤。搞來搞去夜惭,原來是我重命名包名了姻灶,才會有這些問題,就把包名改回去了诈茧,刪掉相應(yīng)系統(tǒng)App后产喉,這個問題就解決了。彈出Toast有問題敢会,我在SettingsActivity中使用Toast是有問題的曾沈,報(bào)xml解析錯誤。也不知道咋回事鸥昏,沒有深入探索塞俱。
Installation error: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE:
原因:apk的AndroidManifest.xml中聲明了android:sharedUserId="android.uid.system",但沒有相應(yīng)的系統(tǒng)簽名吏垮。別急障涯,接下來就說明如何簽名的問題。
4膳汪、調(diào)試
使用到系統(tǒng)級API的唯蝶,或者AndroidManifest.xml文件中聲明了
android:sharedUserId="android.uid.system"
那么沒有系統(tǒng)簽名,直接debug簽名運(yùn)行是不行的遗嗽,需要向底層工程師要系統(tǒng)的簽名文件粘我,在源碼目錄
build\target\product\security
下的platform.pk8
和platform.x509.pem
,如果你想看此次編譯Settings是否已成功了痹换,可以適當(dāng)?shù)脑谌肟诩右幌翷og征字,然后導(dǎo)出未簽名的apk,使用系統(tǒng)簽名進(jìn)行簽名后娇豫,放到/system/app/
下替換掉Settings.apk匙姜,然后重啟系統(tǒng),打開設(shè)置冯痢,看看Logcat是否輸出里加入的Log氮昧。
系統(tǒng)簽名轉(zhuǎn)換成debug簽名進(jìn)行調(diào)試:
在不知道系統(tǒng)簽名可以轉(zhuǎn)換成debug簽名前或详,老實(shí)說我一直都是用Log的方式調(diào)試,太特么痛苦了」疲現(xiàn)在知道后整個人都懵逼了。
我們都希望可以像調(diào)試普通app那樣調(diào)試系統(tǒng)app椒振,以下是如何通過openssl
將platform.pk8
和platform.x509.pem
轉(zhuǎn)換成debug.keystore
文件:
三個命令
得到platform.priv.pem
openssl pkcs8 -in platform.pk8 -inform DER -outform PEM -out platform.priv.pem -nocrypt-
得到platform.pk12
openssl pkcs12 -export -in platform.x509.pem -inkey platform.priv.pem -out platform.pk12 -name androiddebugkey此過程提示輸入密碼昭伸,輸入android
生成debug.keystore
keytool -importkeystore -deststorepass android -destkeypass android -destkeystore debug.keystore -srckeystore platform.pk12 -srcstoretype PKCS12 -srcstorepass android -alias androiddebugkey
此方法來自:http://curlog.com/2016/08/30/android-pk2debug-keystore/
Mac自帶openssl,Linux和Win需要安裝澎迎。
然后就可以使用得到的debug簽名配置到eclipse后愉快的調(diào)試?yán)猜睿?dāng)然,得先把系統(tǒng)中已經(jīng)存在的app先刪除掉夹供。然后重啟系統(tǒng)灵份,至于如何配置eclipse的debug簽名,請Google哮洽。
5填渠、結(jié)語:
使用過AS后,當(dāng)然希望在AS中也可以調(diào)試系統(tǒng)App鸟辅,抽空再寫篇相關(guān)編譯和調(diào)試的文章氛什。如果這篇文章幫到你了,給個贊唄匪凉。