Countly / countly-sdk-flutter-bridge

Flutter SDK for Countly Product Analytics Platform
https://count.ly
MIT License
28 stars 18 forks source link

Fix: Non fatal crashes are handled as fatal crashes in Android #216

Closed Numoy closed 3 months ago

Numoy commented 3 months ago

Currently, nonFatal exceptions are not correctly handled in the Android implementation of the plugin.

This is the Flutter-Code to report exceptions:

static Future<String?> logException(String exception, bool nonfatal, [Map<String, Object>? segmentation]) async {
    if (!_instance._countlyState.isInitialized) {
      String message = '"initWithConfig" must be called before "logException"';
      log('logException, $message', logLevel: LogLevel.ERROR);
      return message;
    }
    int segCount = segmentation != null ? segmentation.length : 0;
    log('Calling "logException":[$exception] nonfatal:[$nonfatal]: with segmentation count:[$segCount]');
    List<String> args = [];
    args.add(exception);
    args.add(nonfatal.toString());
    if (segmentation != null) {
      segmentation.forEach((k, v) {
        args.add(k.toString());
        args.add(v.toString());
      });
    }
    final String? result = await _channel.invokeMethod('logException', <String, dynamic>{'data': json.encode(args)});

    return result;
  }

The flag to mark an exception as fatal/nonfatal is called "nonfatal". So if the exception is fatal it is "false" and "true" if the exception is fatal.

The corresponding code in the Android-Plugin looks like this:

else if ("logException".equals(call.method)) {
                String exceptionString = args.getString(0);
                boolean fatal = args.getBoolean(1);
                Exception exception = new Exception(exceptionString);
                Map<String, Object> segments = new HashMap<>();
                for (int i = 2, il = args.length(); i < il; i += 2) {
                    segments.put(args.getString(i), args.getString(i + 1));
                }
                if (fatal) {
                    Countly.sharedInstance().crashes().recordUnhandledException(exception, segments);
                } else {
                    Countly.sharedInstance().crashes().recordHandledException(exception, segments);
                }

                result.success("logException success!");
            }

Here it takes the "nonfatal" as "fatal". This results in that the flag "fatal" is used in the wrong way. If in Flutter the Flag is nonfatal = true it will result in fatal = true in Android or the other way round (nonfatal = false => fatal false).

I decided to change it in the platform code to not introduce a breaking change.

peterBrxwn commented 3 months ago

Hello Numoy,

Thank you for bringing this matter to our attention and for creating a fix.

This issue has already been addressed and resolved within this pull request, which has been merged into the staging branch.

Upon the release of the upcoming SDK version, the changes will be merged into the master branch accordingly.

Numoy commented 3 months ago

Thank you! Do you have an ETA on the release to the master branch?

peterBrxwn commented 3 months ago

We are actively working on this and aim to merge by tomorrow.

peterBrxwn commented 2 months ago

Hello @Numoy, it has been released to master branch.