Android NDK クラッシュ レポートを取得する

Android アプリにネイティブ ライブラリが含まれている場合は、アプリのビルド構成を少し変更するだけで、Firebase Crashlytics でネイティブ コードの完全なスタック トレースを行い、詳細なクラッシュ レポートを作成できます。

このガイドでは、NDK 用の Firebase Crashlytics SDK を使用してクラッシュ レポートを構成する方法について説明します。

Unity プロジェクトで Crashlytics の使用を開始する方法については、Unity スタートガイドをご覧ください。

始める前に

  1. まだ Firebase を Android プロジェクトに追加していない場合は追加します。Android アプリをお持ちでない場合は、サンプルアプリをダウンロードできます。

  2. 推奨: パンくずリストのログを自動的に取得して、クラッシュ イベント、非致命的イベント、ANR イベントに至るまでのユーザー操作を把握するには、Firebase プロジェクトで Google Analytics を有効にする必要があります。

    • 既存の Firebase プロジェクトで Google Analytics が有効になっていない場合は、Firebase コンソールで [] > [プロジェクトの設定] の [統合] タブGoogle Analytics を有効にします。

    • 新しい Firebase プロジェクトを作成する場合は、プロジェクトの作成ワークフローで Google Analytics を有効にします。

  3. アプリが次の最小バージョン要件を満たしていることを確認します。

    • Gradle 8.0
    • Android Gradle プラグイン 8.1.0
    • Google サービス Gradle プラグイン 4.4.1

ステップ 1: NDK 用の Crashlytics SDK をアプリに追加する

モジュール(アプリレベル)の Gradle ファイル(通常は <project>/<app-module>/build.gradle.kts または <project>/<app-module>/build.gradle)に、Android 用 Crashlytics NDK ライブラリの依存関係を追加します。ライブラリのバージョニングの制御には、Firebase Android BoM を使用することをおすすめします。

Crashlytics でのエクスペリエンスを最適化するために、Firebase プロジェクトで Google Analytics を有効にして、Google アナリティクス用の Firebase SDK をアプリに追加することをおすすめします。

dependencies {
    // Import the BoM for the Firebase platform
    implementation(platform("com.google.firebase:firebase-bom:33.9.0"))

    // Add the dependencies for the Crashlytics NDK and Analytics libraries
    // When using the BoM, you don't specify versions in Firebase library dependencies
    implementation("com.google.firebase:firebase-crashlytics-ndk")
    implementation("com.google.firebase:firebase-analytics")
}

Firebase Android BoM を使用すると、アプリは常に互換性のあるバージョンの Firebase Android ライブラリを使用します。

Firebase BoM を使用しない場合は、依存関係の行でそれぞれの Firebase ライブラリのバージョンを指定する必要があります。

アプリで複数の Firebase ライブラリを使用する場合は、すべてのバージョンの互換性を確保するため、BoM を使用してライブラリのバージョンを管理することを強くおすすめします。

dependencies {
    // Add the dependencies for the Crashlytics NDK and Analytics libraries
    // When NOT using the BoM, you must specify versions in Firebase library dependencies
    implementation("com.google.firebase:firebase-crashlytics-ndk:19.4.0")
    implementation("com.google.firebase:firebase-analytics:22.2.0")
}
Kotlin 固有のライブラリ モジュールをお探しの場合、 2023 年 10 月(Firebase BoM 32.5.0)以降、Kotlin と Java のどちらのデベロッパーもメイン ライブラリ モジュールを利用できるようになります(詳しくは、このイニシアチブに関するよくある質問をご覧ください)。

ステップ 2: アプリに Crashlytics Gradle プラグインを追加する

  1. ルートレベル(プロジェクト レベル)の Gradle ファイル(<project>/build.gradle.kts または <project>/build.gradle)で、Crashlytics Gradle プラグインを plugins ブロックに追加します。

    KotlinGroovy
    plugins {
        // Make sure that you have the AGP plugin 8.1+ dependency
        id("com.android.application") version "8.1.4" apply false
        // ...
    
        // Make sure that you have the Google services Gradle plugin 4.4.1+ dependency
        id("com.google.gms.google-services") version "4.4.2" apply false
    
        // Add the dependency for the Crashlytics Gradle plugin
        id("com.google.firebase.crashlytics") version "3.0.3" apply false
    }
    plugins {
        // Make sure that you have the AGP plugin 8.1+ dependency
        id 'com.android.application' version '8.1.4' apply false
        // ...
    
        // Make sure that you have the Google services Gradle plugin 4.4.1+ dependency
        id 'com.google.gms.google-services' version '4.4.2' apply false
    
        // Add the dependency for the Crashlytics Gradle plugin
        id 'com.google.firebase.crashlytics' version '3.0.3' apply false
    }
  2. モジュール(アプリレベル)の Gradle ファイル(通常は <project>/<app-module>/build.gradle.kts または <project>/<app-module>/build.gradle)に、Crashlytics Gradle プラグインを追加します。

    KotlinGroovy
    plugins {
      id("com.android.application")
      // ...
    
      // Make sure that you have the Google services Gradle plugin
      id("com.google.gms.google-services")
    
      // Add the Crashlytics Gradle plugin
      id("com.google.firebase.crashlytics")
    }
    plugins {
      id 'com.android.application'
      // ...
    
      // Make sure that you have the Google services Gradle plugin
      id 'com.google.gms.google-services'
    
      // Add the Crashlytics Gradle plugin
      id 'com.google.firebase.crashlytics'
    }

ステップ 3: ビルドに Crashlytics 拡張機能を追加する

モジュール(アプリレベル)の Gradle ファイル(通常は <project>/<app-module>/build.gradle.kts または <project>/<app-module>/build.gradle)で、Crashlytics 拡張機能を構成します。

KotlinGroovy
import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension

// ...

android {
  // ...
  buildTypes {
      getByName("release") {
          // Add this extension
          configure<CrashlyticsExtension> {
              // Enable processing and uploading of native symbols to Firebase servers.
              // By default, this is disabled to improve build speeds.
              // This flag must be enabled to see properly-symbolicated native
              // stack traces in the Crashlytics dashboard.
              nativeSymbolUploadEnabled = true
          }
      }
  }
}
// ...

android {
  // ...
  buildTypes {
      release {
          // Add this extension
          firebaseCrashlytics {
              // Enable processing and uploading of native symbols to Firebase servers.
              // By default, this is disabled to improve build speeds.
              // This flag must be enabled to see properly-symbolicated native
              // stack traces in the Crashlytics dashboard.
              nativeSymbolUploadEnabled true
          }
      }
  }
}

ステップ 4: ネイティブ シンボルの自動アップロードを設定する

NDK のクラッシュから読み取り可能なスタック トレースを生成するには、ネイティブ バイナリ内のシンボルを Crashlytics に知らせる必要があります。Crashlytics Gradle プラグインには、このプロセスを自動化する uploadCrashlyticsSymbolFileBUILD_VARIANT タスクが含まれています。

  1. 自動シンボル アップロードのタスクにアクセスするには、モジュール(アプリレベル)の Gradle ファイルで nativeSymbolUploadEnabledtrue に設定されていることを確認してください。

  2. スタック トレースにメソッド名を含めるには、NDK ライブラリをビルドするたびに uploadCrashlyticsSymbolFileBUILD_VARIANT タスクを明示的に呼び出す必要があります。例:

    >./gradlew app:assembleBUILD_VARIANT\
               app:uploadCrashlyticsSymbolFileBUILD_VARIANT
  3. NDK 用の Crashlytics SDK と Crashlytics Gradle プラグインは両方とも、ネイティブ共有オブジェクト内の GNU ビルド ID の存在に依存しています。

    この ID の存在を確認するには、各バイナリに対して readelf -n を実行します。このビルド ID が存在しない場合は、ビルドシステムのフラグに -Wl,--build-id を追加することで問題を解決できます。

ステップ 5: 強制的にテスト クラッシュを発生させて設定を完了する

Crashlytics の設定を完了し、Firebase コンソールの Crashlytics ダッシュボードで最初のデータを確認するには、強制的にテスト クラッシュを発生させる必要があります。

  1. 強制的にテスト クラッシュを発生させるためのコードをアプリに追加します。

    アプリの MainActivity で次のコードを使用するとアプリにボタンが追加され、このボタンを押すとクラッシュを発生させることができます。ボタンには「Test Crash」というラベルが付いています。

    KotlinJava
    val crashButton = Button(this)
    crashButton.text = "Test Crash"
    crashButton.setOnClickListener {
       throw RuntimeException("Test Crash") // Force a crash
    }
    
    addContentView(crashButton, ViewGroup.LayoutParams(
           ViewGroup.LayoutParams.MATCH_PARENT,
           ViewGroup.LayoutParams.WRAP_CONTENT))
    Button crashButton = new Button(this);
    crashButton.setText("Test Crash");
    crashButton.setOnClickListener(new View.OnClickListener() {
       public void onClick(View view) {
           throw new RuntimeException("Test Crash"); // Force a crash
       }
    });
    
    addContentView(crashButton, new ViewGroup.LayoutParams(
           ViewGroup.LayoutParams.MATCH_PARENT,
           ViewGroup.LayoutParams.WRAP_CONTENT));
  2. アプリをビルドして実行します。

  3. アプリの最初のクラッシュ レポートを送信するために、強制的にテスト クラッシュを発生させます。

    1. テスト用のデバイスまたはエミュレータからアプリを開きます。

    2. アプリ内で、上述のコードを使用して追加した [Test Crash] ボタンを押します。

    3. アプリがクラッシュしたら再起動します。これにより、Firebase にクラッシュ レポートが送信されます。

  4. Firebase コンソールの Crashlytics ダッシュボードに移動して、テスト クラッシュを確認します。

    コンソールを更新し、5 分経過してもテスト クラッシュが表示されない場合は、デバッグ ロギングを有効にして、アプリがクラッシュ レポートを送信しているかどうかを確認してください。


これで完了です。これで Crashlytics がアプリのクラッシュをモニタリングするようになったため、Crashlytics ダッシュボードでクラッシュ レポートと統計情報を確認、調査できます。

次のステップ

  • (推奨) GWP-ASan レポートを収集すると、ネイティブ メモリエラーに起因するクラッシュのデバッグに役立つ情報が得られます。 このようなメモリ関連のエラーは、アプリのセキュリティの脆弱性の主な原因である、アプリ内のメモリ破損に関連している可能性があります。このデバッグ機能を使用するには、アプリで GWP-ASan を明示的に有効にするとともに、最新の Crashlytics SDK for NDK(v18.3.6 以降または Firebase BoM v31.3.0 以降)を使用してください。

  • クラッシュ レポートの設定をカスタマイズするために、オプトイン レポート、ログ、キー、致命的でないエラーの追跡を追加する。

  • Android アプリのクラッシュ レポートを Crashlytics ダッシュボードから直接 Google Play トラックでフィルタリングできるように、Google Play と統合する。これにより、ダッシュボードで特定のビルドに注目できます。

トラブルシューティング

Firebase コンソールのスタック トレースと logcat のスタック トレースが一致しない場合は、トラブルシューティング ガイドをご覧ください。



シンボルをアップロードするための代替オプション

このページの前述のメイン ワークフローは、標準の Gradle ビルドに適用できます。ただし、アプリによっては、別の構成やツール(Gradle 以外のビルドプロセスなど)を使用する場合があります。そのような場合は、以下のオプションを使用してシンボルをアップロードできる可能性があります。

オプション: ライブラリ モジュールと外部依存関係のシンボルをアップロードする

このオプションは次のような場合に役立ちます。

  • カスタマイズした NDK ビルドプロセスを Gradle 内で使用する場合
  • ネイティブ ライブラリがライブラリ / 機能モジュール内でビルドされている場合、またはサードパーティによって提供されている場合
  • 自動シンボル アップロード タスクが失敗する場合、またはシンボリケートされていないクラッシュがダッシュボードに表示される場合

標準的な Crashlytics シンボルのアップロード タスクは、CMake などの標準的な NDK ビルドツールを使用して、アプリ モジュールの Gradle ビルドの一環としてネイティブ ライブラリをビルドすることを前提としています。

カスタマイズした NDK のビルドプロセスを Gradle 内で使用している場合、またはネイティブ ライブラリがライブラリ / 機能モジュール内でビルドされている場合、またはネイティブ ライブラリがサードパーティによって提供されている場合は、ストリップされていないライブラリへのパスを明示的に指定しなければならない場合があります。これを行うには、Gradle ビルドファイルの Crashlytics 拡張機能に unstrippedNativeLibsDir プロパティを追加します。

  1. このページの前述のメイン ワークフローに記載されている次の初期タスクが完了していることを確認してください。

    1. Firebase コンソールで Crashlytics を有効にした。

    2. Crashlytics SDK for NDKCrashlytics Gradle プラグインを追加しました。

    3. ビルドに Crashlytics 拡張機能を追加した。

    4. ネイティブ シンボルの自動アップロードを設定した。

  2. 自動シンボル アップロード タスクでシンボル情報を検出できるように、モジュール(アプリレベル)の Gradle ファイル(通常は <project>/<app-module>/build.gradle.kts または <project>/<app-module>/build.gradle)に次の設定を追加します。

    KotlinGroovy
    import com.google.firebase.crashlytics.buildtools.gradle.CrashlyticsExtension
    
    // ...
    
    android {
        // ...
        buildTypes {
            release {
                configure<CrashlyticsExtension> {
                    nativeSymbolUploadEnabled = true
                    unstrippedNativeLibsDir = file("PATH/TO/UNSTRIPPED/DIRECTORY")
                }
            }
        }
    }
    // ...
    
    android {
        // ...
        buildTypes {
            release {
                firebaseCrashlytics {
                    nativeSymbolUploadEnabled true
                    unstrippedNativeLibsDir file("PATH/TO/UNSTRIPPED/DIRECTORY")
                }
            }
        }
    }

    Crashlytics プラグインは、.so 拡張子を含むネイティブ ライブラリを、指定したディレクトリ内で再帰的に検索します。Crashlytics は、そのようなすべてのライブラリからデバッグ シンボルを抽出し、Firebase サーバーにアップロードします。

    unstrippedNativeLibsDir プロパティで指定できる内容を以下に示します。

    • org.gradle.api.Project#files(Object...) に使用できる任意の引数(java.lang.Stringjava.io.Fileorg.gradle.api.file.FileCollection など)

    • 1 つのビルド フレーバー用の複数のディレクトリ。リストまたは FileCollection インスタンスを指定します。

    • Crashlytics Gradle プラグイン v3.0.0 以降)個別のプロダクトとビルド フレーバーに複数のディレクトリを蓄積します。

      buildTypes {
        release {
          configure<CrashlyticsExtension> {
            nativeSymbolUploadEnabled = true
            unstrippedNativeLibsDir = file("MY/NATIVE/LIBS")
          }
        }
        productFlavors {
          flavorDimensions += "feature"
          create("basic") {
            dimension = "feature"
            // ...
          }
          create("featureX") {
            dimension = "feature"
            configure<CrashlyticsExtension> {
              unstrippedNativeLibsDir = file("MY/FEATURE_X/LIBS")
            }
          }
        }
      }
      

    uploadCrashlyticsSymbolFilesBasicRelease タスクは MY/NATIVE/LIBS のシンボルのみをアップロードしますが、uploadCrashlyticsSymbolFilesFeatureXReleaseMY/NATIVE/LIBSMY/FEATURE_X/LIBS の両方のシンボルをアップロードします。

  3. 最後に、強制的にテスト クラッシュを発生させて Crashlytics の設定を完了し、Firebase コンソールの Crashlytics ダッシュボードで最初のデータを確認します。

オプション: Gradle 以外のビルドのシンボル、またはストリップされておらずアクセスできないネイティブ ライブラリのシンボルをアップロードする

このオプションは次のような場合に役立ちます。

  • Gradle 以外のビルドプロセスを使用する場合

  • ストリップされていないネイティブ ライブラリが提供されていて、Gradle ビルド中にアクセスできない場合

このオプションでは、リリースビルドを作成する際や、Firebase コンソールでシンボリケートされたスタック トレースを表示するビルドを作成する際に、Firebase CLI コマンドを実行する必要があります。

  1. このページの前述のメイン ワークフローに記載されている次の初期タスクが完了していることを確認してください。

    1. Firebase コンソールで Crashlytics を有効にした。

    2. Crashlytics SDK for NDKCrashlytics Gradle プラグインを追加しました。

    このオプションでは、firebaseCrashlytics 拡張機能を追加したり、自動シンボル アップロードを設定したりする必要はありません。代わりに、Firebase CLI(以下の手順を参照)を使用して、シンボル ファイルの生成とアップロードを行います。

  2. シンボルをアップロードするための環境設定とプロジェクト設定を行います。

    1. 手順に沿って Firebase CLI をインストールします。

      すでに CLI がインストールされている場合は、最新バージョンに更新してください。

    2. (Android API レベル 30 以上を使用するアプリの場合のみ)アプリの AndroidManifest.xml テンプレートを更新して、ポインタのタグ付けを無効にします。

      1. [Android Player Settings] > [Publishing Settings] > [Build] > [Custom Main Manifest] チェックボックスをオンにします。

      2. Assets/Plugins/Android/AndroidManifest.xml にあるマニフェスト テンプレートを開きます。

      3. アプリケーション タグに次の属性を追加します: <application android:allowNativeHeapPointerTagging="false" ... />

  3. プロジェクトをビルドします。

  4. シンボル情報をアップロードします。

    ビルドが完了したら、次の Firebase CLI コマンドを実行して、Crashlytics 互換のシンボル ファイルを生成し、Firebase サーバーにアップロードします。

    firebase crashlytics:symbols:upload --app=FIREBASE_APP_ID PATH/TO/SYMBOLS
    • FIREBASE_APP_ID: Firebase Android アプリ ID(パッケージ名ではありません)
      Firebase Android アプリ ID の例: 1:567383003300:android:17104a2ced0c9b9b

      次の 2 つの方法で Firebase アプリ ID を確認することができます。

      • google-services.json ファイル内の mobilesdk_app_id の値がアプリ ID です。

      • Firebase コンソールで、[プロジェクトの設定] に移動します。下にスクロールして [マイアプリ] カードを表示し、目的の Firebase アプリをクリックしてアプリ ID を確認します。

    • PATH/TO/SYMBOLS: CLI によって生成されたシンボル ファイルのパス

      • Android Studio プロジェクトにエクスポートされた場合: PATH/TO/SYMBOLS はディレクトリです。Firebase CLI は、.so 拡張子を含むネイティブ ライブラリを、指定したディレクトリ内で再帰的に検索します。

      • Unity から直接 APK をビルドした場合: PATH/TO/SYMBOLS は、ビルドが完了した際に、プロジェクトのルート ディレクトリに生成される、圧縮されたシンボル ファイルのパスです(例: myproject/myapp-1.0-v100.symbols.zip)。

    フラグ 説明
    --generator=csym

    デフォルトの Breakpad ジェネレーターではなく、古い cSYM シンボル ファイル ジェネレーターを使用します。

    このオプションの使用は推奨されません。デフォルトの Breakpad シンボル ファイル ジェネレーターを使用することをおすすめします。

    --generator=breakpad

    Breakpad シンボル ファイル ジェネレーターを使用します。

    デフォルトのシンボル ファイル生成は Breakpad です。このフラグは、ビルド構成に symbolGenerator { csym() } を追加したが、それをオーバーライドして Breakpad を使用する場合のみ使用します。

    --dry-run

    シンボル ファイルを生成するがアップロードは行いません。

    このフラグは、送信されるファイルの内容を調べる場合に役立ちます。

    --debug 追加のデバッグ情報が提供される
  5. 最後に、強制的にテスト クラッシュを発生させて Crashlytics の設定を完了し、Firebase コンソールの Crashlytics ダッシュボードで最初のデータを確認します。

    強制的にクラッシュを発生させる処理の中でアプリのビルドを行った後に、Firebase CLI の crashlytics:symbols:upload コマンドを実行して、シンボル ファイルをアップロードしてください。