Writing Custom Lint Rules(半讀半就版)

官網(wǎng)原址

本文只是個人為了整理Lint相關(guān)知識滚婉,依據(jù)谷歌翻譯整理而成图筹,水平確實不堪,很多地方自己都讀不太懂让腹,見諒...

新的2015年8月27日:現(xiàn)在有一個最新的示例項目远剩,顯示了如何編寫自定義lint檢查-包括單元測試
https://github.com/googlesamples/android-custom-lint-rules
該代碼庫編寫一個lint規(guī)則比下面寫上去包含的代碼有更好的基礎(chǔ)。


Lint 在ADT20上預(yù)先配置了大概100中檢查骇窍。但是瓜晤,也可以使用附加規(guī)則進(jìn)行擴(kuò)展。例如腹纳,如果你是庫項目的作者痢掠,并且你的庫項目具有一定的使用要求,則可以編寫額外的lint規(guī)則去檢查你的庫是否正確使用嘲恍,然后你可以向這個庫項目的用戶分發(fā)這些額外的lint規(guī)則足画。同樣,您可能需要執(zhí)行公司本地的規(guī)則蛔钙。

本文介紹如何編寫自定義lint規(guī)則锌云。首先,請參閱Google I/O 2012“開發(fā)工具的新功能”中的以下演講吁脱,用一個簡短的demo了解如何編寫和使用lint規(guī)則桑涎。(跳轉(zhuǎn)至視頻55分鐘18秒,如果嵌入式播放器未自動跳轉(zhuǎn)兼贡。)
(...................................內(nèi)嵌視頻好高端啊攻冷,諸位請自行官網(wǎng)............................................)

以下是該視頻的詳細(xì)信息。

為Android Studio創(chuàng)建自定義規(guī)則項目


首先遍希,你需要創(chuàng)建一個單獨的java項目去編譯這個lint 規(guī)則等曼。請注意,這是一個java項目,而不是Android項目禁谦,因為此代碼將被運行在Android studio胁黑,IntelliJ,Eclipse州泊,或Gradle丧蘸,或命令行l(wèi)int工具中運行--而不是在一臺設(shè)備上運行。

最簡單的方法是從示例項目開始遥皂,解壓它力喷,然后根據(jù)需要更改源代碼。你可以在Android Studio或者IntelliJ通過指向要導(dǎo)入的build.gradle項目.

這是一個Gradle項目演训,它具有使用Lint APIs的所有依賴項弟孟,并使用正確的清單條目構(gòu)建.jar文件。

為Eclipse創(chuàng)建自定義規(guī)則項目

如果你使用Eclipse样悟,使用一個簡單的庫創(chuàng)建一個簡單的java項目拂募。

接下來,添加 lint_api .jar文件到項目的classpath乌奇。這個jar文件包含規(guī)則實現(xiàn)的Lint APIS没讲,你可以在sdk的安裝目錄 tools/lib/lint_api.jar中找到lint_api jar包

創(chuàng)建檢測器

當(dāng)你實施“l(fā)int規(guī)則”時,你將準(zhǔn)備實現(xiàn)一個“檢測器”礁苗,它可以識別一個或多個不同類型的問題爬凑。這種分離使得單個檢查器識別與邏輯相關(guān)的不同類型的問題,但是可能具有不同的嚴(yán)重性,描述试伙,并且用戶可能想要獨立的抑制嘁信。例如,清單檢測器查找單獨的問題疏叨,如不正確的注冊順序潘靖,缺失minSdkVersion聲明等。有關(guān)如何編寫lint檢查的更多詳細(xì)信息蚤蔓,請參閱編寫Lint Check文檔卦溢。

在我們的示例中,我們假設(shè)我們有一個自定義View秀又,并且我們想要制定一個lint 規(guī)則单寂,確保這個自定義View的所有使用處都定義了這個特定的View屬性。

這里是完整的檢測器的源代碼:


首先你可以看到這個檢測器繼承ResourceXmlDetector吐辙。這是一種用于資源xml文件如布局和字符串資源聲明的檢測器宣决。還有其它類型的檢測器,例如處理java 源代碼或者字節(jié)碼的檢測器昏苏。

getApplicableElements()方法返回一組當(dāng)前檢測器關(guān)心的xml標(biāo)簽尊沸。這里我們只返回了我們自定義view的標(biāo)簽威沫。lint基礎(chǔ)設(shè)施將為每次出現(xiàn)的標(biāo)簽調(diào)用visitElement()方法--并且僅針對該標(biāo)記的出現(xiàn)。在visitElement()方法中洼专,我們簡單的看當(dāng)前的元素是否定義了我們自定義的屬性(“exampleString”)棒掠,如果沒有,我們就報告一份錯誤壶熏。

visitElement方法傳遞一個context對象句柠。這個context提供很多相關(guān)的context;例如棒假,你可以查找相應(yīng)的項目(從這兒請求minSdkVersion或者targetSdkVersion),或你可以查找正在被分析的xml文件的路徑精盅,或你可以創(chuàng)建一個錯誤的位置(如此處所示)帽哑。在這里,我們傳遞這個元素叹俏,這將使錯誤指向元素的開頭妻枕,但是你可以例如傳遞一個xml屬性對象,這將指向一個特定的屬性粘驰。

再說一次屡谐,查看Writing a Lint Check文檔以獲取更多的細(xì)節(jié)。

創(chuàng)建問題

report()方法第一個參數(shù)是ISSUE蝌数。這是該檢測器報告問題的引用愕掏。這是我們在上面類中頂部定義的靜態(tài)字段。

一個問題有幾個不同的屬性顶伞,按以上順序定義:

? ? ? ◆id饵撑,這是一個與這個問題有關(guān)的常量,應(yīng)該是簡短和描述性的唆貌;這個id例如用于java抑制注釋和
? ? ? ? xml抑制屬性來標(biāo)識這個問題滑潘。
? ? ? ◆摘要。這應(yīng)該是問題的簡要(單行)摘要锨咙,例如在Eclipse中的Lint Options UI和其它簡要描述
? ? ? ? 這個問題的地方语卤。
? ? ? ◆說明。這是對問題的更長的說明酪刀,這應(yīng)該向lint的用戶解釋這是什么問題粹舵。通常一次 lint 的錯誤
? ? ? ? 信息是簡短的(單行),并且有時候很難在單行錯誤信息中完全解釋一個細(xì)的問 題蓖宦,所以該說
? ? ? ? 明用于提供更多的上下文齐婴。該說明在lint命令行工具創(chuàng)建的完整HTML報告中顯示,在Eclipse
? ? ? ? Lint窗口中顯示當(dāng)前選定的問題等稠茂。

? ? ? ◆類別柠偶。這里有許多預(yù)定義的類別情妖,類別可以嵌套(例如可用性>圖標(biāo)),并且這有助于
? ? ? ? 用戶過濾和排序問題诱担,或者通過命令行僅運行某些類型的問題毡证。最常見的類別? ?
? ? ? ? 是“correctness”和"performance",但是也包括國際化,可訪問性蔫仙,可用性等料睛。
? ? ? ◆優(yōu)先權(quán)。優(yōu)先級是1-10之間的整數(shù)摇邦,其中10是最重要的恤煞,并且這被用于排序相應(yīng)每一個其
? ? ? ? 它優(yōu)先級的問題。
? ? ? ◆嚴(yán)重性施籍。一個問題可以有嚴(yán)重的居扒,錯誤,警告丑慎,或忽略默認(rèn)的嚴(yán)重性喜喂。請注意我所說的默
? ? ? ? 認(rèn):用戶可以通過一份lint.xml 文件(更多信息)覆蓋問題所使用的嚴(yán)重性。嚴(yán)重和錯誤在
? ? ? ? eclipse中作為“錯誤”展示竿裂,但是嚴(yán)重的問題在用戶想要在Eclipse當(dāng)中打包一份APK的任何
? ? ? ? 時候是自動運行的(沒有用戶的介入)玉吁,并且如果它們中的任何一個發(fā)現(xiàn)錯誤,然后這個
? ? ? ? 打包過程將被停止腻异〗保“忽略”嚴(yán)重性的規(guī)則不運行。
? ? ? ◆檢測器類捂掰。這只是指向負(fù)責(zé)識別問題的檢測器敢会,這應(yīng)該指向我們自己的類。請注意这嚣,我們
? ? ? ? 通過Lint自動實例化檢測器鸥昏,這是為每次運行完成的。因此姐帚,你不需要擔(dān)心在運行之后清除
? ? ? ? 檢測器中的實例狀態(tài)吏垮。在Eclipse中(其中Lint可以運行多次),將為每次運行創(chuàng)建一個新
? ? ? ? 的檢測器罐旗。因此膳汪,你的lint規(guī)則必須有一個公有的默認(rèn)構(gòu)造器。(如果沒有指定九秀,這個編譯
? ? ? ? 器將自動為你創(chuàng)建一個遗嗽,就是上面的例子
? ? ? ◆檢測范圍。這決定了這個問題適用于哪些類型的文件鼓蜒。這里我們只是聲明我們應(yīng)用于xml文
? ? ? ? 件痹换,但未使用的資源問題的范圍包含java和xml文件征字。

你還可以在問題上調(diào)用其它方法,例如娇豫,將問題定義為默認(rèn)禁用匙姜,或設(shè)置“更多信息”URL。

我們已經(jīng)創(chuàng)建了一個問題的實例冯痢。內(nèi)置的lint問題都在BuiltinIssueRegistry類中注冊氮昧。然而,對于自定義規(guī)則浦楣,我們需要提供我們自己的注冊表袖肥。每一個自定義jar文件提供它們自己問題的注冊類,其中每個問題注冊表可以包含由給定jar文件標(biāo)識的一個或多個問題振劳。

這是我們問題的自定義注冊表:

getIssues()方法返回的是由此注冊表提供的問題列表昭伸。我們在這種特殊的情況下明顯可以使用Collections.singletonList()來代替Arrays.asList(),但是這里通常會有多個問題澎迎。請注意,注冊表必須具有公共默認(rèn)構(gòu)造參數(shù)选调,以便它能夠被lint實例化夹供。

注冊注冊表

最后一件事情我們需要去做的是注冊這個問題注冊表,以便可以由lint找到仁堪。我們通過編輯jar文件的清單文件來做到這一點哮洽。

如果你是在Gradle/Android studio項目中使用它,則由Gradle處理弦聂;只要打開build.gradle文件并根據(jù)需要更新jar條目中注冊表的路徑鸟辅。

在Eclipse,創(chuàng)建一個清單文件莺葫,如下所示:

然后從你使用了上面清單文件的項目中導(dǎo)出一個jar文件匪凉。(我在Eclispe當(dāng)中遇到了一些困難;導(dǎo)出jar對話框中有明確的選項可以做到這一點捺檬,但是當(dāng)我查看導(dǎo)出的.jar文件并打開其中的manifest文件再层,它不包括我上面的兩行,所以我手動創(chuàng)建jar文件:jar cvfm customrule.jar META-INF/MANIFEST.MF googleio)

注意:Eclipse中的導(dǎo)出程序期望在第二行之后添加換行符堡纬。所以聂受,確保最后有一個空行,然后直接從Eclipse中導(dǎo)出應(yīng)該正常工作烤镐。

注冊自定義jar文件

現(xiàn)在我們有自己自定義規(guī)則.jar文件蛋济。當(dāng)lint運行時,它將在~/.android/lint/目錄查找自定義規(guī)則jar文件炮叶,因此我們需要將其放在那里:

(有人問過這個碗旅;Lint基本上調(diào)用了一般的Android工具方法來找到“工具設(shè)置目錄”渡处,用于模擬器快照,ddms配置等扛芽。你可以在這里找到相關(guān)的代碼:https://android.googlesource.com/platform/tools/base/+/master/common/src/main/java/com/android/prefs/AndroidLocation.java)

搜索位置

android目錄的位置通常是主目錄骂蓖;lint將在$ANDROID_SDK_HOME,${user.home}(java屬性)和在$HOME中搜索川尖,只是為了澄清登下。Lint按順序搜索第一個存在的位置:
◆ANDROID_SDK_HOME(系統(tǒng)環(huán)境或環(huán)境變量)
◆user.home(系統(tǒng)環(huán)境)
◆HOME(環(huán)境變量)

所以,如果ANDROID_SDK_HOME存在的話叮喳,然后user.home和HOME將被忽略被芳!這可能看起來是直觀的,但是原因是ANDROID_SDK_HOME并不指向你的SDK安裝路徑馍悟;環(huán)境變量為ANDROID_SDK畔濒。最近的代碼也在尋找ANDROID_HOME。所以锣咒,ANDROID_SDK_HOME真的是一個替代的主目錄位置侵状,當(dāng)你指向特定的模擬器AVDs等進(jìn)行單元測試時,在構(gòu)建服務(wù)器上使用毅整。這個命名是非常不幸的趣兄,并且導(dǎo)致了各種錯誤,但是很難改變悼嫉,而不會破壞用戶過去已經(jīng)依賴的記錄行為⊥叮現(xiàn)在,確保你不會使用環(huán)境變量ANDROID_SDK_HOME來指向你的sdk安裝目錄戏蔑。

之后蹋凝,它查找子路徑/.android/lint/,即其中一個對應(yīng)于剛找到的位置总棵。
◆ANDROID_SDK_HOME/.android/lint/
◆user.home/.android/lint/
◆HOME/.android/lint/
and loads any JAR files it finds there.

并加載在那里找到的任何jar文件鳍寂。

因此,如果你在?/ .android / lint /和ANDROID_SDK_HOME存在時有 Lint jar文件彻舰,你的JAR 文件將不會被讀取伐割。?

如果你在~/.android/lint/和ANDROID_SDK_HOME不存在時有Lint JAR文件,你的JAR文件將被讀取刃唤。

如果ANDROID_SDK_HOME存在隔心,將你的Lint JAR 文件放到ANDROID_SDK_HOME/.android/lint/

運行自定義檢查

最后,讓我們運行l(wèi)int去確保它知道我們的規(guī)則:

如果這不起作用尚胞,通過確保你的jar文件在正確的位置來解決這個問題硬霍,它包含在清單配置文件中正確注冊的行數(shù),完整的包名稱和類名稱是正確的笼裳,它是可實例化的(公有的默認(rèn)構(gòu)造器)唯卖,并注冊您的問題粱玲。

最后,讓我們來測試這條規(guī)則拜轨,這是一個示例布局文件:

現(xiàn)在讓我們在包含上面布局的項目中運行l(wèi)int(并使用 --check MyId參數(shù)抽减,我們僅檢查我們自己的問題):

使用Jenkins /其他構(gòu)建服務(wù)器

如果你作為正在連續(xù)構(gòu)建的一部分運行l(wèi)int,而不是將自定義lint規(guī)則放在構(gòu)建服務(wù)器使用的賬戶主目錄當(dāng)中橄碾,你還可以使用環(huán)境變量$ANDROID_LINT_JARS來指向包含要是用lint規(guī)則的jar文件的路徑(使用File.pathSeparator來分隔卵沉,例如在Windows和其它地方)。更多關(guān)于Jenkins+Lint的使用信息法牲,請查看https://wiki.jenkins-ci.org/display/JENKINS/Android+Lint+Plugin史汗。

更復(fù)雜的規(guī)則

上面的檢查非常簡單。還有更多的可能拒垃。一個真正有用的資源指出如何更多的查看存在的100左右的問題停撞。查看SDK git信息庫,在sdk/lint/悼瓮,特別是sdk/lint/dl/lint/libs/lint_checks/src/ com / android / tools / lint / checking戈毒。

貢獻(xiàn)規(guī)則

自定義lint規(guī)則支持在lint當(dāng)中主要用于編寫真正的本地規(guī)則。如果你想到一般感興趣的Lint檢查横堡,你可以使用上述方法來開發(fā)和檢查規(guī)則副硅。然而,請考慮將規(guī)則歸因于AOSP翅萤,以便所有的Android開發(fā)者可以從檢查中受益!請參閱合作頁腊满。

源代碼

在Gradle/Android Studio/IntelliJ中使用

this sample project

和在 Eclipse中使用

this .zip

在Eclipse當(dāng)中打開項目之前套么,上述自定義lint規(guī)則和 lint_api.jar包復(fù)制到項目的根目錄。

更多信息

如果你有Google+賬號碳蛋,你可以在此發(fā)表評論或提問胚泌。https://plus.google.com/u/0/116539451797396019960/posts/iyH3ER3LJF7

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市肃弟,隨后出現(xiàn)的幾起案子玷室,更是在濱河造成了極大的恐慌,老刑警劉巖笤受,帶你破解...
    沈念sama閱讀 218,204評論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件穷缤,死亡現(xiàn)場離奇詭異,居然都是意外死亡箩兽,警方通過查閱死者的電腦和手機(jī)津肛,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,091評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來汗贫,“玉大人身坐,你說我怎么就攤上這事秸脱。” “怎么了部蛇?”我有些...
    開封第一講書人閱讀 164,548評論 0 354
  • 文/不壞的土叔 我叫張陵摊唇,是天一觀的道長。 經(jīng)常有香客問我涯鲁,道長巷查,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,657評論 1 293
  • 正文 為了忘掉前任撮竿,我火速辦了婚禮吮便,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘幢踏。我一直安慰自己髓需,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,689評論 6 392
  • 文/花漫 我一把揭開白布房蝉。 她就那樣靜靜地躺著僚匆,像睡著了一般。 火紅的嫁衣襯著肌膚如雪搭幻。 梳的紋絲不亂的頭發(fā)上咧擂,一...
    開封第一講書人閱讀 51,554評論 1 305
  • 那天,我揣著相機(jī)與錄音檀蹋,去河邊找鬼松申。 笑死,一個胖子當(dāng)著我的面吹牛俯逾,可吹牛的內(nèi)容都是我干的贸桶。 我是一名探鬼主播,決...
    沈念sama閱讀 40,302評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼桌肴,長吁一口氣:“原來是場噩夢啊……” “哼皇筛!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起坠七,我...
    開封第一講書人閱讀 39,216評論 0 276
  • 序言:老撾萬榮一對情侶失蹤水醋,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后彪置,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體拄踪,經(jīng)...
    沈念sama閱讀 45,661評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,851評論 3 336
  • 正文 我和宋清朗相戀三年拳魁,在試婚紗的時候發(fā)現(xiàn)自己被綠了宫蛆。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,977評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖耀盗,靈堂內(nèi)的尸體忽然破棺而出想虎,到底是詐尸還是另有隱情,我是刑警寧澤叛拷,帶...
    沈念sama閱讀 35,697評論 5 347
  • 正文 年R本政府宣布舌厨,位于F島的核電站,受9級特大地震影響忿薇,放射性物質(zhì)發(fā)生泄漏裙椭。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,306評論 3 330
  • 文/蒙蒙 一署浩、第九天 我趴在偏房一處隱蔽的房頂上張望揉燃。 院中可真熱鬧,春花似錦筋栋、人聲如沸炊汤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,898評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽抢腐。三九已至,卻和暖如春襟交,著一層夾襖步出監(jiān)牢的瞬間迈倍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,019評論 1 270
  • 我被黑心中介騙來泰國打工捣域, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留啼染,地道東北人。 一個月前我還...
    沈念sama閱讀 48,138評論 3 370
  • 正文 我出身青樓焕梅,卻偏偏與公主長得像提完,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子丘侠,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,927評論 2 355

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

  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,135評論 25 707
  • 立冬立冬,艷陽高空逐样, 徒有夏氣蜗字,不見夏風(fēng)。 日漸西西脂新,水泛東東挪捕, 片帆掠影,清波臥弓争便, 地冒排齒级零,岸銜潛龍, 鏡涌...
    瘋界閱讀 241評論 0 0
  • 1. Qt串口通信類QSerialPort 在Qt5的的更新中,新增了串口通信的相關(guān)接口類QSerialPort奏纪,...
    Jiatian閱讀 4,390評論 0 5
  • 讀小說的樂趣鉴嗤,就是在想象中經(jīng)歷一段不可能;翻譯小說的樂趣序调,就是在想象中把這段不可能當(dāng)中的每個細(xì)節(jié)都經(jīng)歷一遍醉锅,并且在...
    joyli閱讀 2,193評論 2 1
  • 一個男人的——怨念边酒。 他對他心里的姑娘经柴,百般示好而不得芳心。 某一天他邀請一個姑娘去看演唱會墩朦,沒想到姑娘答應(yīng)了坯认。 ...
    逝者君閱讀 214評論 0 0