1

Is there a way to save data just before a crash with sharedpreference? I search to deactivate a function only if a crash happens. So, to disable the function, I need to detect the crash. I'd like to use crash analytics to accomplish that, is that possible?

I tried to simulate a crash, but catch (error) is not called:

try {
       
        FirebaseCrashlytics.instance.crash();


      } catch (error) {

        prefs.setBool("crash",true);
      }
Andrew
  • 1
  • 4
  • 19
Nitneuq
  • 3,866
  • 13
  • 41
  • 64

4 Answers4

1

From the documentation:

FirebaseCrashlytics.instance.crash();

Your app should exit immediately after calling this method. After opening your app again after the crash Firebase Crashlytics will upload the crash report to the Firebase Console.

So it does not let the catch method be called, it just crashes the app immediately.

A workaround would be to to go with something like this:

testingCrash(){

prefs.setBool("crash",true);
some code that may or may not cause a crash...
prefs.setBool("crash",false); //If the line is executed and true is stored in 'crash' then you can be sure the code did not cause any crash

}

then on every start of your app, in your initState() method you can check if prefs.getBool('crash') is true, if yes then last time prefs.getBool('crash') did not managed to become false and hence the crash was there

Siddy Hacks
  • 1,846
  • 14
  • 15
0

The issue with your code of simulating the error is that you have to await for the crash to happen - like this:

      try {
        await crashFunction();
      } catch (error) {
        prefs.writeBool(key: "crash", value: true);
      }

In this case, the catch block will work.

FirebaseCrashlytics.instance.crash(); triggers the native app terminating crash, so I assume that is why catch did not work in this case - it cannot catch such kinds of crashes. You should use try catch to handle Dart/Flutter exceptions but not the Native crashes - it will not work like that.

Regarding your question - you cannot log anything before the crash - because you don't know when the crash will happen - but you sure can do it after in catch block(if the crash is not app terminating(but even in that case, there are ways to perform some logic))

The solution to that may be a wide logging system - so you would log everything needed to you, disregarding the crash occurrence. It may look too verbose but it is the only possible way to log something before the crash - log everything and everywhere.

If you want more info in the catch block, you can use another override of catch that looks like this:

try{
...
} catch (error, stacktrace){
//save to sharedprefs
}

In this case, you can store the complete stacktrace instead of just the error description.

Also you can catch specific errors with the help of :

try{
} on SomeException catch(error){
}

This override will catch only instances of SomeException and all the other ones will be thrown.

If you want to catch an app terminating error - I don't think there is a way in a clean flutter - but there is for sure a way to do that from the native platform as described here for Android.

Hope it helps

Pavlo Ostasha
  • 14,527
  • 11
  • 35
0

Here's what helped me so far; might be helpful!

class MyError extends Error {
  final dynamic data;
  final String? message;
  MyError(this.data, this.message);

  void storeError() {
    //Any Operation Can be done here
  }

  String toString() {
    var message = this.message;
    //Call this method in extension function to access there could be many ways to do so
    storeError();
    return (message != null) ? "MyError: $message" : "MyError";
  }
}

Create custom error class for specified operation after the crash:

Usage:

try {
      throw MyError({"testingData": "TestError"}, "Error Kind");
    } catch (error) {
      Logger.log("Crash Crash Crash", error.toString());
    }
Andrew
  • 1
  • 4
  • 19
Dhrumil Shah
  • 121
  • 3
-1

For any Future value returning method you can try like this..

futureMethod(params).catchError((e){
    debugPrint(e.toString());
    //todo handle error
});

Somehow few future returning methods cannot be caught by try/catch block. After trying like above I m able to catch the error.

In your case it might be like...

FirebaseCrashlytics.instance.crash().catchError((e){
        debugPrint(e.toString());
        prefs.setBool("crash",true);
    });

Check for crash at the beginning of app and proceed according to that.

bool crashed = await FirebaseCrashlytics.instance.didCrashOnPreviousExecution();

if(crashed){
    prefs.setBool("crash", crashed);
    //other stuff....
}else{
   //continue.....
}
Naveen Avidi
  • 3,004
  • 1
  • 11
  • 23
  • I can write like that -> This expression has a type of 'void' so its value can't be used. (Documentation) Try checking to see if you're using the correct API; there might be a function or call that returns void you didn't expect. Also check type parameters and variables which might also be void. – Nitneuq Nov 03 '22 at 09:36
  • Well then, there is a method didCrashOnPreviousExecution, it will return true or false. So in the beginning of your app you can call and proceed according to that. – Naveen Avidi Nov 04 '22 at 07:08
  • When I force to crash the app with FirebaseCrashlytics.instance.crash(); the function didCrashOnPreviousExecution not return true after call – Nitneuq Nov 04 '22 at 16:01