Android 項目代碼質量保證實踐

  • 2019 年 12 月 12 日
  • 筆記

來源:http://www.ltesting.net

1 背景

一個項目開發必然會涉及團隊協作,而工程質量就需要團隊去保證。一般我們期望的代碼:無潛在風險、無重複邏輯、風格無差異、可閱讀性好、新人上手速度快等。為了達到上述目標,一般團隊都會制定一套自己認可的編碼規範,並且周期性進行 code review。然而編碼規範的制定,那麼一套編碼規範需要包含哪些內容,另外編碼規範僅僅是一套軟規範,實際程序員同學能遵守到什麼程序還是一個未知數,所以需要我們進行人肉 code review,而這種人肉排查方式,很容易遺漏部分問題,保障性還是有些不足。 為此,我們從編碼前期、編碼中期和編碼後期保證進行了初步嘗試。

2 編碼前期 – 編碼規範

對於一個 Android 項目,一般需要涉及的編碼規範有:

  1. 普通 java 編碼風格規範 如每個方法最大行數,每個類文件的最大行數,每個方法最大參數數等
  2. 普通 java 編碼最佳實踐 如iffortry 等嵌套深度規範,變量初始化規範等
  3. 通用 Android 編碼規範(java 部分和 xml 部分), 包含 Android java 部分和 Android xml 部分,如避免使用普通內部類定義handler,避免 layout xml 中存在無用結點等
  4. Gradle 編碼規範 如盡量避免 lib 使用 module,獨立工程可以通過 aar 或 mvn 方式導入
  5. 具體項目相關的編碼規範等 如項目團隊規定使用自定義 LogUtil 打日誌,Activity、Fragment 等重要類的繼承關係,Activity 對應的 xml 文件必須以 activity_ 開頭等

制定了這些內容可以一定程度上規範程序猿的編碼,配合團隊進行了周期性的 code review (一般是一個版本一次,大概 4 個星期一次),會有比較好的效果。然而即使這麼做,還是存在一定的問題,距離我們期望的目標還是比較遠。比如各個單例類的定義五花八門,使用 LogUtil 代替 Log 的使用,Message.Obtain() 代替 new Message()Activity 部分文件命名,甚至 ActivityFragment 的基類定義規則還是很容易發生錯誤,並沒有被發現。隨着編碼規範的完善充實,多個開發的編碼規範如何保證,就會成為一個顯而易見的問題。

3 編碼中期 – 編碼模板

為了實現公用代碼復用,我們定義了一些 util 工具類,但隨着各個開發的補充,這套 util 工具類也越來越多,如 LogUtilKeyboardUtil 等,而這些類一部分是為了統一入口,如統一使用 LogUtil,可以統一做到測試服打開本地日誌,線上服關閉日誌;KeyboardUtil 方便使用者控制鍵盤的彈出隱藏等操作。雖然定義了這些工具類,但終究存在應該使用而沒有使用的情況。當然這些工具代碼並不難,開發在自己的模塊也能很容易的實現和使用,一般也不會出問題。然而上述講的優點都會消失掉。而這些問題依賴 code review 也是件頭疼的問題。 此外,RecycleView 的編碼方式,單例模式的實現方式等等,各個開發可能寫出各式代碼,甚至實現的單例模式並不是線程安全的。 提了這麼多,另一方面,要求開發在繁忙的業務中嚴格遵守這些規範,也有些強人所難。所幸,Android Studio 為我們提供了編碼模板來解放開發的工作,並一定程度上統一編碼風格。

3.1 Live Template

3.1.1 系統模板

查看一個使用 Android Studio 中很常見的例子,輸入 for,出現下拉列表如下:

image

當選擇 fori,出現編碼片段:

image

確認循環變量 i,跳入循環結果值的輸入:

image

上例,就是 Android Studio 中系統提供的 Live Template 一個實例。這個類似於 iOS 中的 Code Snippets,提供了代碼片段的能力。 Android Studio (Mac) 進入 Settings/Preferences -> Editor -> Live Templates,可以看到已定義的模板組:

image

查看 fori 編碼模板的實現:

image

  • A: 完成模板的快捷鍵 Tab
  • B: 位置分類 iterations
  • C: 編碼模板對應的縮寫 fori
  • D: 模板的內容
  • E: 模板應用環境

3.1.2 自定義模板

  1. 構建項目 group

image 輸入 group 的名稱

image

  1. 構建具體編碼模板

image

  • Abbreviation:觸發編碼模板的縮寫
  • Description:模板的具體描述
  • Template Text:具體的模板內容
  1. 變量定義 變量形式為 $<variable_name>$,點擊 Edit variables 可設置變量具體內容:

image

  1. Name:變量名
  2. Expression:變量表現
  3. Default value:默認值
  4. Skip if defined:是否跳過編輯已經定義的值
  5. 模板應用環境 點擊 No application contexts yet. Define,設置為 java 環境:

image

  1. 模板文件 構建了模板 group 後,在 android studio configtemplates 目錄下查看到 yanxuan.xml。 windows: C:Users\<user>\.AndroidStudiox.xconfigtemplates(user 為你的計算機用戶名) mac:~/Library/Preferences/AndroidStudiox.x/templates <templateSet group="test"> <template name="yxtest" value="testMethod($a$, $b$);" description="這是一個測試模板" toReformat="false" toShortenFQNames="true"> <variable name="a" expression="lineNumber()" defaultValue="2" alwaysStopAt="false" /> <variable name="b" expression="" defaultValue="" alwaysStopAt="true" /> <context> <option name="JAVA_CODE" value="true" /> <option name="JAVA_STATEMENT" value="true" /> <option name="JAVA_EXPRESSION" value="true" /> <option name="JAVA_DECLARATION" value="true" /> <option name="JAVA_COMMENT" value="true" /> <option name="JAVA_STRING" value="true" /> <option name="COMPLETION" value="true" /> </context> </template> </templateSet>
  2. 設置完畢,實踐查看:

image yxtest

image singleton

3.2 Android Studio Template

  1. 背景 除了 Live Template 之外,工程項目中很多新建的類也有很多機械的代碼,如我們定義的 Activity 要麼繼承自 BaseBlankActivity,要麼繼承自 BaseActionBarActivity,另外項目中採用 MVP 模式,因此一個 Activity 基本上會有一個對應的 presenter 類,一個 layout 文件,同時很多時候,一個頁面中會有一個需要支持刷新的 RecycleView 等。除此之外,ViewHolderHttpTask 等代碼也是固定模式的代碼。 這些都是固定機械的代碼,而如果是人肉去寫的話,難免會出現代碼風格不一致、不規範的情況,同時也浪費了一部分的時間。所幸,Android Studio 提供了工程類模板,方便我們實現這樣的功能。
  2. 系統模板 查看 Android Studio 系統類模板,我們能發現有很多定義好的類模板:

image 如需要創建一個空的 Activity 頁面,可以選擇 Empty Activity,並填寫類名,layout 名稱等信息,之後就能出現對應的添加或修改:MainActivity.javaactivity_main.xmlAndroidManifest.xml

image 而這些模板定義,可以在相關路徑文件中找到: < >Windows: ${Android Studio 的安裝目錄}/plugins/android/lib/templates/Mac: Android Studio.app/Contents/plugins/android/lib/templates/

image

針對 EmpytActivity 這裡需要定義的文件有: < >globals.xml.ftl:定義當前模板的一些全局變量recipe.xml.ftl:定義模板拷貝的邏輯等template.xml:定義模板對話框的樣式template_blank_activity.png:定義模板的圖標root/src/app_package/SimpleActivity.java.ftl:具體的模板文件

image16

圖片來自:http://www.slideshare.net/murphonic/custom-android-code-templates-15537501

  • 自定義模板 而針對我們需要自定義的模板,可以在模板定義路徑下新建文件夾和文件即可,細節內容可查看 Tutorial How To Create Custom Android Code Templates 項目的模板文件內容:

image17

  • 設置完模板文件之後,重啟 Android Studio,可以生效模板文件,使用模板文件如下:
  • image18

4 編碼後期 – 靜態代碼檢查

由上,我們定義了編碼規範,定義了 Live Template 和 Android Studio Template 方便程序猿更好的准守我們的項目編碼規範。然後編碼規範畢竟只是軟規範,而提供編碼模板更多的解決大量 util 的使用問題和便利小夥伴完成機械編碼,並不能完全保證程序猿嚴格按照全部的規範來編碼。 為此,我們需要一套靜態代碼檢查機制能檢查已有的代碼是否遵守規範。總結已有的規範,可以將規範類型歸納為普通 Java 規範、普通 Android 規範、具體項目規範等。而這些檢查點,可以配合不同的檢查工具進行檢查。

4.1 檢查 java 代碼風格 – CheckStyle

對於 java 規範,checkstyle 幫助開發者實現常用的檢查。這裡 CheckStyle 能檢查的內容有:

  1. Javadoc 注釋
  2. 命名約定
  3. 標題
  4. Import 語句
  5. 體積大小
  6. 空白
  7. 修飾符
  8. 代碼問題
  9. 類設計
  10. 混合檢查(包活一些有用的比如非必須的System.out和printstackTrace)

檢查內容很多,而檢查項需要和具體的項目規範做結合。如,每行代碼字符數控制在 80,單頁代碼行數控制在 800 等。因此需要結合配置文件,來檢查項目中的 java 代碼。在 Android Studio 上配置 CheckStyle 流程如下:

  1. 在 Android Studio 中添加 gradle Plugin apply plugin: 'checkstyle'
  2. 設置 CheckStyle 版本 checkstyle { toolVersion '6.1.1' showViolations true }
  3. 配置 CheckStyle 檢查項 task checkstyle(type: Checkstyle) { configFile file("$configDir/checkstyle/checkstyle.xml") configProperties.checkstyleSuppressionsPath = file("$configDir/checkstyle/suppressions.xml").absolutePath source 'src' include '**/*.java' // 檢查 java 代碼 exclude '**/gen/**' // 排除生成的代碼 classpath = files() ignoreFailures true // 忽略檢查失敗的情況,避免gradle命令執行中止 }
  4. 配置自定義的檢查項: checkstyle.xml<!--單個文件方法數上限最多為 30--> <module name="MethodCount"> <property name="maxTotal" value="30"/> </module> <!--方法名的首字母是小寫--> <module name="MethodName"> <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> </module> <!--靜態變量名的首字符是 s--> <module name="StaticVariableName"> <property name="format" value="^[a-z][a-zA-Z0-9]*$"/> <property name="applyToPublic" value="true"/> <property name="applyToProtected" value="true"/> <property name="applyToPackage" value="true"/> <property name="applyToPrivate" value="true"/> </module> <!--只有私有構造函數的類需要定義成 final 類型--> <module name="FinalClass"/> ... 具體其他的檢查項配置可以查看 檢查配置鏈接
  5. 執行 checkstyle 檢查 ./gradlew checkstyle
  6. 查看檢查結果 命令執行結束,查看檢查結果文件:${project}/app/build/reports/checkstyle/checkstyle.html
  1. image

4.2 檢查 java 代碼質量 – FindBugs

CheckStyle 工具不同的是,FindBugs 不注重樣式或者格式,而是試圖尋找出真正的缺陷或者現在的性能問題。FindBugs 檢查類和 Jar 文件,不是通過分析類文件的形式或結構來分析程序,而是使用 Visitor 模式,將位元組碼與一組缺陷模式進行對比以發現可能的問題。而這些問題比如如下:

  1. 1. 忽略返回值

image 上述代碼執行結束之後,並沒有什麼意義,變量 a 的值也不會變成 dddbbbccc。因此,上述代碼很可能是程序猿的 bug。為此 FindBugs 能找出這種問題

  1. 2. 空指針示例

image 上述最後一行代碼,很明顯在執行的時候會發生空指針異常,這裡因為 FindBugs 無法知道變量 strMaps 是否確實有 aaa 這個 key,為此這裡會檢查出錯誤。

  1. 3. 未初始化的成員變量使用
  1. image
  2. 這裡由於類成員變量 actions 並未初始化,因此當 actions.add("TEST") 被執行的時候會發生異常。

Android Studio 上 FindBugs 的集成如下:

  1. 在 gradle 中引入插件 apply plugin: 'findbugs'
  2. 在 gradle 中配置 findbugs task task findbugs(type: FindBugs, dependsOn: "assembleDebug") { ignoreFailures = false effort = "max" reportLevel = "high" excludeFilter = new File("$configDir/findbugs/findbugs-filter.xml") classes = files("${project.rootDir}/app/build/intermediates/classes") source 'src' include '**/*.java' exclude '**/gen/**' reports { xml.enabled = false html.enabled = true xml { destination "$reportsDir/findbugs/findbugs.xml" } html { destination "$reportsDir/findbugs/findbugs.html" } } classpath = files() ignoreFailures true // 避免檢查失敗 gradle 執行中止 }
  3. 執行 findbugs 檢查 ./gradlew findbugs
  4. 查看檢查結果 查看檢查結果文件:${project}/app/build/reports/findbugs/findbugs.html

image

4.3 檢查 Android 代碼質量 – Lint

4.3.1 基本介紹

前面 FindBugs 的檢查實例(忽略返回值, 未初始化的成員變量使用),可以發現在 Android Studio IDE 上,已經出現了標黃提示,我們把光標放上去,就能看到具體的提示了:

image

cmd + F1 可以看到具體的錯誤提示:

image

這就原生 Lint 給我們提供的錯誤提示功能。除了和 FindBugs 重複的純 java 代碼檢查之外,Lint 能檢查很多其他工具無法檢查的內容,也更貼合 Android:

image

在 Activity 內定義非靜態內部類 Handler 的報警

image

AndroidManifest.xml 中定義 export 為 true 的廣播接受器,但沒有定義權限,Lint 檢查認為是不安全的

image

build.gradle 文件中引用的 support 包的版本低的提示

Android Lint 是一個靜態代碼檢查工具,能夠對潛在的 bug,可能的安全性、性能、可用性、可訪問性、國際化等優化內容做出監測:

image

來自官方文檔 Improve Your Code with Lint

  1. App Source Files:工程中的源文件,包括 java 代碼、資源 xml 代碼、gradle 文件,圖片資源文件以及 progroud 等文件
  2. lint.xml:配置文件,配置哪些 lint 檢查可以排除,自定義問題的嚴重級別
  3. lint Tool:靜態代碼檢查工具,可以是命令行或者集成在 Android Studio 上
  4. lint Output:代碼檢查結果,可以直接顯示在 Console 上,也可以是 lint-result.html

4.3.2 原生 Lint 檢查

在 Android SDK Tools 16 及更高的版本中,Lint 工具會自動安裝。原生 Lint 的檢查項已經有 200 多項 (包括前面示例的 5 項內容),因此使用原生的功能點,就能檢查開發中的大部分通用問題。

  1. Android Studio IDE 上配置 Lint 檢查偏好設置 (Mac 下) PreferencesEditorInspections 進入 Android StudioLint 配置界面

image

  • A:配置 Profile,方便不同項目或者不同情況下使用不同的 Profile 進行檢查
  • B:Lint 檢查點 Group
  • C:Lint 檢查點具體描述
  • D:Lint 檢查點警告級別設置
  • E:Lint 檢查點開關
  1. lint.xml 上配置 Lint 除了可以通過 IDE 配置 Lint,還可以通過直接 lint.xml 為單個項目配置檢查規則 <?xml version="1.0" encoding="UTF-8"?> <lint> <!-- Disable the given check in this project --> <issue id="IconMissingDensityFolder" severity="ignore" /> <!-- Ignore the ObsoleteLayoutParam issue in the specified files --> <issue id="ObsoleteLayoutParam"> <ignore path="res/layout/activation.xml" /> <ignore path="res/layout-xlarge/activation.xml" /> </issue> <!-- Ignore the UselessLeaf issue in the specified file --> <issue id="UselessLeaf"> <ignore path="res/layout/main.xml" /> </issue> <!-- Change the severity of hardcoded strings to "error" --> <issue id="HardcodedText" severity="error" /> </lint> 來源 Android Develop 文檔 Improve Your Code with Lint
  2. gradle 中配置 Lint task android { lintOptions { abortOnError false // 配置 lint 過程中出錯,不中止 gradle 任務 xmlReport false htmlReport true lintConfig file("$configDir/lint/lint.xml") // 配置 lint 檢查規則 htmlOutput file("$reportsDir/lint/lint-result.html") // 配置 lint 輸出文件 xmlOutput file("$reportsDir/lint/lint-result.xml") // 配置 lint 輸出文件 } }
  3. 執行檢查 在工程根目錄執行以下命令 (Mac),以執行檢查任務 ./gradlew lint
  4. 檢查結果 生成的檢查結果在 ${項目工程}/app/build/reports/lint/lint-result.html

image

4.3.3 自定義 Lint 檢查

雖然原生的 Lint 檢查已經很強大了,檢查項也已經很多,然而還是無法滿足項目中的特有需求

  1. log 統一使用 LogUtil
  2. 對應 Activity 的 layout 命名為 activity_XXX
  3. 對應 Fragment 的 layout 命名為 fragment_XXX
  4. Activity 必須派生自 BaseBlankActivityBaseActionBarActivity

對於以上這些需求,原生 Lint 檢查(包括 CheckStyleFindBugs)就已經無能為力了,我們必須編碼支持自定義檢查。以項目中集成的 Lint 檢查為例,講述流程:

4.3.3.1 配置 Gradle,引入 lint
dependencies { ... compile 'com.android.tools.lint:lint-api:24.5.0' compile 'com.android.tools.lint:lint-checks:24.5.0' } 
  • lint-api: 官方給出的API,API並不是最終版,官方提醒隨時有可能會更改API接口。
  • lint-checks:已有的檢查。
4.3.3.2 定義 IssueRegistry

新建一個 MyIssueRegistry 類,繼承自 IssueRegistry。用來註冊我們自定義的全部 issue

public class MyIssueRegistry extends IssueRegistry { @Override public List<Issue> getIssues() { System.out.println("********YXLint rules works!!!********"); return Arrays.asList( LogUsageDetector.ISSUE, ToastUsageDetector.ISSUE, ActivitySuperClassDetector.ACTIVITY_SUPER_CLASS_ISSUE, ... BuildGradleVersionDetector.ISSUE); } } 

其中:

  • LogUsageDetector.ISSUE:用於檢查不允許直接使用 Log.* 方式輸出本地日誌的代碼
  • ToastUsageDetector.ISSUE:用於檢查直接用 Toast 方式顯示 toast 的代碼
  • ActivitySuperClassDetector.ACTIVITY_SUPER_CLASS_ISSUE:用於檢查 Activity 的基類
  • BuildGradleVersionDetector.ISSUE:用於檢查 gradle 文件中不允許直接寫數字版本號的代碼
4.3.3.3 gradle 清單項中註冊前面定義的 IssueRegistry
jar { manifest { attributes('Lint-Registry': 'com.netease.htlint.lintrules.MyIssueRegistry') } } 
4.3.3.4 定義 Detector

MyIssueRegistry 類中聲明註冊了各個 DetectorIssueIssueDetector 發現並報告,是 Android 程序代碼可能存在的風險。而這裡就需要真正實現這些 Detector,以檢查 Activity 的基類為例。

image

ACTIVITY_SUPER_CLASS_ISSUE 這個 Issue 的定義需要使用 Issue.create(...) 方式實現,同時需要傳入 6 個參數分別如下:

  • A:一個固定的唯一的 id 代表這個 Issue
  • B:對於問題的簡短總結,描述問題而不是修復措施
  • C:完整的問題解釋和修復建議
  • D:問題類別,現在已有的問題類別有如下
    • Lint
    • Correctness (incl. Messages)
    • Security
    • Performance
    • Usability (incl. Icons, Typography)
    • Accessibility
    • Internationalization
    • Bi-directional text
  • E:優先級,必須在1到10之間,10為最重要/最嚴重。
  • F:嚴重級別,可選值有 Fatal, Error, Warning, Informational, Ignore
  • G:為 IssueDetector 提供映射關係,Detector 就是當前類。聲明掃描檢測的範圍 Scope,描述 Detector 需要分析時需要考慮的文件集,包括:Resource 文件或目錄、Java 文件、Class 文件

ActivitySuperClassDetector 繼承自 Detector,並實現 Detector.JavaScaner。這裡主要自定義實現的方法如上圖 H,I

  • H:檢查類的基類是 "android.support.v4.app.Activity" 或 "android.app.Activity"
  • I:具體檢查類的方法,這裡需要排除非 yanxuan 包名下的代碼,判斷當前類的基類是否是 BaseBlankActivityBaseActionBarActivity?如果都不是的話,則報告錯誤
  • J:報出問題的方法:該方法中指定參數有:
    • 需要報錯的 Issue
    • 發生問題的代碼在語法樹上的節點
    • 發生問題的代碼位置
    • 警告的信息
4.3.3.5 生成 jar 包

完成上述步驟,可以在控制台中通過命令 ../../gradlew assemble 來執行編譯任務,就可以輸出我們需要的 jar 文件 (htlintrules_jar-0.0.1.jar) 了

4.3.3.6 jar 的使用

按照 Google 方法,可以將 htlintrules_jar-0.0.1.jar 拷貝到 ~/.android/lint 中,但缺點是針對會影響一台機器其他的工程。很明顯,我們的自定義 Lint 檢查有很多是項目中特有的一些編碼規範。 為此,我們採用 LinkedIn 方案:將 jar 放到一個 aar 中。這樣我們就可以針對工程進行自定義 Lint,lint.jar 只對當前工程有效。 在現有的 htlintrules_jar 工程的 build.gradle 中添加代碼,整體看起來如下:

apply plugin: 'java' apply plugin: 'maven' dependencies { compile 'com.android.tools.lint:lint-api:24.5.0' compile 'com.android.tools.lint:lint-checks:24.5.0' } jar { manifest { attributes('Lint-Registry': 'com.netease.htlint.lintrules.MyIssueRegistry') } } configurations { lintJarOutput } dependencies { lintJarOutput files(jar) } defaultTasks 'assemble' 

同時新建另一個工程 htlint,在其 build.gradle 文件中添加如下代碼:

/* * rules for including "lint.jar" in aar */ configurations { lintJarImport } dependencies { lintJarImport project(path: ':htlintrules_jar', configuration: "lintJarOutput") } task copyLintJar(type: Copy) { from (configurations.lintJarImport) { rename { String fileName -> 'lint.jar' } } into 'build/intermediates/lint/' } project.afterEvaluate { def compileLintTask = project.tasks.find { it.name == 'compileLint' } compileLintTask.dependsOn(copyLintJar) } 

最後在 app 工程的 build.gradle 中添加 htlint 引用,配置完成

dependencies { compile project(':htlint') // lint 檢查庫 ... } 
4.3.3.7 自定義 Lint 檢查執行及結果檢查

${項目工程}/app/ 目錄下執行 ../gradlew lint

image

根據提示查看 lint-result.html 文件,可以查看到前面編寫的 ActivitySuperClassDetector.ACTIVITY_SUPER_CLASS_ISSUE 已經生效,並且檢查出了相關的非規範代碼。

image

image

4.3.3.8 排除錯誤的檢查結果

前面很好的給出了檢查結果了,然而我們會發現,FullScreenVideoActivity 確實是需要的錯誤檢查結果,而 WXEntryActivity 卻不是,這個類是有集成微信分享時需要的,並且按照微信開放平台的文檔來編寫,因此並不需要按照項目規範,繼承 BaseBlankActivityBaseActionBarActivity。為此,我們期望 WXEntryActivity 不應該被檢查出 WrongActivitySuperClass 錯誤 為此,我們可以在 WXEntryActivity 類名簽名添加 SuppressLint 註解:

@SuppressLint("WrongActivitySuperClass") public class WXEntryActivity extends Activity implements IWXAPIEventHandler{ ... } 
  1. 排除 java 類或者方法的 Lint 檢查 若需要抑制某個 Issue 檢查,可以在類定義簽名或者方法定義簽名,添加註解 @SuppressLint(${IssueId})。這裡設置的就是具體某個 Issueid 值 若需要抑制全部的 Issue 檢查,可以使用 all 關鍵字,比如:@SuppressLint("all")
  2. 排除 xml 資源的 Lint 檢查 如項目中引入微博分享 sdk,按照官方文檔,需要在 AndroidManifest 中聲明 com.sina.weibo.sdk.net.DownloadService 這個 Service,而這個 Service 會被 Lint 檢查為未定義,為此需要 xml 文件中也過濾部分代碼的 Lint 的檢查: <manifest xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" package="com.netease.yanxuan"> ... <service android:name="com.sina.weibo.sdk.net.DownloadService" android:exported="false" tools:ignore="MissingRegistered" /> </manifest> 這裡對於單個 Issue 過濾的規則為:tools:ignore=${IssueId} 如果需要過濾全部的 Issue,可以使用 all 關鍵字:tools:ignore="all"

4.4 其他代碼檢查工具

4.4.1 360 火線

360 火線 是 360 公司和信息安全部門深度合作,定製的適用於 360 公司產品的安卓 APP 安全檢查規則。總共覆蓋 61 項代碼檢查。使用也非常方便,細節看 使用文檔,可以直接使用 jar 包並執行命令或集成 Android Studio Plugin 執行檢查

image

4.4.2 pmd

pmd 代碼檢查工具,包含 16 個規則集,涵蓋了 Java 的各種常見問題。其中規則集包含 基本(rulesets/basic.xml)終結函數(finalizer)未使用的代碼(rulesets/unusedcode.xml)設計(rulesets/design.xml) 等。 相比 FindBugspmd 的一些規則更具爭議,但 pmd 支持我們構建自己的規則集

<?xml version="1.0"?> <ruleset name="customruleset"> <description> Sample ruleset for developerWorks article </description> <rule ref="rulesets/design.xml"/> <rule ref="rulesets/naming.xml"/> <rule ref="rulesets/basic.xml"/> </ruleset> 

4.5 代碼檢查工具整合及集成 jenkins

為整合這些檢查工具,在 gradle 中自定義 check 命名,並依賴其他的 task。在執行檢查的時候,可以通過 ./gradlew check 來執行全部的檢查命令。

check.dependsOn 'checkstyle', 'findbugs', 'pmd', 'lint' 

另一方面,這種代碼檢查,如果等到開發完成的時候再去執行,很可能問題積累了很多,甚至導致產品上線前,開發並不能來得及修正全部的問題。為此,可以將代碼檢查的命令集成 jenkins,保證開發每天都能看到當前的代碼的缺陷,能及時的修改

5 總結

我們從編碼前的編碼規範,編碼進行中的編碼模板,編碼結束後的代碼靜態檢查,保障了程序小夥伴們的代碼。除此之外,還有很多不完善的地方需要我們做進一步處理:

  1. 和特定項目相關的自定義 Lint 檢查項,僅支持了一部分的編碼規範,自定義 Lint 檢查項需要後續完成
  2. 雖然檢查工具很多,檢查的結果內容也很多,而很明顯,這些檢查工具相互之間是有重複的情況(主要是純 java 代碼部分的檢查),因此如果整理檢查結果,並過濾出我們真正關心的問題,也是後續需要完成的內容

星雲測試

http://www.teststars.cc

奇林軟件

http://www.kylinpet.com

聯合通測

http://www.quicktesting.net