Firebase CrashlyticsをXamarin.Formsアプリで使ってみたら色々と難ありだった


これは Xamarin Advent Calendar 2018 の4日目の記事です。

Firebaseの Crashlytics が使えるようになったとのことで、Xamarin.Formsなアプリに導入してみました。結構手こずったため試行錯誤が足りずイマイチ正解が見えていませんが、動いたので共有します。

対象

新規作成したXamarin.Formsプロジェクト。
(Formsは最新に更新)

環境

検証したのが11月末のため、記事公開時点でVisual Studioは1個前のバージョンです。

コンポーネント バージョン
macOS Mojave(10.14.1)
Visual Studio for Mac 7.6.11 (build 9)
Xcode 10.1
Xamarin.iOS 12.2.1.10
Android SDK Tools 26.1.1
Android SDK Platform-Tools 28.0.0
Android SDK Build Tools 28.0.2
Android SDK 8.1
Java SDK 1.8.0_192
Xamarin.Android 9.0.0.20

準備

明日の @f-miyu さんがFirebaseを使うあたりのことを書かれるとのことで、ざくっと言うと
1. FirebaseのコンソールでiOS、Androidそれぞれのアプリプロジェクトを作成する
2. plistやjsonの定義ファイルをダウンロードし、プロジェクトに組み込む
3. iOS、AndroidそれぞれのプロジェクトにFirebase.CoreなNugetパッケージを組み込む
4. アプリを起動する
という感じです。アプリを起動したときFirebaseに(たぶんAnalyticsの)情報が届くと、Firebaseコンソールのほうで導入が成功した表示がされます。

ここまで来たら、FirebaseのコンソールでそれぞれのプロジェクトからCrashlyticsを有効にします。

ここまできたら、いよいよ本番です。

Xamarin.Formsの画面にボタンを追加して押したら例外をスローするようにする

動作確認用のクラッシュとして単に例外をスローしてみます。

MainPage.xaml
<Button Text="Crash!" Clicked="OnClickedCrash" />
MainPage.xaml.cs
void OnClickedCrash(object sender, System.EventArgs e)
{
    throw new InvalidOperationException("Hello Crashlytics!");
}

「Crash!」ボタンを押すとクラッシュしますが、当然ながらまだCrashlyticsには何も届きません。

ちなみにCrasylyticsには動作確認用のCrashメソッドが用意されているためこれを使っても良かったのですが、これをFormsから呼ぶにはDependencyServiceを経由しないといけないし、ネイティブでのクラッシュになり話がややこしくなるため今回は手抜きです。

Xamarin.FormsのiOSアプリにCrashyticsを導入する

公式ドキュメントGet Started with Firebase Crashlytics for iOSを参考にしましたが、なぜか色々と違いました。

iOSプロジェクトは以下のようにしました。

  1. Xamarin.Firebase.iOS.Crashlyticsを追加する
  2. AppDelegate.csのFinishedLaunchingにCrashlyticsの初期化を追加する
  3. Xamarin.Firebase.iOS.Analyticsの4.0.5を追加する
  4. AppDelegate.csのFinishedLaunchingにFirebase.Coreの初期化を追加する

1と2のみで動く・・・と予想していたのですが、ハマったところはこのあたりです。

  • Xamarin.Firebase.iOS.Analyticsを追加せずにXamarin.Firebase.iOS.Crashlyticsのみの場合
    • クラッシュさせてもCrashlyticsのコンソールに届きませんでした。
    • クラッシュ→アプリ再起動、で通常はクラッシュログが送信されます。
  • Xamarin.Firebase.iOS.Analyticsを追加した(=最新の5.1.4)場合
  • 初期化コードがCrashlyticsのみの場合
    • クラッシュさせてもCrashlyticsのコンソールに届きませんでした。

Xamarin.Firebase.iOS.Crashlyticsの依存関係には改善の余地があるのかも、と思っています。

初期化コードはこうなりました。

MainPage.xaml.cs
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    Firebase.Core.App.Configure();
    Firebase.Crashlytics.Crashlytics.Configure();

    // :(以下、元のコード)
}

これでアプリを起動してしばらくすると、何か初期化が届くのかFirebaseのコンソール(虫網ボーイの表示)がこうなります。

Xamarin.FormsのiOSアプリから送信されたクラッシュログの例

このようなメールが届きます。
MainPage.xaml.csに書いた「Crash!」ボタンによるInvalidOperationExceptionということは全然想像が付きません。

でも詳細を見るとスタックトレースには現れていました。

よかったよかった。

・・・だけど「ログ」が空です。

Analyticsによる画面遷移の記録が載るはず、と思っていたのですがFormsはPageだからキビしかったかな・・・?(自力でFirebase Analyticsで画面名を送信する対応が必要になります)

Xamarin.FormsのAndroidアプリにCrashyticsを導入する

公式ドキュメントはこちら

Androidプロジェクトは以下のようにしました。
結構色々とワケ分からん感じでした。

  1. Xamarin.Android.Crashlyticsを追加する
  2. MainActivity.csのOnCreateにCrashlyticsの初期化を追加する
  3. 足りないライブラリを追加する
    • Xamarin.Android.Crashlytics.Answers
    • Xamarin.Android.Crashlytics.Beta
    • Xamarin.Android.Crashlytics.Core
    • Xamarin.Firebase.Core
    • これらを入れないと何かが足りないからとアプリが起動しませんでした。そういうもの…?。
  4. Xamarin.Build.Downloadを0.4.12-preview3に上げる
  5. strings.xmlにcom.crashlytics.android.build_idを追加する
  6. AndroidManifest.xmlにfirebase_crashlytics_collection_enabled(=false)を追加する
  7. アプリを起動する
  8. AndroidManifest.xmlのfirebase_crashlytics_collection_enabledをtrueに変更する
  9. アプリを起動する

5をしないと、落ちます(例外忘れた)。

6(と7)を飛ばすと、このようなエラーで落ちます。

E AndroidRuntime: io.fabric.sdk.android.services.concurrency.UnmetDependencyException: This app relies on Crashlytics. Please sign up for access at https://fabric.io/sign_up,
E AndroidRuntime: install an Android build tool and ask a team member to invite you to this app's organization.

まさか今さら登録が必要なのか?と思ったのですが、特にFabricのサイトを使う必要はなかったです。

Xamarin.FormsのAndroidアプリから送信されたクラッシュログの例

このようなメールが届きます。
そのファイル名はForms側なのでは、と思ってしまいます。

詳細が思ったような感じではありませんが・・・

よく見ると、それっぽい事が書いてありました。
行番号がないので少し不安です。

ログも1つ出ていました。
ただ結局PageではMainActivityのままなので、画面名は送信しないといけないでしょうね。

参考:普通のAndroidアプリでクラッシュさせたログ

Android Studioで普通に作ったアプリからCrashlyticsのテスト用API、crash()で落とした時のログです。


↑これが、こう↓

行番号も出ているし、さすが、良い感じです。

(ちなみに普通のiOSのほうはCocoaPodsがうまく使えなくて挫折中です)

まとめ

Xamarin.FormsでFirebaseのCrashlyticsは使えます。
ただいくつか難があり本番環境ではケアが必要です。

  • 画面名やイベント(ボタン押下など)を自力で送信するようにしておかないと「ログ」が寂しくなります
  • スタックトレースが意味不明な場合もありそうです

iOSやAndroid側の目新しいものをXamarinで使おうとするのはイバラの道ですね。
(Xamarin.Android.CrashlyticsのNugetパッケージが出たのは9月です)

課題(残件)

Crashlytics自体の話ですが、ストアに届くクラッシュログとの関係が良く分かっていません。
こっちを有効にするとストアには届かなくなるのか?など。
またチームで開発している場合、Crashlyticsに届いた内容をどう周知すると良いのだろうとか。
まだまだ不明点が多いです。


明日は @f-miyu さんです。よろしくお願いします!