quickstart-unity
quickstart-unity copied to clipboard
[Crashlytics][FR] Callback after crash happened
Is there a way to get a callback into my app when a crash happened in the previous session?
This issue does not seem to follow the issue template. Make sure you provide all the required information.
In this thread they talk about android callbacks, but seems te be old.
If native implementations have callback can someone point me in that direction please?
Seems like there is native implementation, boolean instead of a callback, here. Android: https://firebase.google.com/docs/reference/android/com/google/firebase/crashlytics/FirebaseCrashlytics#didCrashOnPreviousExecution() iOS: https://firebase.google.com/docs/reference/ios/firebasecrashlytics/api/reference/Classes/FIRCrashlytics#/c:objc(cs)FIRCrashlytics(im)didCrashDuringPreviousExecution
But does not seems to be available in Unity SDK.
I can file a feature request for you. Shawn
We don't currently offer a didCrashOnPreviousExecution API for Unity because the vast majority of Unity events that are collected by Crashlytics are caught by the Unity runtime and therefore did not result in a hard crash. (Internally, they are reported to Crashlytics similar to how a caught exception would be manually reported in Android. This is why the Crashlytics dashboard lists them as "non-fatals".)
Most app developers who use the didCrashOnPreviousExecution APIs for Android & iOS use them to pop a dialog to the customer apologizing for the crash and offering a discount, or requesting more info for a bug report, etc. This wouldn't make sense for a logged Unity exception because the customer may or may not have actually had a degraded experience as a result of the exception, and it is hard / impossible to know that without analyzing the exception report pretty closely.
Crashlytics can also catch hard crashes in the Unity runtime, which will be reported as fatals in the Crashlytics console. If we added a didCrashOnPreviousExecution for Unity, it would only return true for those hard crash cases. In our experience, this is fairly rare (in C# code, at least) and there hasn't been a lot of customer demand for it, though let us know if you believe it would be valuable! It would be great to hear how you might use it.
Having this didCrashOnPreviousExecution
on those hard crashes would be really useful since we are looking for understanding users funnels. We would like to send a metric to our analytics services.
Also as you said if we would like to give any discount/bug report we can improve the user experience based on that.
@mrichards Is there any possibility to add this feature?
@mrichards I found a way to get this value working. Is there a way to contribute in the SDK?
Tested on Unity 2018.4.16f1 + Crashlytics 6.15.2 in Android, iOS and Unity Editor.
Crashes were seen in Firebase Console as crashes in both platforms.
Main Class
This would be awesome to have it under Firebase Crashlytics class.
public static class CrashlyticsUtils
{
private static ICrashlyticsUtils _crashlyticsUtilsImp;
static CrashlyticsUtils()
{
_crashlyticsUtilsImp = GetCrashlyticsUtils();
}
public static bool DidCrashInPreviousExecution
{
get { return _crashlyticsUtilsImp.DidCrashInPreviousExecution; }
}
public static void ForceNativeCrash()
{
_crashlyticsUtilsImp.ForceNativeCrash();
}
private static ICrashlyticsUtils GetCrashlyticsUtils()
{
#if UNITY_ANDROID && !UNITY_EDITOR
return new AndroidCrashlyticsUtils();
#elif UNITY_IOS && !UNITY_EDITOR
return new IOSCrashlyticsUtils();
#else
return new EditorCrashlyticsUtils();
#endif
}
}
public interface ICrashlyticsUtils
{
bool DidCrashInPreviousExecution { get; }
void ForceNativeCrash();
}
Android
#if UNITY_ANDROID && !UNITY_EDITOR
using System;
using UnityEngine;
public class AndroidCrashlyticsUtils : ICrashlyticsUtils
{
public bool DidCrashInPreviousExecution
{
get
{
try
{
var firebaseClass = new AndroidJavaClass("com.google.firebase.crashlytics.FirebaseCrashlytics");
var getInstance = firebaseClass.CallStatic<AndroidJavaObject>("getInstance");
return getInstance.Call<bool>("didCrashOnPreviousExecution");
}
catch (Exception e)
{
Debug.LogError("Error accessing to FirebaseCrashlytics class.");
return false;
}
}
}
public void ForceNativeCrash()
{
var message = new AndroidJavaObject("java.lang.String", "This is a test crash, ignore.");
var exception = new AndroidJavaObject("java.lang.Exception", message);
var looperClass = new AndroidJavaClass("android.os.Looper");
var mainLooper = looperClass.CallStatic<AndroidJavaObject>("getMainLooper");
var mainThread = mainLooper.Call<AndroidJavaObject>("getThread");
var exceptionHandler = mainThread.Call<AndroidJavaObject>("getUncaughtExceptionHandler");
exceptionHandler.Call("uncaughtException", mainThread, exception);
}
}
#endif
iOS
#if UNITY_IOS
using System.Runtime.InteropServices;
public class IOSCrashlyticsUtils : ICrashlyticsUtils
{
[DllImport("__Internal")]
private static extern bool didCrashDuringPreviousExecution();
[DllImport("__Internal")]
private static extern void crash();
public bool DidCrashInPreviousExecution
{
get { return didCrashDuringPreviousExecution(); }
}
public void ForceNativeCrash()
{
crash();
}
}
#endif
And you need to add under Plugins/iOS the following .mm
//
// CrashlyticsUtils.mm
// Unity-iPhone
//
// Created by Martin Gonzalez on 03/08/2020.
//
#import <Foundation/Foundation.h>
#import <FirebaseCrashlytics.h>
extern "C" {
bool didCrashDuringPreviousExecution() {
return [[FIRCrashlytics crashlytics] didCrashDuringPreviousExecution];
}
void crash() {
strcpy(0, "crash!");
}
}
Usage
public class Demo : MonoBehaviour
{
public TMP_Text txtDidCrashed;
public Button btnForceCrash;
private Firebase.FirebaseApp _app;
void Start()
{
// Subscription to ForceCrash Button
btnForceCrash.onClick.AddListener(CrashlyticsUtils.ForceNativeCrash);
// Firebase Initialization
Firebase.FirebaseApp.CheckAndFixDependenciesAsync().ContinueWith(task =>
{
var dependencyStatus = task.Result;
if (dependencyStatus == Firebase.DependencyStatus.Available)
{
Debug.Log("Firebase Initialized");
_app = Firebase.FirebaseApp.DefaultInstance;
// Showing if previous execution crashed in Text
txtDidCrashed.text = "Did Crash on Previous Execution? " + CrashlyticsUtils.DidCrashInPreviousExecution;
}
else
{
Debug.LogError($"Could not resolve all Firebase dependencies: {dependencyStatus}");
}
//Need to add TaskScheduler.FromCurrentSynchronizationContext() to go back to main thread.
}, TaskScheduler.FromCurrentSynchronizationContext());
}
}