Lint チェックでコードを改善する

テストを作成してアプリが機能要件を満たしていることを確認するのは重要ですが、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:lint
    Ran lint on variant release: 5 issues found
    Ran lint on variant debug: 5 issues found
    Wrote HTML report to file:<path-to-project>/app/build/reports/lint-results.html
    Wrote XML report to file:<path-to-project>/app/build/reports/lint-results.xml
    

Lint ツールによるチェックが完了すると、Lint レポートの XML バージョンおよび HTML バージョンのパスが表示されます。図 2 に示すように、HTML レポートに移動してブラウザで開くことができます。

図 2. HTML 版 Lint レポートの例

プロジェクトにビルド バリアントが含まれている場合、特定のビルド バリアントに対してのみ lint タスクを実行するには、バリアント名の頭文字を大文字にして、lint 接頭辞を付けます。

    gradlew lintDebug
    

コマンドラインから Gradle タスクを実行する方法については、コマンドラインからアプリをビルドするをご覧ください。

スタンドアロン ツールで Lint を実行する

Android Studio または Gradle を使用していない場合は、SDK Manager から Android SDK Tools をインストールすると、スタンドアロンの Lint ツールを使用できます。Lint ツールは android_sdk/tools/ ディレクトリで見つけられます。

プロジェクト ディレクトリにあるファイルのリストに対して 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 つ(ManifestOrderUsesMinSdkAttributesUnusedResources)はプロジェクトの AndroidManifest.xml ファイルに関するもので、1 つ(IconMissingDensityFolder)は Preferences.xml レイアウト ファイルに関するものです。

Lint の設定により警告を抑制する

デフォルトでは、Lint スキャンを実行すると、Lint がサポートする問題がすべてチェックされますが、Lint でチェックする問題を限定したり、問題の重大度を指定したりすることもできます。たとえば、プロジェクトと無関係な特定の問題に対する Lint チェックを無効にする、重要でない問題を Lint がレポートする際の重大度を下げるなどです。

次に示すさまざまなレベルで Lint チェックを設定できます。

  • グローバル(プロジェクト全体)
  • プロジェクト モジュール
  • 製品版モジュール
  • テスト モジュール
  • 開いているファイル
  • クラス階層
  • バージョン管理システム(VCS)のスコープ

Android Studio で Lint を設定する

Android Studio を使用している場合は、組み込みの Lint ツールによってコードがチェックされます。次の 2 つの方法で警告とエラーを表示できます。

  • コードエディタ内のポップアップ テキスト。Lint が問題を検出すると、問題のあるコードが黄色で強調表示されます。重大な問題の場合は、コードに赤い下線が表示されます。
  • Lint の [Inspection Results] ウィンドウで、[Analyze] > [Inspect Code] をクリックします。手動でインスペクションを実行するをご覧ください。

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 ファイルの lintOptions {} ブロックで、実行するチェックや無視するチェックなど、特定の Lint オプションを設定できます。次のコード スニペットは、設定可能なプロパティの一部を示しています。

    android {
      ...
      lintOptions {
        // 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.
        check '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
      }
    }
    ...
    

警告ベースラインを作成する

プロジェクトの現在の警告セットのスナップショットを作成し、将来のインスペクションでスナップショットをベースラインとして使用して、新しい問題のみがレポートされるようにすることができます。ベースライン スナップショットを使用すると、すべての既存の問題に戻って対処する手間をかけずに、Lint でビルドエラーをチェックできます。

ベースライン スナップショットを作成するには、プロジェクトの build.gradle ファイルを次のように変更します。

    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 を編集して、追加する問題タイプを指定できます。

    android {
      lintOptions {
        check 'NewApi', 'HandlerLeak'
        baseline file("lint-baseline.xml")
       }
    }
    

ベースラインの作成後、コードベースに新しい警告を追加すると、Lint は新たに追加されたバグの一覧のみをレポートします。

ベースライン警告

ベースラインを有効にした場合、1 つ以上の問題がベースラインに含まれているために除外されたことを知らせる情報警告が表示されます。この警告が表示されるのは、ベースラインを設定したことをリマインドするためです。理想的には、ある時点ですべての問題を解決する必要があるからです。

この情報警告は、除外されたエラーと警告の正確な数を表示するだけでなく、今後レポートされない問題もトラッキングします。この情報により、実際に問題が修正されたかどうかがわかります。そのため、オプションでベースラインを再作成して、エラーが検出されずに復活するのを防ぐこともできます。

注: ベースラインは、IDE でインスペクションをバッチモードで実行するときは有効になりますが、ファイルの編集時にバックグラウンドで実行されるエディタ内チェックでは無視されます。これは、ベースラインを使用するケースとして、コードベースに既存の警告が大量に存在し、コードの編集時にローカルで問題を修正する場合を想定しているためです。

手動でインスペクションを実行する

設定済みの Lint とその他の IDE インスペクションを手動で実行するには、[Analyze] > [Inspect Code] を選択します。インスペクションの結果は [Inspection Results] ウィンドウに表示されます。

インスペクションのスコープとプロファイルを設定する

分析するファイル(インスペクション スコープ)と実行するインスペクション(インスペクション プロファイル)を選択するには、次の手順に従います。

  1. [Android] ビューでプロジェクトを開き、分析するプロジェクト、フォルダ、またはファイルを選択します。
  2. メニューバーから、[Analyze] > [Inspect Code] を選択します。
  3. [Specify Inspection Scope] ダイアログで、設定を確認します。 インスペクション スコープの指定

    図 3. インスペクション スコープの設定を確認する

    [Specify Inspection Scope] ダイアログに表示されるオプションの組み合わせは、プロジェクト、フォルダ、ファイルのどれを選択したかによって異なります。インスペクションの対象を変更するには、他のいずれかのラジオボタンを選択します。[Specify Inspection Scope] ダイアログに表示される可能性があるすべてのフィールドを確認するには、[Specify Inspection Scope] ダイアログの説明をご覧ください。

    • プロジェクト、ファイル、またはディレクトリを 1 つ選択すると、選択したプロジェクトファイル、またはディレクトリのパスが [Specify Inspection Scope] ダイアログに表示されます。
    • 複数のプロジェクト、ファイル、またはディレクトリを選択すると、選択したファイルに対してオンになったラジオボタンが [Specify Inspection Scope] ダイアログに表示されます。
  4. [Inspection profile] は、デフォルトのプロファイル(Project Default)のままにします。
  5. [OK] をクリックして、インスペクションを実行します。図 4 は、[Inspect Code] から実行された Lint とその他の IDE インスペクションの結果を示しています。

    図 4. 問題を選択して解決策を表示する

  6. 左ペインのツリービューで、エラーのカテゴリ、タイプ、問題を展開して選択し、インスペクション結果を表示します。

    右ペインには、選択したエラーのカテゴリ、タイプ、または問題のインスペクション レポートが表示され、エラーの名前と場所が示されます。場合によっては、問題の解決に役立つ問題の概要などの情報もインスペクション レポートに表示されます。

  7. 左ペインのツリービューで、カテゴリ、タイプ、または問題を右クリックして、コンテキスト メニューを表示します。

    コンテキストに応じて、各種の操作(ソースへのジャンプ、選択したアイテムの除外または追加、問題の無視、設定の編集、インスペクション アラートの管理、インスペクションの再実行)の全部または一部を実行できます。

左側のツールバー ボタン、コンテキスト メニュー、インスペクション レポートのフィールドの詳細については、[Inspection Tool] ウィンドウの説明をご覧ください。

カスタム スコープを使用する

Android Studio に用意されているカスタム スコープのいずれかを使用するには、次の手順に従います。

  1. [Specify Inspection Scope] ダイアログで、[Custom scope] をクリックします。
  2. [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] フィールドを使用すると、検査するクラスを絞り込んで選択できます。クラスの絞り込みを行わないと、コード インスペクションによってすべてのクラスが検査されます。
  3. [OK] をクリックします。

カスタム スコープを作成する

現在使用可能ないずれのカスタム スコープも対応していないファイルやディレクトリを選択して検査するには、カスタム スコープを作成します。

  1. [Specify Inspection Scope] ダイアログで、[Custom scope] を選択します。
  2. [Custom Scope] プルダウン リストの横にある 3 つのドットをクリックします。

    図 6. [Specify Inspection Scope] ダイアログ

    [Scopes] ダイアログが表示されます。

    図 7. カスタム スコープを作成する

  3. [Add] をクリックして、新しいスコープを定義します。
  4. 表示された [Add Scope] プルダウン リストで、[Local] を選択します。

    プロジェクト内では、ローカル スコープと共有スコープの両方がコード インスペクション機能に使用されます。共有スコープは、スコープ フィールドを設定できる含む他のプロジェクト機能でも使用できます。たとえば、[Find Usages] の設定を変更するために [Edit Settings] をクリックすると表示されるダイアログには、共有スコープを選択できる [Scope] フィールドがあります。

    図 8. [Find Usages] ダイアログで共有スコープを選択する

  5. スコープに名前を付けて、[OK] をクリックします。

    [Scopes] ダイアログの右ペインに、カスタム スコープを定義するためのオプションが表示されます。

  6. プルダウン リストから、[Project] を選択します。

    使用可能なプロジェクトのリストが表示されます。

    注: プロジェクトまたはパッケージのカスタム スコープを作成できます。いずれの場合も手順は同じです。

  7. プロジェクト フォルダを展開し、カスタム スコープに追加するアイテムを選択して、右側にあるボタンのいずれかをクリックします。

    図 9. カスタム スコープを定義する

    • [Include]: このフォルダとその中のファイルを追加しますが、サブフォルダは追加しません。
    • [Include Recursively]: このフォルダとその中のファイルに加えて、サブフォルダとその中のファイルを追加します。
    • [Exclude]: このフォルダとその中のファイルを除外しますが、サブフォルダは除外しません。
    • [Exclude Recursively]: フォルダとその中のファイルに加えて、サブフォルダとその中のファイルを除外します。

    図 10 では、main フォルダがサブフォルダ抜きで追加され、java フォルダが再帰的に追加されています。青色はサブフォルダ抜きで追加されたフォルダを示し、緑色は再帰的に追加されたフォルダとファイルを示します。

    図 10. カスタム スコープのパターンの例

    • java フォルダを選択して [Exclude Recursively] をクリックすると、java フォルダと、その下のすべてのフォルダとファイルは、緑色で強調表示されなくなります。
    • 緑色で強調表示された MainActivity.java ファイルを選択して [Exclude] をクリックすると、MainActivity.java は緑色で強調表示されなくなりますが、java フォルダの下の他のアイテムはすべて緑色で強調表示されます。
  8. [OK] をクリックします。定義したカスタム スコープがプルダウン リストの一番下に表示されます。

インスペクション プロファイルの確認と編集

Android Studio には、Lint およびその他のインスペクション プロファイルがいくつか付属しており、それらは Android アップデートによって更新されます。これらのプロファイルはそのまま使用することもできますが、名前、説明、重大度、スコープを編集することもできます。プロファイルのグループ全体またはグループ内の個々のプロファイルを有効化または無効化することも可能です。

[Inspections] ダイアログにアクセスするには:

  1. [Analyze] > [Inspect Code] を選択します。
  2. [Specify Scope] ダイアログで、[Inspection Profile] の下にある [More] をクリックします。

    サポートされているインスペクションとその説明のリストを示す [Inspections] ダイアログが開きます。

    図 11. サポートされているインスペクションとその説明

  3. Default(Android Studio)インスペクションと Project Default(アクティブなプロジェクト)インスペクションを切り替えるには、[Profile] プルダウン リストを選択します。詳細については、IntelliJ の [Specify Inspection Scope] ダイアログのページをご覧ください。
  4. 左ペインの [Inspections] ダイアログで、最上位レベルのプロファイル カテゴリを選択するか、グループを展開して特定のプロファイルを選択します。プロファイル カテゴリを選択すると、そのカテゴリに含まれているすべてのインスペクションを、単一のインスペクションとして編集できます。
  5. インスペクションのコピー、名前の変更、説明の追加、エクスポート、インポートを行うには、[Manage] プルダウン リストを選択します。
  6. 完了したら、[OK] をクリックします。