[Xamarin.Forms] Firebase Crashlytics を導入してみた (Android & iOS)
以前、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