![[Xamarin.Forms] Firebase Crashlytics を導入してみた (Android & iOS)](https://devio2023-media.developers.io/wp-content/uploads/2019/07/eyecatch_xamarin_2.png)
[Xamarin.Forms] Firebase Crashlytics を導入してみた (Android & iOS)
この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
以前、Xamarin.FormsアプリにFirebase Analyticsを導入してみましたが、せっかくなので、Firebase Crashlyticsも追加導入してみました。
- Q:なぜXamarin?
 - A:趣味です!
 
目次
環境
- Windows
- Windows 10 Pro
 - Visual Studio Community 2019 (16.1.5)
 
 - macOS
- macOS Mojave (10.14.5)
 - Visutal Studio Community 2019 for Mac (8.1.3)
 - Xcode (10.2.1)
 
 - Android
- Pixel 3a (Android 9)
 
 - iOS
- iPhone 7 (12.2)
 - iPhone Xs Simulator (12.2)
 
 - Xamarin
- Xamarin 16.1.0.545
 - Xamarin.Android SDK 9.3.0.23
 - Xamarin.iOS and Xamarin.Mac SDK 12.10.0.157
 
 - Library
- 共通
- Xamarin.Forms: 4.0.0.425677
 
 - Android
- Xamarin.Android.Crashlytics: 2.9.4.1
 - Xamarin.Android.Crashlytics.Answers: 1.4.2
 - Xamarin.Android.Crashlytics.Beta: 1.2.9
 - Xamarin.Android.Crashlytics.Core: 2.6.3
 - Xamarin.Android.Fabric: 1.4.3
 - Xamarin.Firebase.Analytics: 60.1142.1
 - Xamarin.Firebase.Analytics.Impl: 60.1142.1
 - Xamarin.Firebase.Common: 60.1142.1
 - Xamarin.Firebase.Core: 60.1142.1
 - Xamarin.Firebase.Iid: 60.1142.1
 - Xamarin.GooglePlayServices.Basement: 60.1142.1
 - Xamarin.GooglePlayServices.Tasks: 60.1142.1
 
 - iOS
- Xamarin.Firebase.iOS.Analytics: 5.5.0
 - Xamarin.Firebase.iOS.Crashlytics: 3.10.9
 
 
 - 共通
 
Xamarin.Formsアプリの作成とFirebaseプロジェクトの作成
下記で作成したXamarin.FormsアプリとFirebaseプロジェクトを流用します。
Xamarin.FormsアプリにFirebase Analyticsを導入してみたので、手順をまとめた! (Android & iOS)
Androidの準備
Firebase Crashlyticsの導入(Android)
NuGetで下記のライブラリをAndroidプロジェクトに追加します。
- Xamarin.Android.Crashlytics
 
strings.xmlにユニークIDを追加
Resources/values/strings.xmlを新規作成し、下記を追加します。
アプリとバージョンを特定するためのユニークなIDのため、BundleIDとバージョンにしています。
<resources> <string name="com.crashlytics.android.build_id">com.companyname.FASample.v1.0.0</string> </resources>
Firebase Crashlyticsの初期化(Android)
MainActivity.csのOnCreate()に初期化コードを追記します。
protected override void OnCreate(Bundle savedInstanceState)
{
    TabLayoutResource = Resource.Layout.Tabbar;
    ToolbarResource = Resource.Layout.Toolbar;
    AnalyticsSingleton.GetInstance.Analytics = FirebaseAnalytics.GetInstance(this);
    AnalyticsSingleton.GetInstance.Activity = this;
    Fabric.Fabric.With(this, new Crashlytics.Crashlytics());
    Crashlytics.Crashlytics.HandleManagedExceptions();
    base.OnCreate(savedInstanceState);
    Xamarin.Essentials.Platform.Init(this, savedInstanceState);
    global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
    LoadApplication(new App());
}
Firebaseプロジェクト設定(Android)
Firebase Consoleにアクセスし、アプリが追加されているプロジェクトを選択したのち、「Crashlytics」を選択します。

続いて、Androidアプリを選択します。

「いいえ」を選択して「次へ」を選択します。

「ドキュメントに移動」を選択します。(そうしないと進めない)

待機画面でいったん放置します。

アプリの実行と接続確認(Android)
ビルドエラー対応
下記のビルドエラーが発生したので、NuGetでライブラリを追加導入します。(私のWindows環境だと、ビルドエラーが文字化けしてました……)
error: package io.fabric.sdk.android.services.events does not exist io.fabric.sdk.android.services.events.EventsStorageListener
- Xamarin.Android.Crashlytics
 - Xamarin.Android.Crashlytics.Answers
 - Xamarin.Android.Fabric
 - Xamarin.Android.Crashlytics.Beta
 - Xamarin.Firebase.Analytics
 - Xamarin.Firebase.Analytics.Impl
 - Xamarin.Firebase.Common
 - Xamarin.Firebase.Core
 - Xamarin.Firebase.Iid
 - Xamarin.GooglePlayServices.Basement
 - Xamarin.GooglePlayServices.Tasks
 
例外発生してアプリが落ちる
Androidアプリを実行すると、例外発生しました……。

Unhandled Exception: Java.Lang.NoClassDefFoundError: <Timeout exceeded getting exception details>
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/crashlytics/android/core/CrashlyticsCore; Caused by: java.lang.ClassNotFoundException: Didn't find class "com.crashlytics.android.core.CrashlyticsCore" on path: DexPathList[[zip file "/data/app/com.companyname.FASample-Jn4wnhxxnT4aX8IyEn33SQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.companyname.FASample-Jn4wnhxxnT4aX8IyEn33SQ==/lib/arm64, /data/app/com.companyname.FASample-Jn4wnhxxnT4aX8IyEn33SQ==/base.apk!/lib/arm64-v8a, /system/lib64, /system/product/lib64]]
これに対処するため、NuGetから下記のライブラリを追加します。
- Xamarin.Android.Crashlytics.Core
 
参考: Xamarin.Android.Crashlytics 2.9.4.1 - NoClassDefFoundError on CrashlyticsCore #455 | GitHub Issues
改めてアプリを実行する
接続成功しました!!!!
怪しい場合は、リビルド・Visual Studioを再起動・アプリの再インストールを試してみてください。

iOSの準備
Firebase Crashlyticsの導入(iOS)
NuGetで下記のライブラリをiOSプロジェクトに追加します。
- Xamarin.Firebase.iOS.Crashlytics
 
Firebase Crashlyticsの初期化(iOS)
AppDelegate.csのFinishedLaunching()に初期化コードを追記します。
public override bool FinishedLaunching(UIApplication app, NSDictionary options)
{
    // https://github.com/xamarin/GoogleApisForiOSComponents/issues/158#issuecomment-483194061
    var foo = Firebase.Core.Configuration.SharedInstance;
    Firebase.Core.App.Configure();
    Firebase.Crashlytics.Crashlytics.Configure();
    global::Xamarin.Forms.Forms.Init();
    LoadApplication(new App());
    return base.FinishedLaunching(app, options);
}
Firebaseプロジェクト設定(iOS)
アプリの種類をiOSに変更します。

Androidと同じ手順でポチポチし、待機画面を表示しておきます。
アプリの実行と接続確認(iOS)
iOSは素直にビルド&実行できました!!

Crashのテスト
Xamarin.Formsコードの追加
Xamarin.Formsの画面にボタンを追加し、それを押すと強制的にCrashさせてみます。
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:d="http://xamarin.com/schemas/2014/forms/design"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
             mc:Ignorable="d"
             x:Class="FASample.MainPage">
    <StackLayout VerticalOptions="Center">
        <Label Text="Welcome to Xamarin.Forms!" 
               HorizontalOptions="Center"
               VerticalOptions="Center"/>
        <Button Text="send event"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Clicked="Button_OnClicked" />
        <Button Text="crash!!"
                HorizontalOptions="Center"
                VerticalOptions="Center"
                Clicked="Button_Crash_Clicked"/>
    </StackLayout>
</ContentPage>
private void Button_Crash_Clicked(object sender, EventArgs e)
{
    throw new NotImplementedException("this is crash test!!!");
}
Crashのテスト(Android)
アプリを通常実行し(デバッグ実行だと通知来ないっぽい?)、画面の「crash!!」ボタンを押します。
アプリが強制終了したら、アプリを再び起動します。(次に起動した際にクラッシュレポートが送信されるため)
数分待つと、画面にクラッシュ情報が表示されました!

詳細はこんな感じになってます!

Crashのテスト(iOS)
iOSも、Androidと同じように通常実行し、「crash!!」ボタンを押します。 (アプリが終了するまで時間が掛かりました……)
すると、「dSYMをアップロードしてね」と言われました。

dSYMファイルの取得(エミュレータビルド)
下記を参考に取得しようと頑張りました。
私の場合は、「dSYMファイル」は存在していなかったので、下記のように「IPAをビルドする」設定を有効にし、「FASample.iOSのリビルド」を実行しました。

すると今度は「そんなprovisioningないよ」と怒られました。
error : Could not find any available provisioning profiles for iOS.
「なんちゃってBundleIDで実機リリースビルド」は流石に無理でした……。
dSYMファイルの取得(実機ビルド)
というわけで、BundleIDをちゃんと登録し、やり直しました。 (ここから先は有料会員パワー発動です)
- FirebaseプロジェクトにiOSアプリ追加
 - GoogleService-Info.plistの更新
 - Crashlyticsの登録
 - アプリ起動し、Crashさせる
 
すると、、、なんということでしょう、、、「dSYMファイル」が無くても表示されました!!!

エラー行もいい感じです。

ついでに、「dSYMファイル」ぽいものはできてました。

おまけ
簡単に試したところ、「iPhone実機」の場合に「dSYMファイル」は必要ありませんでした。
| 種類 | 対象 | dSYMファイルは必要? | 
|---|---|---|
| Debug | iOSシミュレータ | Yes | 
| Debug | iPhone実機 | No | 
| Release | iOSシミュレータ | Yes | 
| Release | iPhone実機 | No | 
なお、iOSシミュレータの場合に「dSYMファイル」は生成されませんでした。
やはりiOSは実機が安心ですね……! (個人の感想です)
他の機能
今回は試しませんが、Firebase Crashlyticsには下記などの機能もあります。
- 任意のカスタムキーを追加(Key-Value)
 - ユーザIDを設定
 - カスタムログメッセージを追加
 - 致命的でない例外をログに記録
 
これらをうまく使えば、
- ユーザ毎の傾向は?
 - 設定値の状態は?
 
といった情報も把握できそうです。
さいごに
簡単だと思ってましたが、一筋縄では行きませんでした……。
ビルドエラー等と戦いながら試したので、その記録も残しています。 どなたかの参考になれば幸いです。
参考
- Android
- Firebase Crashlytics を使ってみる(Android) | Firebase
 - Firebase Crashlytics 実装のテスト(Android) | Firebase
 - Firebase Crashlytics のクラッシュ レポートのカスタマイズ(Android) | Firebase
 - Crashlytics for Xamarin.Android | GitHub
 - CrashlyticsSample(Android) | GitHub
 - Xamarin.Android.Crashlytics error: package io.fabric.sdk.android.services.events #460 | GitHub Issues
 - Xamarin.Android.Crashlytics 2.9.4.1 - NoClassDefFoundError on CrashlyticsCore #455 | GitHub Issues
 
 - iOS
 










