テストを作成してアプリが機能要件を満たしていることを確認するのは重要ですが、lint を使用してコードを実行し、コードに構造上の問題がないことを確認するのも重要です。lint ツールは、構造化が不十分なコードの発見に役立ちます。そのようなコードは Android アプリの信頼性と効率に悪影響を及ぼし、コードの保守を困難にします。
たとえば、XML リソース ファイル内に使用されない名前空間が含まれていると、そのためのスペースが占有され、不要な処理が発生します。非推奨になった要素や、ターゲットの API バージョンでサポートされていない API 呼び出しといった構造上の問題があると、コードが適切に実行されなくなることがあります。lint はこうした問題を除去するのに役立ちます。
lint チェックのパフォーマンスを改善するには、コードにアノテーションを追加する必要もあります。
概要
Android Studio には、lint と呼ばれるコードスキャン ツールがあります。このツールを使用すると、アプリの実行やテストケースの作成を行わずに、コードの構造上の品質に関する問題を特定して修正できます。ツールによって問題が検出されると、問題の内容を説明するメッセージと重大度レベルも報告されるので、実施する必要がある重要な改善を速やかに優先順位付けできます。プロジェクトと無関係な問題を無視するために問題の重大度レベルを下げたり、特定の問題を優先するために重大度レベルを上げたりできます。
lint ツールは、Android プロジェクトのソースファイルをチェックして潜在的なバグを探し、正確性、セキュリティ、パフォーマンス、ユーザビリティ、ユーザー補助、国際化機能を最適化するための改善点を検出します。Android Studio を使用すると、アプリをビルドするたびに、設定済みの lint インスペクションと IDE インスペクションが実行されます。ただし、手動でインスペクションを実行することも、コマンドラインから lint を実行することもできます。
注: Android Studio でコードをコンパイルすると、IntelliJ コード インスペクションも実行されるため、効率的にコードレビューを実施できます。
図 1 は、lint ツールがアプリのソースファイルをどのように処理するかを示しています。
図 1. lint ツールによるコードスキャンのワークフロー
- アプリのソースファイル
- ソースファイルは、Java、Kotlin、および XML ファイル、アイコン、ProGuard 設定ファイルなど、Android プロジェクトを構成するファイルで構成されています。
lint.xml
ファイル- 除外する lint チェックを指定し、問題の重大度レベルをカスタマイズするために使用する設定ファイル。
- lint ツール
- Android プロジェクトに対して実行できる静的コードスキャン ツール。コマンドラインまたは Android Studio 内で実行できます(手動でインスペクションを実行するをご覧ください)。lint ツールは、Android アプリの品質とパフォーマンスに悪影響を及ぼす可能性があるコードの構造上の問題をチェックします。アプリを公開する前に、lint が検出したエラーをすべて修正することを強くおすすめします。
- lint チェックの結果
- lint チェックの結果は、コンソールか、または Android Studio の [Inspection Results] ウィンドウで確認できます。手動でインスペクションを実行するをご覧ください。
コマンドラインから lint を実行する
Android Studio または Gradle を使用している場合は、プロジェクトのルート ディレクトリから以下のいずれかのコマンドを入力することで、Gradle ラッパーを使用してプロジェクトの lint
タスクを呼び出すことができます。
- Windows の場合:
gradlew lint
- Linux または Mac の場合:
./gradlew lint
出力は次のようになります。
> Task :app:lintDebug Wrote HTML report to file:<path-to-project>/app/build/reports/lint-results-debug.html
lint ツールによるチェックが完了すると、lint レポートの XML バージョンおよび HTML バージョンのパスが表示されます。図 2 に示すように、HTML レポートに移動してブラウザで開くことができます。
図 2. HTML 版 lint レポートの例
プロジェクトにビルド バリアントが含まれている場合、lint を実行するとデフォルトのバリアントしかチェックされません。別のバリアントに対して lint を実行するには、バリアント名を大文字にして、先頭に「lint」を付ける必要があります。
./gradlew lintRelease
コマンドラインから Gradle タスクを実行する方法については、コマンドラインからアプリをビルドするをご覧ください。
スタンドアロン ツールで lint を実行する
Android Studio も Gradle も使用していない場合は、SDK Manager から Android SDK コマンドライン ツールをインストールすると、スタンドアロンの lint ツールを使用できます。その場合、lint ツールは android_sdk/cmdline-tools/version/bin/lint
に配置されます。
プロジェクト ディレクトリにあるファイルのリストに対して lint を実行するには、次のコマンドを使用します。
lint [flags] <project directory>
たとえば、myproject
ディレクトリとそのサブディレクトリにあるファイルをスキャンするには、下記のコマンドを実行します。問題 ID MissingPrefix
は、Android 名前空間接頭辞が不足している XML 属性のみをスキャンするよう lint に指示します。
lint --check MissingPrefix myproject
このツールでサポートされているフラグとコマンドライン引数の一覧は、次のコマンドで確認できます。
lint --help
次の例は、Earthquake というプロジェクトに対して lint コマンドを実行したときのコンソール出力を示しています。
$ lint Earthquake Scanning Earthquake: ............................................................................................................................... Scanning Earthquake (Phase 2): ....... AndroidManifest.xml:23: Warning: <uses-sdk> tag appears after <application> tag [ManifestOrder] <uses-sdk android:minSdkVersion="7" /> ^ AndroidManifest.xml:23: Warning: <uses-sdk> tag should specify a target API level (the highest verified version; when running on later versions, compatibility behaviors may be enabled) with android:targetSdkVersion="?" [UsesMinSdkAttributes] <uses-sdk android:minSdkVersion="7" /> ^ res/layout/preferences.xml: Warning: The resource R.layout.preferences appears to be unused [UnusedResources] res: Warning: Missing density variation folders in res: drawable-xhdpi [IconMissingDensityFolder] 0 errors, 4 warnings
上記の出力には 4 つの警告が含まれており、エラーはありません。警告のうち 3 つ(ManifestOrder
、UsesMinSdkAttributes
、UnusedResources
)はプロジェクトの AndroidManifest.xml
ファイルに関するもので、1 つ(IconMissingDensityFolder
)は Preferences.xml
レイアウト ファイルに関するものです。
警告を抑制するように lint を設定する
デフォルトでは、lint スキャンを実行すると、lint がサポートする問題がすべてチェックされますが、lint でチェックする問題を限定することも、問題の重大度レベルを指定することもできます。たとえば、プロジェクトと無関係な特定の問題に対する lint チェックを無効にしたり、重要でない問題がレポートされる重大度レベルを下げたりできます。
次に示すさまざまなレベルで lint チェックを設定できます。
- グローバル(プロジェクト全体)
- プロジェクト モジュール
- 製品版モジュール
- テスト モジュール
- 開いているファイル
- クラス階層
- バージョン管理システム(VCS)のスコープ
Android Studio 内で lint を設定する
Android Studio の使用中は、組み込みの lint ツールによってコードがチェックされます。次の 2 つの方法で警告とエラーを表示できます。
- コードエディタ内のポップアップ テキスト。lint が問題を検出すると、問題のあるコードが黄色でハイライト表示されます。重大な問題の場合は、コードに赤色の下線が引かれます。
- lint で [Analyze] > [Inspect Code] をクリックした後の [Inspection Results] ウィンドウ。 手動でインスペクションを実行するをご覧ください。
lint ファイルを設定する
lint チェックの設定は、lint.xml
ファイルで指定できます。このファイルを手動で作成する場合は、Android プロジェクトのルート ディレクトリに配置してください。
lint.xml
ファイルは、1 つ以上の <issue>
子要素を囲む <lint>
親タグで構成されます。lint では、<issue>
ごとに固有の id
属性値が定義されます。
<?xml version="1.0" encoding="UTF-8"?> <lint> <!-- list of issues to configure --> </lint>
問題の重大度レベルを変更するか、問題の lint チェックを無効にするには、<issue>
タグで severity 属性を設定します。
ヒント: lint がサポートする問題と、それに対応する問題 ID の完全なリストを表示するには、lint --list
コマンドを実行します。
サンプル lint.xml ファイル
次の例は、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>
Java、Kotlin、XML ソースファイルの lint チェックを設定する
Java、Kotlin、XML ソースファイルの lint チェックを無効にできます。
ヒント: Java、Kotlin、XML ソースファイルの lint チェック機能は、[Default Preferences] ダイアログで管理できます。[File] > [Other Settings] > [Default Settings] を選択し、[Default Preferences] ダイアログの左ペインで [Editor] > [Inspections] を選択します。
Java または Kotlin で lint チェックを設定する
Android プロジェクトのクラスまたはメソッドに対する lint チェックのみを無効にするには、そのコードに @SuppressLint
アノテーションを追加します。
次の例は、onCreate
メソッドで NewApi
問題の lint チェックをオフにする方法を示しています。lint ツールは、このクラスの他のメソッドでは引き続き NewApi
問題をチェックします。
Kotlin
@SuppressLint("NewApi") override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.main)
Java
@SuppressLint("NewApi") @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main);
次の例は、FeedProvider
クラスで ParserError
問題の lint チェックをオフにする方法を示しています。
Kotlin
@SuppressLint("ParserError") class FeedProvider : ContentProvider() {
Java
@SuppressLint("ParserError") public class FeedProvider extends ContentProvider {
ファイル内のすべての lint 問題のチェックを無効にするには、次のように all
キーワードを使用します。
Kotlin
@SuppressLint("all")
Java
@SuppressLint("all")
XML で lint チェックを設定する
XML ファイルの特定のセクションに対する lint チェックを無効にするには、tools:ignore
属性を使用します。lint.xml
ファイルに次の名前空間値を挿入すると、lint ツールによって属性が認識されます。
namespace xmlns:tools="http://schemas.android.com/tools"
次の例は、XML レイアウト ファイルの <LinearLayout>
要素で UnusedResources
問題の lint チェックをオフにする方法を示しています。親要素で宣言された ignore
属性は、その子要素によって継承されます。この例では、<TextView>
子要素の lint チェックも無効になります。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" tools:ignore="UnusedResources" > <TextView android:text="@string/auto_update_prompt" /> </LinearLayout>
複数の問題に対するチェックを無効にするには、無効にする問題のリストをカンマ区切り文字列で指定します。次に例を示します。
tools:ignore="NewApi,StringFormatInvalid"
XML 要素のすべての問題に対する lint チェックを無効にするには、次のように all
キーワードを使用します。
tools:ignore="all"
Gradle で lint オプションを設定する
Android Plugin for Gradle を使用すると、モジュール レベルの build.gradle
ファイルの lint{}
ブロックで、実行するチェックや無視するチェックなど、特定の lint オプションを設定できます。次のコード スニペットは、設定可能なプロパティの一部を示しています。
Groovy
android { ... lint { // Turns off checks for the issue IDs you specify. disable 'TypographyFractions','TypographyQuotes' // Turns on checks for the issue IDs you specify. These checks are in // addition to the default lint checks. enable 'RtlHardcoded','RtlCompat', 'RtlEnabled' // To enable checks for only a subset of issue IDs and ignore all others, // list the issue IDs with the 'check' property instead. This property overrides // any issue IDs you enable or disable using the properties above. checkOnly 'NewApi', 'InlinedApi' // If set to true, turns off analysis progress reporting by lint. quiet true // If set to true (default), stops the build if errors are found. abortOnError false // If true, only report errors. ignoreWarnings true // If true, lint also checks all dependencies as part of its analysis. Recommended for // projects consisting of an app with library dependencies. checkDependencies true } } ...
Kotlin
android { ... lintOptions { // Turns off checks for the issue IDs you specify. disable("TypographyFractions") disable("TypographyQuotes") // Turns on checks for the issue IDs you specify. These checks are in // addition to the default lint checks. enable("RtlHardcoded") enable("RtlCompat") enable("RtlEnabled") // To enable checks for only a subset of issue IDs and ignore all others, // list the issue IDs with the 'check' property instead. This property overrides // any issue IDs you enable or disable using the properties above. checkOnly("NewApi", "InlinedApi") // If set to true, turns off analysis progress reporting by lint. quiet = true // If set to true (default), stops the build if errors are found. abortOnError = false // If true, only report errors. ignoreWarnings = true // If true, lint also checks all dependencies as part of its analysis. Recommended for // projects consisting of an app with library dependencies. isCheckDependencies = true } } ...
問題の特定の重大度(enable
、disable
/ignore
、informational
、warning
、error
、fatal
)をオーバーライドする lint メソッドはすべて、設定の順序を考慮します。たとえば、finalizeDsl()
で問題を fatal に設定すると、メイン DSL での問題の無効化よりも優先されます。
警告ベースラインを作成する
プロジェクトの現在の警告セットのスナップショットを作成し、将来のインスペクションでスナップショットをベースラインとして使用すると、新しい問題のみをレポートできます。ベースライン スナップショットを使用すると、すべての既存の問題に戻って対処する手間をかけずに、lint でビルドエラーをチェックできます。
ベースライン スナップショットを作成するには、プロジェクトの build.gradle
ファイルを次のように変更します。
Groovy
android { lintOptions { baseline file("lint-baseline.xml") } }
Kotlin
android { lintOptions { baseline(file("lint-baseline.xml")) } }
初めてこの行を追加したとき、ベースラインを確立するために lint-baseline.xml
ファイルが作成されます。それ以降、ツールはベースラインを確認するためにファイルの読み取りのみを行います。新しいベースラインを作成する場合は、手動でファイルを削除し、lint を再度実行してファイルを再作成します。
次に、IDE([Analyze] > [Inspect Code])またはコマンドライン(下記を参照)から lint を実行します。出力に、lint-baseline.xml
ファイルの場所が表示されます。設定用のファイルの場所は、ここで示している例とは異なる場合があります。
$ ./gradlew lintDebug ... Wrote XML report to file:///app/lint-baseline.xml Created baseline file /app/lint-baseline.xml
lint
を実行すると、lint-baseline.xml
ファイルに現在の問題がすべて記録されます。現在の問題セットをベースラインと呼びます。ベースラインを他のユーザーと共有する場合は、lint-baseline.xml
ファイルをバージョン管理システムにチェックインします。
ベースラインをカスタマイズする
ベースラインに特定の問題タイプのみを追加する場合は、次のようにプロジェクトの build.gradle
を編集して、追加する問題タイプを指定します。
Groovy
android { lintOptions { checkOnly 'NewApi', 'HandlerLeak' baseline file("lint-baseline.xml") } }
Kotlin
android { lintOptions { checkOnly("NewApi", "HandlerLeak") baseline = file("lint-baseline.xml") } }
ベースラインの作成後、コードベースに新しい警告を追加すると、lint は新たに追加されたバグのみをリストします。
ベースライン警告
ベースラインを有効にした場合、問題がベースラインに含まれているために除外されたことを知らせる情報警告が表示されます。この警告が表示されるのは、ある時点ですべての問題を修正することが望ましいので、ベースラインが設定されていることをリマインドするためです。
この情報警告は、除外されたエラーと警告の正確な数を表示するだけでなく、今後レポートされない問題もトラッキングします。この情報により、実際に問題が修正されたかどうかがわかります。そのため、オプションでベースラインを再作成して、エラーが検出されずに復活するのを防ぐことができます。
注: ベースラインは、IDE でインスペクションをバッチモードで実行するときは有効になりますが、ファイルの編集時にバックグラウンドで実行されるエディタ内チェックでは無視されます。これは、ベースラインを使用するケースとして、コードベースに既存の警告が大量に存在し、コードの編集時にローカルで問題を修正する場合を想定しているためです。
手動でインスペクションを実行する
設定済みの lint とその他の IDE インスペクションを手動で実行するには、[Analyze] > [Inspect Code] を選択します。インスペクションの結果は [Inspection Results] ウィンドウに表示されます。
インスペクションのスコープとプロファイルを設定する
分析するファイル(インスペクション スコープ)と実行するインスペクション(インスペクション プロファイル)を選択する手順は次のとおりです。
- [Android] ビューでプロジェクトを開き、分析するプロジェクト、フォルダ、またはファイルを選択します。
- メニューバーから、[Analyze] > [Inspect Code] を選択します。
- [Specify Inspection Scope] ダイアログで、設定を確認します。
図 3. インスペクション スコープの設定を確認する
[Specify Inspection Scope] ダイアログに表示されるオプションの組み合わせは、プロジェクト、フォルダ、ファイルのどれを選択したかによって異なります。インスペクションの対象を変更するには、他のいずれかのラジオボタンを選択します。[Specify Inspection Scope] ダイアログに表示される可能性があるすべてのフィールドについては、Specify Inspection Scope ダイアログの説明をご覧ください。
- プロジェクト、ファイル、またはディレクトリを 1 つ選択すると、選択したプロジェクト、ファイル、またはディレクトリのパスが [Specify Inspection Scope] ダイアログに表示されます。
- 複数のプロジェクト、ファイル、またはディレクトリを選択すると、選択したファイルに対してオンになったラジオボタンが [Specify Inspection Scope] ダイアログに表示されます。
- [Inspection profile] は、デフォルトのプロファイル(Project Default)のままにします。
- [OK] をクリックして、インスペクションを実行します。図 4 は、[Inspect Code] から実行した lint および他の IDE インスペクションの結果を示しています。
図 4. 問題を選択して解決策を表示する
-
左ペインのツリービューで、エラーのカテゴリ、タイプ、問題を展開して選択し、インスペクション結果を表示します。
右ペインには、選択したエラーのカテゴリ、タイプ、または問題のインスペクション レポートが表示され、エラーの名前と場所が示されます。場合によっては、問題の解決に役立つ問題の概要などの情報もインスペクション レポートに表示されます。
- 左ペインのツリービューで、カテゴリ、タイプ、または問題を右クリックして、コンテキスト メニューを表示します。
コンテキストに応じて、各種の操作(ソースへのジャンプ、選択したアイテムの除外または追加、問題の無視、設定の編集、インスペクション アラートの管理、インスペクションの再実行)の全部または一部を実行できます。
左側のツールバー ボタン、コンテキスト メニュー項目、インスペクション レポートのフィールドの詳細については、[Inspection Tool] ウィンドウの説明をご覧ください。
カスタム スコープを使用する
Android Studio に用意されているカスタム スコープのいずれかを使用する手順は次のとおりです。
- [Specify Inspection Scope] ダイアログで、[Custom scope] をクリックします。
- [Custom scope] プルダウン リストをクリックして、オプションを表示します。
図 5. 使用するカスタム スコープを選択する
- [Project Files]: 現在のプロジェクト内のすべてのファイル。
- [Project Production Files]: 現在のプロジェクト内の製品版ファイルのみ。
- [Project Test Files]: 現在のプロジェクト内のテストファイルのみ。 テストのタイプと場所をご覧ください。
- [Open Files]: 現在のプロジェクト内の開いているファイルのみ。
- [Module <your-module>]: 現在のプロジェクト内の対応するモジュール フォルダ内のファイルのみ。
- [Current File]: 現在のプロジェクト内の現在のファイルのみ。1 つのファイルまたはフォルダを選択している場合にのみ表示されます。
- [Class Hierarchy]: これを選択して [OK] をクリックすると、現在のプロジェクト内のすべてのクラスを示すダイアログが開きます。そのダイアログの [Search by Name] フィールドを使用すると、検査するクラスを絞り込んで選択できます。クラスの絞り込みを行わないと、コード インスペクションによってすべてのクラスが検査されます。
- [OK] をクリックします。
カスタム スコープを作成する
現在使用可能なカスタム スコープのいずれも対応していないファイルとディレクトリを選択して検査するには、カスタム スコープを作成します。
- [Specify Inspection Scope] ダイアログで、[Custom scope] を選択します。
- [Custom Scope] プルダウン リストの横にあるその他メニューをクリックします。
図 6. [Specify Inspection Scope] ダイアログ
[Scopes] ダイアログが表示されます。
図 7. カスタム スコープを作成する
- 追加アイコン
をクリックして、新しいスコープを定義します。
- 表示された [Add Scope] プルダウン リストで、[Local] を選択します。
プロジェクト内では、ローカル スコープと共有スコープの両方がコード インスペクション機能に使用されます。共有スコープは、スコープ フィールドを含む他のプロジェクト機能でも使用できます。たとえば、[Find Usages] の設定を変更するために [Edit Settings]
をクリックすると表示されるダイアログには、共有スコープを選択できる [Scope] フィールドがあります。
図 8. [Find Usages] ダイアログで共有スコープを選択する
- スコープに名前を付けて、[OK] をクリックします。
[Scopes] ダイアログの右パネルに、カスタム スコープを定義するためのオプションが表示されます。
- プルダウン リストから、[Project] を選択します。
使用可能なプロジェクトのリストが表示されます。
注: プロジェクトまたはパッケージのカスタム スコープを作成できます。いずれの場合も手順は同じです。
- プロジェクト フォルダを展開し、カスタム スコープに追加するアイテムを選択して、右側にあるボタンのいずれかをクリックします。
図 9. カスタム スコープを定義する
- [Include]: このフォルダとその中のファイルを追加しますが、サブフォルダは追加しません。
- [Include Recursively]: このフォルダとその中のファイルに加えて、サブフォルダとその中のファイルを追加します。
- [Exclude]: このフォルダとその中のファイルを除外しますが、サブフォルダは除外しません。
- [Exclude Recursively]: フォルダとその中のファイルに加えて、サブフォルダとその中のファイルを除外します。
図 10 では、main フォルダが単独で追加され、java フォルダが再帰的に追加されています。青色は単独で追加されたフォルダを示し、緑色は再帰的に追加されたフォルダとファイルを示します。
図 10. カスタム スコープのパターンの例
- java フォルダを選択して [Exclude Recursively] をクリックすると、java フォルダと、その下のすべてのフォルダとファイルは、緑色でハイライト表示されなくなります。
- 緑色でハイライト表示された MainActivity.java ファイルを選択して [Exclude] をクリックすると、MainActivity.java は緑色でハイライト表示されなくなりますが、java フォルダの下の他のアイテムはすべて緑色でハイライト表示されます。
- [OK] をクリックすると、定義したカスタム スコープがプルダウン リストの一番下に表示されます。
インスペクション プロファイルを確認、編集する
Android Studio には、Android アップデートによって更新される lint およびその他のインスペクションのプロファイルが付属しています。これらのプロファイルはそのまま使用することもできますが、名前、説明、重大度、スコープを編集することもできます。プロファイルのグループ全体またはグループ内の個々のプロファイルを有効化または無効化することも可能です。
[Inspections] ダイアログにアクセスするには:
- [Analyze] > [Inspect Code] を選択します。
- [Specify Scope] ダイアログで、[Inspection Profile] の下にある [More] をクリックします。
サポートされているインスペクションとその説明を一覧表示する [Inspections] ダイアログが表示されます。
図 11. サポートされているインスペクションとその説明
- Default(Android Studio)インスペクションと Project Default(アクティブなプロジェクト)インスペクションを切り替えるには、[Profile] プルダウン リストを選択します。詳細については、IntelliJ の Specify Inspection Scope Dialog ページをご覧ください。
- 左ペインの [Inspections] ダイアログで、最上位レベルのプロファイル カテゴリを選択するか、グループを展開して特定のプロファイルを選択します。プロファイル カテゴリを選択すると、そのカテゴリに含まれているすべてのインスペクションを単一のインスペクションとして編集できます。
- インスペクションのコピー、名前の変更、説明の追加、エクスポート、インポートを行うには、[Manage] プルダウン リストを選択します。
- 完了したら、[OK] をクリックします。