From 29b649864a371a4b35c2604619105e7b5132a212 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Thu, 2 Apr 2020 18:28:51 +0200 Subject: [PATCH 01/28] [crashlytics] Migrate to new Crashlytics SDK --- packages/firebase_crashlytics/CHANGELOG.md | 9 ++++ .../firebase_crashlytics/android/build.gradle | 5 +-- .../FirebaseCrashlyticsPlugin.java | 39 +++++----------- .../example/android/app/build.gradle | 2 +- .../EmbeddingV1ActivityTest.java | 1 - .../EmbeddingV1Activity.java | 1 - .../example/android/build.gradle | 5 +-- .../example/test_driver/crashlytics.dart | 1 - .../lib/src/firebase_crashlytics.dart | 29 ------------ packages/firebase_crashlytics/pubspec.yaml | 2 +- .../test/firebase_crashlytics_e2e.dart | 7 --- .../test/firebase_crashlytics_test.dart | 45 +------------------ 12 files changed, 26 insertions(+), 120 deletions(-) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index f358e8835de4..40bb0c2280a4 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,12 @@ +## 0.2.0 + +* **Breaking**: Migration to the new Firebase Crashlytics SDK. Follow the [migration guide](https://firebase.google.com/docs/crashlytics/upgrade-sdk?platform=android) to update your app. +* **Breaking**: the following methods have been removed: + * `setUserEmail` + * `setUserName` + * `getVersion` + * `isDebuggable` + ## 0.1.3+3 * Fix for missing UserAgent.h compilation failures. diff --git a/packages/firebase_crashlytics/android/build.gradle b/packages/firebase_crashlytics/android/build.gradle index a557dc49e8a2..c06a4bd509b4 100644 --- a/packages/firebase_crashlytics/android/build.gradle +++ b/packages/firebase_crashlytics/android/build.gradle @@ -16,9 +16,6 @@ rootProject.allprojects { repositories { google() jcenter() - maven { - url 'https://maven.fabric.io/public' - } } } @@ -37,7 +34,7 @@ android { } dependencies { - implementation 'com.crashlytics.sdk.android:crashlytics:2.9.9' + implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta03' implementation 'com.google.firebase:firebase-common:16.1.0' implementation 'androidx.annotation:annotation:1.1.0' } diff --git a/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java b/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java index 6de881d1da50..f688661c1901 100644 --- a/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java +++ b/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java @@ -6,8 +6,7 @@ import android.content.Context; import android.util.Log; -import com.crashlytics.android.Crashlytics; -import io.fabric.sdk.android.Fabric; +import com.google.firebase.crashlytics.FirebaseCrashlytics; import io.flutter.embedding.engine.plugins.FlutterPlugin; import io.flutter.plugin.common.BinaryMessenger; import io.flutter.plugin.common.MethodCall; @@ -42,11 +41,6 @@ private static MethodChannel setup(BinaryMessenger binaryMessenger, Context cont final MethodChannel channel = new MethodChannel(binaryMessenger, "plugins.flutter.io/firebase_crashlytics"); channel.setMethodCallHandler(new FirebaseCrashlyticsPlugin()); - - if (!Fabric.isInitialized()) { - Fabric.with(context, new Crashlytics()); - } - return channel; } @@ -57,11 +51,12 @@ public static void registerWith(Registrar registrar) { @Override public void onMethodCall(MethodCall call, Result result) { + final FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); if (call.method.equals("Crashlytics#onError")) { // Add logs. List logs = call.argument("logs"); for (String log : logs) { - Crashlytics.log(log); + crashlytics.log(log); } // Set keys. @@ -69,16 +64,16 @@ public void onMethodCall(MethodCall call, Result result) { for (Map key : keys) { switch ((String) key.get("type")) { case "int": - Crashlytics.setInt((String) key.get("key"), (int) key.get("value")); + crashlytics.setCustomKey((String) key.get("key"), (int) key.get("value")); break; case "double": - Crashlytics.setDouble((String) key.get("key"), (double) key.get("value")); + crashlytics.setCustomKey((String) key.get("key"), (double) key.get("value")); break; case "string": - Crashlytics.setString((String) key.get("key"), (String) key.get("value")); + crashlytics.setCustomKey((String) key.get("key"), (String) key.get("value")); break; case "boolean": - Crashlytics.setBool((String) key.get("key"), (boolean) key.get("value")); + crashlytics.setCustomKey((String) key.get("key"), (boolean) key.get("value")); break; } } @@ -96,30 +91,20 @@ public void onMethodCall(MethodCall call, Result result) { } exception.setStackTrace(elements.toArray(new StackTraceElement[elements.size()])); - Crashlytics.setString("exception", (String) call.argument("exception")); + crashlytics.setCustomKey("exception", (String) call.argument("exception")); // Set a "reason" (to match iOS) to show where the exception was thrown. final String context = call.argument("context"); - if (context != null) Crashlytics.setString("reason", "thrown " + context); + if (context != null) crashlytics.setCustomKey("reason", "thrown " + context); // Log information. final String information = call.argument("information"); - if (information != null && !information.isEmpty()) Crashlytics.log(information); + if (information != null && !information.isEmpty()) crashlytics.log(information); - Crashlytics.logException(exception); + crashlytics.recordException(exception); result.success("Error reported to Crashlytics."); - } else if (call.method.equals("Crashlytics#isDebuggable")) { - result.success(Fabric.isDebuggable()); - } else if (call.method.equals("Crashlytics#getVersion")) { - result.success(Crashlytics.getInstance().getVersion()); - } else if (call.method.equals("Crashlytics#setUserEmail")) { - Crashlytics.setUserEmail((String) call.argument("email")); - result.success(null); } else if (call.method.equals("Crashlytics#setUserIdentifier")) { - Crashlytics.setUserIdentifier((String) call.argument("identifier")); - result.success(null); - } else if (call.method.equals("Crashlytics#setUserName")) { - Crashlytics.setUserName((String) call.argument("name")); + crashlytics.setUserId((String) call.argument("identifier")); result.success(null); } else { result.notImplemented(); diff --git a/packages/firebase_crashlytics/example/android/app/build.gradle b/packages/firebase_crashlytics/example/android/app/build.gradle index 891334951d8d..6bd17182159e 100644 --- a/packages/firebase_crashlytics/example/android/app/build.gradle +++ b/packages/firebase_crashlytics/example/android/app/build.gradle @@ -64,5 +64,5 @@ dependencies { implementation "android.arch.lifecycle:extensions:1.1.1" } -apply plugin: 'io.fabric' apply plugin: 'com.google.gms.google-services' +apply plugin: 'com.google.firebase.crashlytics' diff --git a/packages/firebase_crashlytics/example/android/app/src/androidTest/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/EmbeddingV1ActivityTest.java b/packages/firebase_crashlytics/example/android/app/src/androidTest/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/EmbeddingV1ActivityTest.java index 486cb4978c1b..39bdffc12e98 100644 --- a/packages/firebase_crashlytics/example/android/app/src/androidTest/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/EmbeddingV1ActivityTest.java +++ b/packages/firebase_crashlytics/example/android/app/src/androidTest/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/EmbeddingV1ActivityTest.java @@ -1,4 +1,3 @@ - package io.flutter.plugins.firebase.crashlytics.firebasecrashlytics; import androidx.test.rule.ActivityTestRule; diff --git a/packages/firebase_crashlytics/example/android/app/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlyticsexample/EmbeddingV1Activity.java b/packages/firebase_crashlytics/example/android/app/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlyticsexample/EmbeddingV1Activity.java index 76245da23ea0..b41a0b774914 100644 --- a/packages/firebase_crashlytics/example/android/app/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlyticsexample/EmbeddingV1Activity.java +++ b/packages/firebase_crashlytics/example/android/app/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlyticsexample/EmbeddingV1Activity.java @@ -1,4 +1,3 @@ - package io.flutter.plugins.firebase.crashlytics.firebasecrashlyticsexample; import android.os.Bundle; diff --git a/packages/firebase_crashlytics/example/android/build.gradle b/packages/firebase_crashlytics/example/android/build.gradle index faeab902b866..e4998f460e11 100644 --- a/packages/firebase_crashlytics/example/android/build.gradle +++ b/packages/firebase_crashlytics/example/android/build.gradle @@ -2,15 +2,12 @@ buildscript { repositories { google() jcenter() - maven { - url 'https://maven.fabric.io/public' - } } dependencies { classpath 'com.android.tools.build:gradle:3.3.2' classpath 'com.google.gms:google-services:4.3.0' - classpath 'io.fabric.tools:gradle:1.26.1' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta03' } } diff --git a/packages/firebase_crashlytics/example/test_driver/crashlytics.dart b/packages/firebase_crashlytics/example/test_driver/crashlytics.dart index 0169c1e736f4..cee89ed0b75b 100644 --- a/packages/firebase_crashlytics/example/test_driver/crashlytics.dart +++ b/packages/firebase_crashlytics/example/test_driver/crashlytics.dart @@ -17,7 +17,6 @@ void main() { test('recordFlutterError', () async { // This is currently only testing that we can log errors without crashing. final Crashlytics crashlytics = Crashlytics.instance; - await crashlytics.setUserName('testing'); await crashlytics.setUserIdentifier('hello'); crashlytics.setBool('testBool', true); crashlytics.setInt('testInt', 42); diff --git a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart index 4c95cb4a7081..24b4b6de0a60 100644 --- a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart +++ b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart @@ -54,21 +54,6 @@ class Crashlytics { throw StateError('Error thrown by Crashlytics plugin'); } - /// Reports the global value for debug mode. - /// TODO(kroikie): Clarify what this means in context of both Android and iOS. - Future isDebuggable() async { - final bool result = - await channel.invokeMethod('Crashlytics#isDebuggable'); - return result; - } - - /// Returns Crashlytics SDK version. - Future getVersion() async { - final String result = - await channel.invokeMethod('Crashlytics#getVersion'); - return result; - } - /// Add text logging that will be sent with your next report. `msg` will be /// printed to the console when in debug mode. Each report has a rolling max /// of 64k of logs, older logs are removed to allow newer logs to fit within @@ -110,13 +95,6 @@ class Crashlytics { _setValue(key, value); } - /// Optionally set a end-user's name or username for display within the - /// Crashlytics UI. Please be mindful of end-user's privacy. - Future setUserEmail(String email) async { - await channel.invokeMethod( - 'Crashlytics#setUserEmail', {'email': email}); - } - /// Specify a user identifier which will be visible in the Crashlytics UI. /// Please be mindful of end-user's privacy. Future setUserIdentifier(String identifier) async { @@ -124,13 +102,6 @@ class Crashlytics { {'identifier': identifier}); } - /// Specify a user name which will be visible in the Crashlytics UI. Please - /// be mindful of end-user's privacy. - Future setUserName(String name) async { - await channel.invokeMethod( - 'Crashlytics#setUserName', {'name': name}); - } - List> _prepareKeys() { final List> crashlyticsKeys = >[]; for (String key in _keys.keys) { diff --git a/packages/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/pubspec.yaml index e449a0e86835..543cc9ab70e9 100644 --- a/packages/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/pubspec.yaml @@ -2,7 +2,7 @@ name: firebase_crashlytics description: Flutter plugin for Firebase Crashlytics. It reports uncaught errors to the Firebase console. -version: 0.1.3+3 +version: 0.2.0 homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_crashlytics environment: diff --git a/packages/firebase_crashlytics/test/firebase_crashlytics_e2e.dart b/packages/firebase_crashlytics/test/firebase_crashlytics_e2e.dart index 59f11e023913..b19e37dd6541 100644 --- a/packages/firebase_crashlytics/test/firebase_crashlytics_e2e.dart +++ b/packages/firebase_crashlytics/test/firebase_crashlytics_e2e.dart @@ -1,12 +1,5 @@ -import 'package:flutter_test/flutter_test.dart'; import 'package:e2e/e2e.dart'; -import 'package:firebase_crashlytics/firebase_crashlytics.dart'; void main() { E2EWidgetsFlutterBinding.ensureInitialized(); - - testWidgets('get version', (WidgetTester tester) async { - final String version = await Crashlytics.instance.getVersion(); - expect(version, isNotNull); - }); } diff --git a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart index aac0a29dcd82..346a0b8e9ed5 100644 --- a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart +++ b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart @@ -12,7 +12,7 @@ import 'package:flutter_test/flutter_test.dart'; void main() { TestWidgetsFlutterBinding.ensureInitialized(); - group('$Crashlytics', () { + group('Crashlytics', () { final List log = []; final Crashlytics crashlytics = Crashlytics.instance; @@ -24,16 +24,8 @@ void main() { switch (methodCall.method) { case 'Crashlytics#onError': return 'Error reported to Crashlytics.'; - case 'Crashlytics#isDebuggable': - return true; - case 'Crashlytics#setUserEmail': - return true; case 'Crashlytics#setUserIdentifier': return true; - case 'Crashlytics#setUserName': - return true; - case 'Crashlytics#getVersion': - return '0.0.0+1'; default: return false; } @@ -103,37 +95,10 @@ void main() { expect(log[0].arguments['keys'][3]['type'], 'string'); }); - test('isDebuggable', () async { - expect(await crashlytics.isDebuggable(), true); - expect( - log, - [ - isMethodCall( - 'Crashlytics#isDebuggable', - arguments: null, - ) - ], - ); - }); - test('crash', () { expect(() => crashlytics.crash(), throwsStateError); }); - test('getVersion', () async { - await crashlytics.getVersion(); - expect(log, - [isMethodCall('Crashlytics#getVersion', arguments: null)]); - }); - - test('setUserEmail', () async { - await crashlytics.setUserEmail('foo'); - expect(log, [ - isMethodCall('Crashlytics#setUserEmail', - arguments: {'email': 'foo'}) - ]); - }); - test('setUserIdentifier', () async { await crashlytics.setUserIdentifier('foo'); expect(log, [ @@ -142,14 +107,6 @@ void main() { ]); }); - test('setUserName', () async { - await crashlytics.setUserName('foo'); - expect(log, [ - isMethodCall('Crashlytics#setUserName', - arguments: {'name': 'foo'}) - ]); - }); - test('getStackTraceElements with character index', () async { final List lines = [ 'package:flutter/src/widgets/framework.dart 3825:27 StatefulElement.build' From 3cafc461a97ee9747a4bb7656ec38b46c2cf699f Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Wed, 8 Apr 2020 02:51:03 +0200 Subject: [PATCH 02/28] [crashlytics] Migration to new SDK: update Obj-C files --- .../Classes/FirebaseCrashlyticsPlugin.m | 49 +++++++++---------- .../ios/firebase_crashlytics.podspec | 7 ++- .../macos/firebase_crashlytics.podspec | 5 +- 3 files changed, 27 insertions(+), 34 deletions(-) diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index 607f4def8f02..94069978f4c1 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -18,7 +18,7 @@ + (void)registerWithRegistrar:(NSObject *)registrar { FirebaseCrashlyticsPlugin *instance = [[FirebaseCrashlyticsPlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:channel]; - [Fabric with:@[ [Crashlytics self] ]]; + [FIRApp configure]; SEL sel = NSSelectorFromString(@"registerLibrary:withVersion:"); if ([FIRApp respondsToSelector:sel]) { @@ -41,29 +41,24 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result // Add logs. NSArray *logs = call.arguments[@"logs"]; for (NSString *log in logs) { - // Here and below, use CLSLog instead of CLS_LOG to try and avoid - // automatic inclusion of the current code location. It also ensures that - // the log is only written to Crashlytics and not also to the offline log - // as explained here: - // https://support.crashlytics.com/knowledgebase/articles/92519-how-do-i-use-logging - CLSLog(@"%@", log); + [[FIRCrashlytics crashlytics] logWithFormat:@"%@", log]; } // Set keys. NSArray *keys = call.arguments[@"keys"]; for (NSDictionary *key in keys) { if ([@"int" isEqualToString:key[@"type"]]) { - [[Crashlytics sharedInstance] setIntValue:(int)call.arguments[@"value"] - forKey:call.arguments[@"key"]]; + [[FIRCrashlytics crashlytics] setCustomValue:(int)call.arguments[@"value"] + forKey:call.arguments[@"key"]]; } else if ([@"double" isEqualToString:key[@"type"]]) { - [[Crashlytics sharedInstance] setFloatValue:[call.arguments[@"value"] floatValue] - forKey:call.arguments[@"key"]]; + [[FIRCrashlytics crashlytics] setCustomValue:[call.arguments[@"value"] floatValue] + forKey:call.arguments[@"key"]]; } else if ([@"string" isEqualToString:key[@"type"]]) { - [[Crashlytics sharedInstance] setObjectValue:call.arguments[@"value"] + [[FIRCrashlytics crashlytics] setCustomValue:call.arguments[@"value"] forKey:call.arguments[@"key"]]; } else if ([@"boolean" isEqualToString:key[@"type"]]) { - [[Crashlytics sharedInstance] setBoolValue:[call.arguments[@"value"] boolValue] - forKey:call.arguments[@"key"]]; + [[FIRCrashlytics crashlytics] setCustomValue:[call.arguments[@"value"] boolValue] + forKey:call.arguments[@"key"]]; } } @@ -71,7 +66,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result // Crashlytics. NSString *information = call.arguments[@"information"]; if ([information length] != 0) { - CLSLog(@"%@", information); + [[FIRCrashlytics crashlytics] logWithFormat:@"%@", information]; } // Report crash. @@ -86,23 +81,23 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result if (context != nil) { reason = [NSString stringWithFormat:@"thrown %@", context]; } + NSDictionary *stack = @{ + @"stackTrace" : frames + }; - [[Crashlytics sharedInstance] recordCustomExceptionName:call.arguments[@"exception"] - reason:reason - frameArray:frames]; + NSException *exception = [NSException + exceptionWithName:call.arguments["@exception"] + reason:reason + userInfo:stack] + + [[FIRCrashlytics crashlytics] recordError:exception] result(@"Error reported to Crashlytics."); } else if ([@"Crashlytics#isDebuggable" isEqualToString:call.method]) { - result([NSNumber numberWithBool:[Crashlytics sharedInstance].debugMode]); + result([NSNumber numberWithBool:[FIRCrashlytics crashlytics].debugMode]); } else if ([@"Crashlytics#getVersion" isEqualToString:call.method]) { - result([Crashlytics sharedInstance].version); - } else if ([@"Crashlytics#setUserEmail" isEqualToString:call.method]) { - [[Crashlytics sharedInstance] setUserEmail:call.arguments[@"email"]]; - result(nil); - } else if ([@"Crashlytics#setUserName" isEqualToString:call.method]) { - [[Crashlytics sharedInstance] setUserName:call.arguments[@"name"]]; - result(nil); + result([FIRCrashlytics crashlytics].version); } else if ([@"Crashlytics#setUserIdentifier" isEqualToString:call.method]) { - [[Crashlytics sharedInstance] setUserIdentifier:call.arguments[@"identifier"]]; + [[FIRCrashlytics crashlytics] setUserID:call.arguments[@"identifier"]]; result(nil); } else { result(FlutterMethodNotImplemented); diff --git a/packages/firebase_crashlytics/ios/firebase_crashlytics.podspec b/packages/firebase_crashlytics/ios/firebase_crashlytics.podspec index eb42d90940ad..46b0ca23d1c6 100644 --- a/packages/firebase_crashlytics/ios/firebase_crashlytics.podspec +++ b/packages/firebase_crashlytics/ios/firebase_crashlytics.podspec @@ -22,9 +22,8 @@ A new flutter plugin project. s.ios.deployment_target = '8.0' s.static_framework = true s.dependency 'Flutter' - s.dependency 'Fabric' - s.dependency 'Crashlytics' - s.dependency 'Firebase/Core' - + s.dependency 'Firebase/Crashlytics' + s.dependency 'Firebase/Analytics' + s.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\@\\\"#{libraryVersion}\\\" LIBRARY_NAME=\\@\\\"flutter-fire-cls\\\"" } end diff --git a/packages/firebase_crashlytics/macos/firebase_crashlytics.podspec b/packages/firebase_crashlytics/macos/firebase_crashlytics.podspec index 83eb735d7e80..bc5131cbba97 100644 --- a/packages/firebase_crashlytics/macos/firebase_crashlytics.podspec +++ b/packages/firebase_crashlytics/macos/firebase_crashlytics.podspec @@ -22,9 +22,8 @@ A new flutter plugin project. s.platform = :osx, '10.11' s.static_framework = true s.dependency 'FlutterMacOS' - s.dependency 'Fabric' - s.dependency 'Crashlytics' - s.dependency 'Firebase/Core' + s.dependency 'Firebase/Crashlytics' + s.dependency 'Firebase/Analytics' s.pod_target_xcconfig = { 'GCC_PREPROCESSOR_DEFINITIONS' => "LIBRARY_VERSION=\\@\\\"#{libraryVersion}\\\" LIBRARY_NAME=\\@\\\"flutter-fire-cls\\\"" } end From 93464474a826099d7ffabcfce83b0a2975eaf095 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Tue, 14 Apr 2020 12:52:13 +0200 Subject: [PATCH 03/28] Update generateFrame method --- .../darwin/Classes/FirebaseCrashlyticsPlugin.m | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index 94069978f4c1..20bd9cab44a5 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -104,14 +104,11 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } } -- (CLSStackFrame *)generateFrame:(NSDictionary *)errorElement { - CLSStackFrame *frame = [CLSStackFrame stackFrame]; - - frame.library = [errorElement valueForKey:@"class"]; - frame.symbol = [errorElement valueForKey:@"method"]; - frame.fileName = [errorElement valueForKey:@"file"]; - frame.lineNumber = [[errorElement valueForKey:@"line"] intValue]; - +- (FIRStackFrame *)generateFrame:(NSDictionary *)errorElement { + FIRStackFrame *frame = [FIRStackFrame + stackFrameWithSymbol:[errorElement valueForKey:@"method"] + file:[errorElement valueForKey:@"file"] + line:[[errorElement valueForKey:@"line"] intValue]]; return frame; } From bc7c7a7257bae0be51ef7489f4c678b9620910cb Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Tue, 14 Apr 2020 13:01:11 +0200 Subject: [PATCH 04/28] Remove getVersion and isDebuggable --- .../darwin/Classes/FirebaseCrashlyticsPlugin.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index 20bd9cab44a5..91b2df1a3fca 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -92,10 +92,6 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result [[FIRCrashlytics crashlytics] recordError:exception] result(@"Error reported to Crashlytics."); - } else if ([@"Crashlytics#isDebuggable" isEqualToString:call.method]) { - result([NSNumber numberWithBool:[FIRCrashlytics crashlytics].debugMode]); - } else if ([@"Crashlytics#getVersion" isEqualToString:call.method]) { - result([FIRCrashlytics crashlytics].version); } else if ([@"Crashlytics#setUserIdentifier" isEqualToString:call.method]) { [[FIRCrashlytics crashlytics] setUserID:call.arguments[@"identifier"]]; result(nil); From d03e47ba8b0aeef1f81f818dc7f038967934c06b Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Tue, 14 Apr 2020 13:06:05 +0200 Subject: [PATCH 05/28] Wrong call to argument --- .../darwin/Classes/FirebaseCrashlyticsPlugin.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index 91b2df1a3fca..4f306619c01a 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -48,16 +48,16 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result NSArray *keys = call.arguments[@"keys"]; for (NSDictionary *key in keys) { if ([@"int" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:(int)call.arguments[@"value"] + [[FIRCrashlytics crashlytics] setCustomValue:call.arguments[@"value"] forKey:call.arguments[@"key"]]; } else if ([@"double" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:[call.arguments[@"value"] floatValue] + [[FIRCrashlytics crashlytics] setCustomValue:call.arguments[@"value"] forKey:call.arguments[@"key"]]; } else if ([@"string" isEqualToString:key[@"type"]]) { [[FIRCrashlytics crashlytics] setCustomValue:call.arguments[@"value"] forKey:call.arguments[@"key"]]; } else if ([@"boolean" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:[call.arguments[@"value"] boolValue] + [[FIRCrashlytics crashlytics] setCustomValue:call.arguments[@"value"] forKey:call.arguments[@"key"]]; } } @@ -86,7 +86,7 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result }; NSException *exception = [NSException - exceptionWithName:call.arguments["@exception"] + exceptionWithName:call.arguments[@"exception"] reason:reason userInfo:stack] From e359b0915efcfb02b6db027cfa9ef843e664d054 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Tue, 14 Apr 2020 13:09:23 +0200 Subject: [PATCH 06/28] Missing semicolons --- .../darwin/Classes/FirebaseCrashlyticsPlugin.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index 4f306619c01a..eabb5e5ff51b 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -88,9 +88,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result NSException *exception = [NSException exceptionWithName:call.arguments[@"exception"] reason:reason - userInfo:stack] + userInfo:stack]; - [[FIRCrashlytics crashlytics] recordError:exception] + [[FIRCrashlytics crashlytics] recordError:exception]; result(@"Error reported to Crashlytics."); } else if ([@"Crashlytics#setUserIdentifier" isEqualToString:call.method]) { [[FIRCrashlytics crashlytics] setUserID:call.arguments[@"identifier"]]; From 28891ae30e99c2285a79c98ea9989715687bf470 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Tue, 14 Apr 2020 13:42:06 +0200 Subject: [PATCH 07/28] Use recordExceptionModel instead of recordError --- .../darwin/Classes/FirebaseCrashlyticsPlugin.m | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index eabb5e5ff51b..c8ab7f6d5c10 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -81,16 +81,14 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result if (context != nil) { reason = [NSString stringWithFormat:@"thrown %@", context]; } - NSDictionary *stack = @{ - @"stackTrace" : frames - }; - NSException *exception = [NSException - exceptionWithName:call.arguments[@"exception"] - reason:reason - userInfo:stack]; + FIRExceptionModel *exception = [FIRExceptionModel + exceptionModelWithName:call.arguments[@"exception"] + reason:reason]; + + exception.stackTrace = frames; - [[FIRCrashlytics crashlytics] recordError:exception]; + [[FIRCrashlytics crashlytics] recordExceptionModel:exception]; result(@"Error reported to Crashlytics."); } else if ([@"Crashlytics#setUserIdentifier" isEqualToString:call.method]) { [[FIRCrashlytics crashlytics] setUserID:call.arguments[@"identifier"]]; From ec3cc0f45d420e356738cfbf337dbafc5313082b Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Tue, 14 Apr 2020 14:03:43 +0200 Subject: [PATCH 08/28] Update project.pbxproj --- .../example/ios/Runner.xcodeproj/project.pbxproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_crashlytics/example/ios/Runner.xcodeproj/project.pbxproj b/packages/firebase_crashlytics/example/ios/Runner.xcodeproj/project.pbxproj index 40c572dde0ed..4da18da1bcbd 100644 --- a/packages/firebase_crashlytics/example/ios/Runner.xcodeproj/project.pbxproj +++ b/packages/firebase_crashlytics/example/ios/Runner.xcodeproj/project.pbxproj @@ -268,7 +268,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${PODS_ROOT}/Fabric/run\"\n"; + shellScript = "# Type a script or drag a script file from your workspace to insert its path.\n\"${PODS_ROOT}/FirebaseCrashlytics/run\"\n"; }; 3B06AD1E1E4923F5004D2608 /* Thin Binary */ = { isa = PBXShellScriptBuildPhase; From 7685fe07608566610bfa2b958c4d2cda11b910af Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Wed, 15 Apr 2020 23:28:53 +0200 Subject: [PATCH 09/28] Don't call [FIRApp configure] twice --- .../darwin/Classes/FirebaseCrashlyticsPlugin.m | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index c8ab7f6d5c10..96e5befd6a33 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -18,8 +18,6 @@ + (void)registerWithRegistrar:(NSObject *)registrar { FirebaseCrashlyticsPlugin *instance = [[FirebaseCrashlyticsPlugin alloc] init]; [registrar addMethodCallDelegate:instance channel:channel]; - [FIRApp configure]; - SEL sel = NSSelectorFromString(@"registerLibrary:withVersion:"); if ([FIRApp respondsToSelector:sel]) { [FIRApp performSelector:sel withObject:LIBRARY_NAME withObject:LIBRARY_VERSION]; From 7cf35120f0a9175f43c35119830c4d338bbfddaf Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Wed, 15 Apr 2020 23:42:34 +0200 Subject: [PATCH 10/28] Format --- .../darwin/Classes/FirebaseCrashlyticsPlugin.m | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index 96e5befd6a33..7dab2b140ee3 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -80,10 +80,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result reason = [NSString stringWithFormat:@"thrown %@", context]; } - FIRExceptionModel *exception = [FIRExceptionModel - exceptionModelWithName:call.arguments[@"exception"] - reason:reason]; - + FIRExceptionModel *exception = + [FIRExceptionModel exceptionModelWithName:call.arguments[@"exception"] reason:reason]; + exception.stackTrace = frames; [[FIRCrashlytics crashlytics] recordExceptionModel:exception]; @@ -97,10 +96,10 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } - (FIRStackFrame *)generateFrame:(NSDictionary *)errorElement { - FIRStackFrame *frame = [FIRStackFrame - stackFrameWithSymbol:[errorElement valueForKey:@"method"] - file:[errorElement valueForKey:@"file"] - line:[[errorElement valueForKey:@"line"] intValue]]; + FIRStackFrame *frame = + [FIRStackFrame stackFrameWithSymbol:[errorElement valueForKey:@"method"] + file:[errorElement valueForKey:@"file"] + line:[[errorElement valueForKey:@"line"] intValue]]; return frame; } From 0628c268e89ce7b3e86a109d3c070e322d35844f Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Sun, 19 Apr 2020 16:48:55 +0200 Subject: [PATCH 11/28] Update Gradle dependency --- packages/firebase_crashlytics/android/build.gradle | 2 +- packages/firebase_crashlytics/example/android/build.gradle | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/firebase_crashlytics/android/build.gradle b/packages/firebase_crashlytics/android/build.gradle index c06a4bd509b4..881c4986bc5f 100644 --- a/packages/firebase_crashlytics/android/build.gradle +++ b/packages/firebase_crashlytics/android/build.gradle @@ -34,7 +34,7 @@ android { } dependencies { - implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta03' + implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta04' implementation 'com.google.firebase:firebase-common:16.1.0' implementation 'androidx.annotation:annotation:1.1.0' } diff --git a/packages/firebase_crashlytics/example/android/build.gradle b/packages/firebase_crashlytics/example/android/build.gradle index e4998f460e11..74c0ead08560 100644 --- a/packages/firebase_crashlytics/example/android/build.gradle +++ b/packages/firebase_crashlytics/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.2' classpath 'com.google.gms:google-services:4.3.0' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta03' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04' } } From 6386231f446a5b5b4381652ec05014c78e794aae Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Sun, 19 Apr 2020 17:14:15 +0200 Subject: [PATCH 12/28] Update README --- packages/firebase_crashlytics/README.md | 71 ++++++++++++++++--------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/packages/firebase_crashlytics/README.md b/packages/firebase_crashlytics/README.md index 48f6a4ec482a..a9a945a58f3c 100644 --- a/packages/firebase_crashlytics/README.md +++ b/packages/firebase_crashlytics/README.md @@ -12,43 +12,59 @@ For Flutter plugins for other Firebase products, see [README.md](https://github. To use the `firebase_crashlytics` plugin, follow the [plugin installation instructions](https://pub.dartlang.org/packages/firebase_crashlytics#pub-pkg-tab-installing). +The following instructions are from [the official installation page](https://firebase.google.com/docs/crashlytics/get-started-new-sdk). + ### Android integration Enable the Google services by configuring the Gradle scripts as such: -1. Add the Fabric repository to the `[project]/android/build.gradle` file. -``` -repositories { - google() - jcenter() - // Additional repository for fabric resources - maven { - url 'https://maven.fabric.io/public' +1. Check that you have Google's Maven repository in your **project-level** `build.gradle` file (`[project]/android/build.gradle`). + +```gradle +buildscript { + repositories { + // Add this + google() + + // ... you may have other repositories + } +} +allprojects { + repositories { + // and this + google() + + // ... } } ``` -2. Add the following classpaths to the `[project]/android/build.gradle` file. +2. Add the following classpaths to your **project-level** `build.gradle` file (`[project]/android/build.gradle`). + ```gradle -dependencies { - // Example existing classpath - classpath 'com.android.tools.build:gradle:3.2.1' - // Add the google services classpath - classpath 'com.google.gms:google-services:4.3.0' - // Add fabric classpath - classpath 'io.fabric.tools:gradle:1.26.1' +buildscript { + dependencies { + // Check that you have the Google Services Gradle plugin v4.3.2 or later (if not, add it). + classpath 'com.google.gms:google-services:4.3.3' + // Add the Crashlytics Gradle plugin. + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04' + + // ... you may have other classpaths + } } ``` -2. Apply the following plugins in the `[project]/android/app/build.gradle` file. +3. Apply the following plugins in your **app-level** `build.gradle` file (`[project]/android/app/build.gradle`). + ```gradle // ADD THIS AT THE BOTTOM -apply plugin: 'io.fabric' apply plugin: 'com.google.gms.google-services' +apply plugin: 'com.google.firebase.crashlytics' ``` *Note:* If this section is not completed, you will get an error like this: -``` + +```console java.lang.IllegalStateException: Default FirebaseApp is not initialized in this process [package name]. Make sure to call FirebaseApp.initializeApp(Context) first. @@ -64,18 +80,20 @@ Add the Crashlytics run scripts: 1. From Xcode select `Runner` from the project navigation. 1. Select the `Build Phases` tab. 1. Click `+ Add a new build phase`, and select `New Run Script Phase`. -1. Add `${PODS_ROOT}/Fabric/run` to the `Type a script...` text box. +1. Add `${PODS_ROOT}/FirebaseCrashlytics/run` to the `Type a script...` text box. 1. If you are using Xcode 10, add the location of `Info.plist`, built by your app, to the `Build Phase's Input Files` field. E.g.: `$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)` ### Use the plugin Add the following imports to your Dart code: + ```dart import 'package:firebase_crashlytics/firebase_crashlytics.dart'; ``` Setup `Crashlytics`: + ```dart void main() { // Set `enableInDevMode` to true to see reports while in debug mode @@ -91,20 +109,21 @@ void main() { } ``` -Overriding `FlutterError.onError` with `Crashlytics.instance.recordFlutterError` will automatically catch all -errors that are thrown from within the Flutter framework. -If you want to catch errors that occur in `runZoned`, -you can supply `Crashlytics.instance.recordError` to the `onError` parameter: +Overriding `FlutterError.onError` with `Crashlytics.instance.recordFlutterError` will automatically catch all errors that are thrown from within the Flutter framework. + +If you want to catch errors that occur in `runZoned`, you can supply `Crashlytics.instance.recordError` to the `onError` parameter: + ```dart runZoned>(() async { // ... }, onError: Crashlytics.instance.recordError); -``` +``` ## Result If an error is caught, you should see the following messages in your logs: -``` + +```shell flutter: Flutter error caught by Crashlytics plugin: // OR if you use recordError for runZoned: flutter: Error caught by Crashlytics plugin : From c117ec00ff78a546e6b4302dadfb489c3aa86c84 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Mon, 20 Apr 2020 19:40:29 +0200 Subject: [PATCH 13/28] Update README.md --- packages/firebase_crashlytics/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_crashlytics/README.md b/packages/firebase_crashlytics/README.md index a9a945a58f3c..c8de5c9783f3 100644 --- a/packages/firebase_crashlytics/README.md +++ b/packages/firebase_crashlytics/README.md @@ -123,7 +123,7 @@ runZoned>(() async { If an error is caught, you should see the following messages in your logs: -```shell +```console flutter: Flutter error caught by Crashlytics plugin: // OR if you use recordError for runZoned: flutter: Error caught by Crashlytics plugin : From 5a46b56bc186582c8f9cbb3bb4484ca3f1ad91b4 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Thu, 23 Apr 2020 00:45:55 +0200 Subject: [PATCH 14/28] Add documentation --- packages/firebase_crashlytics/README.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/packages/firebase_crashlytics/README.md b/packages/firebase_crashlytics/README.md index c8de5c9783f3..a2954d0333b9 100644 --- a/packages/firebase_crashlytics/README.md +++ b/packages/firebase_crashlytics/README.md @@ -62,6 +62,18 @@ apply plugin: 'com.google.gms.google-services' apply plugin: 'com.google.firebase.crashlytics' ``` +4. Add the SDK dependencies in your **app-level** `build.gradle` file (`[project]/android/app/build.gradle`). + +```gradle +dependencies { + // Recommended: Add the Firebase SDK for Google Analytics. + implementation 'com.google.firebase:firebase-analytics:17.3.0' + + // Add the Firebase SDK for Crashlytics. + implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta04' +} +``` + *Note:* If this section is not completed, you will get an error like this: ```console From 03facb579349b6ecd4e683ea9dfa6b0524230e12 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Fri, 24 Apr 2020 03:03:39 +0200 Subject: [PATCH 15/28] Update CHANGELOG.md --- packages/firebase_crashlytics/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index 40bb0c2280a4..4c28871febad 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -1,6 +1,6 @@ ## 0.2.0 -* **Breaking**: Migration to the new Firebase Crashlytics SDK. Follow the [migration guide](https://firebase.google.com/docs/crashlytics/upgrade-sdk?platform=android) to update your app. +* **Breaking**: Migration to the new Firebase Crashlytics SDK. Follow the [migration guide](https://firebase.google.com/docs/crashlytics/upgrade-sdk?platform=android) (steps 1 and 2) to update your app. * **Breaking**: the following methods have been removed: * `setUserEmail` * `setUserName` From 146ba8f8618c3f2e0f59a586ae07327e4acc49cc Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Mon, 27 Apr 2020 19:20:33 +0200 Subject: [PATCH 16/28] Edit Gradle plugin version --- packages/firebase_crashlytics/README.md | 9 +++++---- packages/firebase_crashlytics/android/build.gradle | 2 +- .../firebase_crashlytics/example/android/build.gradle | 2 +- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/packages/firebase_crashlytics/README.md b/packages/firebase_crashlytics/README.md index a2954d0333b9..94f7950ef87c 100644 --- a/packages/firebase_crashlytics/README.md +++ b/packages/firebase_crashlytics/README.md @@ -46,8 +46,9 @@ buildscript { dependencies { // Check that you have the Google Services Gradle plugin v4.3.2 or later (if not, add it). classpath 'com.google.gms:google-services:4.3.3' + // Add the Crashlytics Gradle plugin. - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0' // ... you may have other classpaths } @@ -66,11 +67,11 @@ apply plugin: 'com.google.firebase.crashlytics' ```gradle dependencies { - // Recommended: Add the Firebase SDK for Google Analytics. - implementation 'com.google.firebase:firebase-analytics:17.3.0' + // Optional but recommended: Add the Firebase SDK for Google Analytics. + implementation 'com.google.firebase:firebase-analytics:17.4.0' // Add the Firebase SDK for Crashlytics. - implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta04' + implementation 'com.google.firebase:firebase-crashlytics:17.0.0' } ``` diff --git a/packages/firebase_crashlytics/android/build.gradle b/packages/firebase_crashlytics/android/build.gradle index 881c4986bc5f..2c00e17cbd33 100644 --- a/packages/firebase_crashlytics/android/build.gradle +++ b/packages/firebase_crashlytics/android/build.gradle @@ -34,7 +34,7 @@ android { } dependencies { - implementation 'com.google.firebase:firebase-crashlytics:17.0.0-beta04' + implementation 'com.google.firebase:firebase-crashlytics:17.0.0' implementation 'com.google.firebase:firebase-common:16.1.0' implementation 'androidx.annotation:annotation:1.1.0' } diff --git a/packages/firebase_crashlytics/example/android/build.gradle b/packages/firebase_crashlytics/example/android/build.gradle index 74c0ead08560..4e03aa21676f 100644 --- a/packages/firebase_crashlytics/example/android/build.gradle +++ b/packages/firebase_crashlytics/example/android/build.gradle @@ -7,7 +7,7 @@ buildscript { dependencies { classpath 'com.android.tools.build:gradle:3.3.2' classpath 'com.google.gms:google-services:4.3.0' - classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0-beta04' + classpath 'com.google.firebase:firebase-crashlytics-gradle:2.0.0' } } From 3c571edaea2c9d0966cb405fffece6e3fc34b115 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Fri, 8 May 2020 01:19:21 +0200 Subject: [PATCH 17/28] Update README.md --- packages/firebase_crashlytics/README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_crashlytics/README.md b/packages/firebase_crashlytics/README.md index 94f7950ef87c..0792594b724e 100644 --- a/packages/firebase_crashlytics/README.md +++ b/packages/firebase_crashlytics/README.md @@ -127,7 +127,7 @@ Overriding `FlutterError.onError` with `Crashlytics.instance.recordFlutterError` If you want to catch errors that occur in `runZoned`, you can supply `Crashlytics.instance.recordError` to the `onError` parameter: ```dart -runZoned>(() async { +runZonedGuarded>(() async { // ... }, onError: Crashlytics.instance.recordError); ``` From de71916fb33c72eb2b04e3072a0b4442979af3cc Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Fri, 8 May 2020 02:11:22 +0200 Subject: [PATCH 18/28] Replace `runZoned` by `runZonedGuarded` and update SDK constraints Co-authored-by: Michael Bui <25263378+MaikuB@users.noreply.github.com> --- packages/firebase_crashlytics/README.md | 11 +++++++---- packages/firebase_crashlytics/example/lib/main.dart | 11 +++++++---- packages/firebase_crashlytics/pubspec.yaml | 2 +- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/packages/firebase_crashlytics/README.md b/packages/firebase_crashlytics/README.md index 0792594b724e..57e4b79c277e 100644 --- a/packages/firebase_crashlytics/README.md +++ b/packages/firebase_crashlytics/README.md @@ -124,12 +124,15 @@ void main() { Overriding `FlutterError.onError` with `Crashlytics.instance.recordFlutterError` will automatically catch all errors that are thrown from within the Flutter framework. -If you want to catch errors that occur in `runZoned`, you can supply `Crashlytics.instance.recordError` to the `onError` parameter: +If you want to catch errors that occur in [`runZonedGuarded`](https://api.dart.dev/stable/dart-async/runZonedGuarded.html), you can supply `Crashlytics.instance.recordError` to the `onError` positioned parameter: ```dart -runZonedGuarded>(() async { +runZonedGuarded>( + () async { // ... - }, onError: Crashlytics.instance.recordError); + }, + Crashlytics.instance.recordError, +); ``` ## Result @@ -138,7 +141,7 @@ If an error is caught, you should see the following messages in your logs: ```console flutter: Flutter error caught by Crashlytics plugin: -// OR if you use recordError for runZoned: +// OR if you use recordError for runZonedGuarded: flutter: Error caught by Crashlytics plugin : // Exception, context, information, and stack trace in debug mode // OR if not in debug mode: diff --git a/packages/firebase_crashlytics/example/lib/main.dart b/packages/firebase_crashlytics/example/lib/main.dart index 5f2a9d04a689..2b3f5355bf46 100644 --- a/packages/firebase_crashlytics/example/lib/main.dart +++ b/packages/firebase_crashlytics/example/lib/main.dart @@ -17,9 +17,12 @@ void main() { // Pass all uncaught errors to Crashlytics. FlutterError.onError = Crashlytics.instance.recordFlutterError; - runZoned(() { - runApp(MyApp()); - }, onError: Crashlytics.instance.recordError); + runZonedGuarded( + () { + runApp(MyApp()); + }, + Crashlytics.instance.recordError, + ); } class MyApp extends StatefulWidget { @@ -72,7 +75,7 @@ class _MyAppState extends State { onPressed: () { // Example of an exception that does not get caught // by `FlutterError.onError` but is caught by the `onError` handler of - // `runZoned`. + // `runZonedGuarded`. Future.delayed(const Duration(seconds: 2), () { final List list = []; print(list[100]); diff --git a/packages/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/pubspec.yaml index 543cc9ab70e9..01d3d23b1e55 100644 --- a/packages/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/pubspec.yaml @@ -6,7 +6,7 @@ version: 0.2.0 homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/firebase_crashlytics environment: - sdk: ">=2.0.0-dev.28.0 <3.0.0" + sdk: ">=2.8.0 <3.0.0" flutter: ">=1.12.13+hotfix.4 <2.0.0" dependencies: From fa6501db5b18414c229e39c764ef17750bf83fd2 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Fri, 8 May 2020 21:12:27 +0200 Subject: [PATCH 19/28] Update Flutter SDK constraints --- packages/firebase_crashlytics/pubspec.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_crashlytics/pubspec.yaml b/packages/firebase_crashlytics/pubspec.yaml index 01d3d23b1e55..dbbb1d673f03 100644 --- a/packages/firebase_crashlytics/pubspec.yaml +++ b/packages/firebase_crashlytics/pubspec.yaml @@ -7,7 +7,7 @@ homepage: https://github.com/FirebaseExtended/flutterfire/tree/master/packages/f environment: sdk: ">=2.8.0 <3.0.0" - flutter: ">=1.12.13+hotfix.4 <2.0.0" + flutter: ">=1.17.0 <2.0.0" dependencies: flutter: From 0cfa89424975684d55bfea737ad068bf9b0d3bae Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Wed, 13 May 2020 21:08:54 +0200 Subject: [PATCH 20/28] Update CHANGELOG.md --- packages/firebase_crashlytics/CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index 4c28871febad..030870799ad0 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -1,3 +1,5 @@ +# Changelog + ## 0.2.0 * **Breaking**: Migration to the new Firebase Crashlytics SDK. Follow the [migration guide](https://firebase.google.com/docs/crashlytics/upgrade-sdk?platform=android) (steps 1 and 2) to update your app. From d69d9185e598707c5f0caaa41e17c049b45c74a7 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Mon, 18 May 2020 21:52:07 +0200 Subject: [PATCH 21/28] Update UIApplicationDelegate for example iOs app --- packages/firebase_crashlytics/example/ios/Runner/AppDelegate.h | 2 ++ packages/firebase_crashlytics/example/ios/Runner/AppDelegate.m | 2 ++ 2 files changed, 4 insertions(+) diff --git a/packages/firebase_crashlytics/example/ios/Runner/AppDelegate.h b/packages/firebase_crashlytics/example/ios/Runner/AppDelegate.h index 36e21bbf9cf4..dabd2bac3daf 100644 --- a/packages/firebase_crashlytics/example/ios/Runner/AppDelegate.h +++ b/packages/firebase_crashlytics/example/ios/Runner/AppDelegate.h @@ -1,6 +1,8 @@ #import #import +@import Firebase; + @interface AppDelegate : FlutterAppDelegate @end diff --git a/packages/firebase_crashlytics/example/ios/Runner/AppDelegate.m b/packages/firebase_crashlytics/example/ios/Runner/AppDelegate.m index 59a72e90be12..ba737d9a8e7b 100644 --- a/packages/firebase_crashlytics/example/ios/Runner/AppDelegate.m +++ b/packages/firebase_crashlytics/example/ios/Runner/AppDelegate.m @@ -5,6 +5,8 @@ @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + [FIRApp configure]; + [GeneratedPluginRegistrant registerWithRegistry:self]; // Override point for customization after application launch. return [super application:application didFinishLaunchingWithOptions:launchOptions]; From 4fc48358b41b819b243f24a93453f37ad1326324 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Wed, 20 May 2020 20:26:50 +0200 Subject: [PATCH 22/28] Fix bug about key extraction on iOs --- packages/firebase_crashlytics/CHANGELOG.md | 1 + .../darwin/Classes/FirebaseCrashlyticsPlugin.m | 12 ++++-------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index 030870799ad0..30444d261845 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -8,6 +8,7 @@ * `setUserName` * `getVersion` * `isDebuggable` +* Fixes a bug that prevented keys from being set on iOs devices. ## 0.1.3+3 diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index 7dab2b140ee3..54de661a7bc5 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -46,17 +46,13 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result NSArray *keys = call.arguments[@"keys"]; for (NSDictionary *key in keys) { if ([@"int" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:call.arguments[@"value"] - forKey:call.arguments[@"key"]]; + [[FIRCrashlytics crashlytics] setCustomValue:key[@"value"] forKey:key[@"key"]]; } else if ([@"double" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:call.arguments[@"value"] - forKey:call.arguments[@"key"]]; + [[FIRCrashlytics crashlytics] setCustomValue:key[@"value"] forKey:key[@"key"]]; } else if ([@"string" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:call.arguments[@"value"] - forKey:call.arguments[@"key"]]; + [[FIRCrashlytics crashlytics] setCustomValue:key[@"value"] forKey:key[@"key"]]; } else if ([@"boolean" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:call.arguments[@"value"] - forKey:call.arguments[@"key"]]; + [[FIRCrashlytics crashlytics] setCustomValue:key[@"value"] forKey:key[@"key"]]; } } From bda47bcc2adfa8289f35b0cba6dd2a830e43221f Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Thu, 21 May 2020 05:56:39 +0200 Subject: [PATCH 23/28] Implement [setCustomKey] on Dart side --- packages/firebase_crashlytics/CHANGELOG.md | 1 + .../FirebaseCrashlyticsPlugin.java | 35 ++++------ .../Classes/FirebaseCrashlyticsPlugin.m | 14 +--- .../example/lib/main.dart | 2 +- .../example/test_driver/crashlytics.dart | 11 ++-- .../lib/src/firebase_crashlytics.dart | 64 ++++--------------- .../test/firebase_crashlytics_test.dart | 45 +++++-------- 7 files changed, 48 insertions(+), 124 deletions(-) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index 30444d261845..24583f8e1199 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -8,6 +8,7 @@ * `setUserName` * `getVersion` * `isDebuggable` +* **Breaking**: the methods `setInt`, `setDouble`, `setString` and `setBool` have been replaced by `setCustomKey`. * Fixes a bug that prevented keys from being set on iOs devices. ## 0.1.3+3 diff --git a/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java b/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java index f688661c1901..a3496e0796c2 100644 --- a/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java +++ b/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java @@ -54,37 +54,24 @@ public void onMethodCall(MethodCall call, Result result) { final FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); if (call.method.equals("Crashlytics#onError")) { // Add logs. - List logs = call.argument("logs"); - for (String log : logs) { - crashlytics.log(log); + final List logs = call.argument("logs"); + for (String l : logs) { + crashlytics.log(l); } // Set keys. - List> keys = call.argument("keys"); - for (Map key : keys) { - switch ((String) key.get("type")) { - case "int": - crashlytics.setCustomKey((String) key.get("key"), (int) key.get("value")); - break; - case "double": - crashlytics.setCustomKey((String) key.get("key"), (double) key.get("value")); - break; - case "string": - crashlytics.setCustomKey((String) key.get("key"), (String) key.get("value")); - break; - case "boolean": - crashlytics.setCustomKey((String) key.get("key"), (boolean) key.get("value")); - break; - } + final Map keys = call.argument("keys"); + for (String key : keys.keySet()) { + crashlytics.setCustomKey(key, (String) keys.get(key)); } // Report crash. - String dartExceptionMessage = (String) call.argument("exception"); - Exception exception = new Exception(dartExceptionMessage); - List> errorElements = call.argument("stackTraceElements"); - List elements = new ArrayList<>(); + final String dartExceptionMessage = (String) call.argument("exception"); + final Exception exception = new Exception(dartExceptionMessage); + final List> errorElements = call.argument("stackTraceElements"); + final List elements = new ArrayList<>(); for (Map errorElement : errorElements) { - StackTraceElement stackTraceElement = generateStackTraceElement(errorElement); + final StackTraceElement stackTraceElement = generateStackTraceElement(errorElement); if (stackTraceElement != null) { elements.add(stackTraceElement); } diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index 54de661a7bc5..888b0308fbfa 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -43,17 +43,9 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } // Set keys. - NSArray *keys = call.arguments[@"keys"]; - for (NSDictionary *key in keys) { - if ([@"int" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:key[@"value"] forKey:key[@"key"]]; - } else if ([@"double" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:key[@"value"] forKey:key[@"key"]]; - } else if ([@"string" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:key[@"value"] forKey:key[@"key"]]; - } else if ([@"boolean" isEqualToString:key[@"type"]]) { - [[FIRCrashlytics crashlytics] setCustomValue:key[@"value"] forKey:key[@"key"]]; - } + NSDictionary *keys = call.arguments[@"keys"]; + for (NSString *key in keys) { + [[FIRCrashlytics crashlytics] setCustomValue:keys[key] forKey:key]; } // Add additional information from the Flutter framework to the exception reported in diff --git a/packages/firebase_crashlytics/example/lib/main.dart b/packages/firebase_crashlytics/example/lib/main.dart index 2b3f5355bf46..e814af971722 100644 --- a/packages/firebase_crashlytics/example/lib/main.dart +++ b/packages/firebase_crashlytics/example/lib/main.dart @@ -49,7 +49,7 @@ class _MyAppState extends State { FlatButton( child: const Text('Key'), onPressed: () { - Crashlytics.instance.setString('foo', 'bar'); + Crashlytics.instance.setCustomKey('foo', 'bar'); }), FlatButton( child: const Text('Log'), diff --git a/packages/firebase_crashlytics/example/test_driver/crashlytics.dart b/packages/firebase_crashlytics/example/test_driver/crashlytics.dart index cee89ed0b75b..4dc4e9c31338 100644 --- a/packages/firebase_crashlytics/example/test_driver/crashlytics.dart +++ b/packages/firebase_crashlytics/example/test_driver/crashlytics.dart @@ -18,11 +18,12 @@ void main() { // This is currently only testing that we can log errors without crashing. final Crashlytics crashlytics = Crashlytics.instance; await crashlytics.setUserIdentifier('hello'); - crashlytics.setBool('testBool', true); - crashlytics.setInt('testInt', 42); - crashlytics.setDouble('testDouble', 42.0); - crashlytics.setString('testString', 'bar'); - Crashlytics.instance.log('testing'); + crashlytics + ..setCustomKey('testBool', true) + ..setCustomKey('testInt', 42) + ..setCustomKey('testDouble', 42.0) + ..setCustomKey('testString', 'bar') + ..log('testing'); await crashlytics.recordFlutterError(FlutterErrorDetails( exception: 'testing', stack: StackTrace.fromString(''), diff --git a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart index 24b4b6de0a60..4898eb517f69 100644 --- a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart +++ b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart @@ -7,18 +7,18 @@ part of firebase_crashlytics; /// /// You can get an instance by calling `Crashlytics.instance`. class Crashlytics { - static final Crashlytics instance = Crashlytics(); + static final instance = Crashlytics(); /// Set to true to have errors sent to Crashlytics while in debug mode. By /// default this is false. - bool enableInDevMode = false; + var enableInDevMode = false; /// Keys to be included with report. - final Map _keys = {}; + final _keys = {}; /// Logs to be included with report. - final ListQueue _logs = ListQueue(15); - int _logSize = 0; + final _logs = ListQueue(15); + var _logSize = 0; @visibleForTesting static const MethodChannel channel = @@ -68,33 +68,16 @@ class Crashlytics { } } - void _setValue(String key, dynamic value) { + /// Sets a [value] to be associated with a given [key] for your crash data. + /// + /// The [value] will be converted to a string by calling [toString] on it. + void setCustomKey(String key, dynamic value) { // Check that only 64 keys are set. if (_keys.containsKey(key) || _keys.length <= 64) { - _keys[key] = value; + _keys[key] = value.toString(); } } - /// Sets a value to be associated with a given key for your crash data. - void setBool(String key, bool value) { - _setValue(key, value); - } - - /// Sets a value to be associated with a given key for your crash data. - void setDouble(String key, double value) { - _setValue(key, value); - } - - /// Sets a value to be associated with a given key for your crash data. - void setInt(String key, int value) { - _setValue(key, value); - } - - /// Sets a value to be associated with a given key for your crash data. - void setString(String key, String value) { - _setValue(key, value); - } - /// Specify a user identifier which will be visible in the Crashlytics UI. /// Please be mindful of end-user's privacy. Future setUserIdentifier(String identifier) async { @@ -102,31 +85,6 @@ class Crashlytics { {'identifier': identifier}); } - List> _prepareKeys() { - final List> crashlyticsKeys = >[]; - for (String key in _keys.keys) { - final dynamic value = _keys[key]; - - final Map crashlyticsKey = { - 'key': key, - 'value': value - }; - - if (value is int) { - crashlyticsKey['type'] = 'int'; - } else if (value is double) { - crashlyticsKey['type'] = 'double'; - } else if (value is String) { - crashlyticsKey['type'] = 'string'; - } else if (value is bool) { - crashlyticsKey['type'] = 'boolean'; - } - crashlyticsKeys.add(crashlyticsKey); - } - - return crashlyticsKeys; - } - @visibleForTesting List> getStackTraceElements(List lines) { final List> elements = >[]; @@ -231,7 +189,7 @@ class Crashlytics { 'information': _information, 'stackTraceElements': stackTraceElements, 'logs': _logs.toList(), - 'keys': _prepareKeys(), + 'keys': _keys, }); // Print result. diff --git a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart index 346a0b8e9ed5..a503144a5e65 100644 --- a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart +++ b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart @@ -44,12 +44,13 @@ void main() { ], context: ErrorDescription('foo context'), ); - crashlytics.enableInDevMode = true; - crashlytics.log('foo'); - crashlytics.setBool('testBool', true); - crashlytics.setInt('testInt', 42); - crashlytics.setDouble('testDouble', 42.0); - crashlytics.setString('testString', 'bar'); + crashlytics + ..enableInDevMode = true + ..log('foo') + ..setCustomKey('testBool', true) + ..setCustomKey('testInt', 42) + ..setCustomKey('testDouble', 42.0) + ..setCustomKey('testString', 'bar'); await crashlytics.recordFlutterError(details); expect(log[0].method, 'Crashlytics#onError'); expect(log[0].arguments['exception'], 'foo exception'); @@ -57,18 +58,10 @@ void main() { expect(log[0].arguments['information'], 'test message\nsecond message'); expect(log[0].arguments['logs'], isNotEmpty); expect(log[0].arguments['logs'], contains('foo')); - expect(log[0].arguments['keys'][0]['key'], 'testBool'); - expect(log[0].arguments['keys'][0]['value'], isTrue); - expect(log[0].arguments['keys'][0]['type'], 'boolean'); - expect(log[0].arguments['keys'][1]['key'], 'testInt'); - expect(log[0].arguments['keys'][1]['value'], 42); - expect(log[0].arguments['keys'][1]['type'], 'int'); - expect(log[0].arguments['keys'][2]['key'], 'testDouble'); - expect(log[0].arguments['keys'][2]['value'], 42.0); - expect(log[0].arguments['keys'][2]['type'], 'double'); - expect(log[0].arguments['keys'][3]['key'], 'testString'); - expect(log[0].arguments['keys'][3]['value'], 'bar'); - expect(log[0].arguments['keys'][3]['type'], 'string'); + expect(log[0].arguments['keys']['testBool'], 'true'); + expect(log[0].arguments['keys']['testInt'], '42'); + expect(log[0].arguments['keys']['testDouble'], '42.0'); + expect(log[0].arguments['keys']['testString'], 'bar'); }); test('recordError', () async { @@ -81,18 +74,10 @@ void main() { expect(log[0].arguments['context'], "context"); expect(log[0].arguments['logs'], isNotEmpty); expect(log[0].arguments['logs'], contains('foo')); - expect(log[0].arguments['keys'][0]['key'], 'testBool'); - expect(log[0].arguments['keys'][0]['value'], isTrue); - expect(log[0].arguments['keys'][0]['type'], 'boolean'); - expect(log[0].arguments['keys'][1]['key'], 'testInt'); - expect(log[0].arguments['keys'][1]['value'], 42); - expect(log[0].arguments['keys'][1]['type'], 'int'); - expect(log[0].arguments['keys'][2]['key'], 'testDouble'); - expect(log[0].arguments['keys'][2]['value'], 42.0); - expect(log[0].arguments['keys'][2]['type'], 'double'); - expect(log[0].arguments['keys'][3]['key'], 'testString'); - expect(log[0].arguments['keys'][3]['value'], 'bar'); - expect(log[0].arguments['keys'][3]['type'], 'string'); + expect(log[0].arguments['keys']['testBool'], 'true'); + expect(log[0].arguments['keys']['testInt'], '42'); + expect(log[0].arguments['keys']['testDouble'], '42.0'); + expect(log[0].arguments['keys']['testString'], 'bar'); }); test('crash', () { From 497e3f9a46d202b63dcb9f71d392d68878ff355f Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Thu, 21 May 2020 06:12:02 +0200 Subject: [PATCH 24/28] Update packages/firebase_crashlytics/CHANGELOG.md Co-authored-by: Jason Parrott --- packages/firebase_crashlytics/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index 24583f8e1199..8b7ba528739a 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -9,7 +9,7 @@ * `getVersion` * `isDebuggable` * **Breaking**: the methods `setInt`, `setDouble`, `setString` and `setBool` have been replaced by `setCustomKey`. -* Fixes a bug that prevented keys from being set on iOs devices. +* Fixes a bug that prevented keys from being set on iOS devices. ## 0.1.3+3 From 1adeca91dc262195b222d475465f01bb60e9c847 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Thu, 21 May 2020 06:32:05 +0200 Subject: [PATCH 25/28] Check that [value] passed to [setCustomKey] is not null --- packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart index 4898eb517f69..b6e70d35a4c6 100644 --- a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart +++ b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart @@ -71,7 +71,9 @@ class Crashlytics { /// Sets a [value] to be associated with a given [key] for your crash data. /// /// The [value] will be converted to a string by calling [toString] on it. + /// An error will be thrown if it is null. void setCustomKey(String key, dynamic value) { + ArgumentError.checkNotNull(value, 'value'); // Check that only 64 keys are set. if (_keys.containsKey(key) || _keys.length <= 64) { _keys[key] = value.toString(); From 324dcf666f456119a8507c31adc5f1b59e185521 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Mon, 1 Jun 2020 04:48:11 +0200 Subject: [PATCH 26/28] Update CHANGELOG --- packages/firebase_crashlytics/CHANGELOG.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index 8b7ba528739a..1bea46759e50 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -2,13 +2,13 @@ ## 0.2.0 -* **Breaking**: Migration to the new Firebase Crashlytics SDK. Follow the [migration guide](https://firebase.google.com/docs/crashlytics/upgrade-sdk?platform=android) (steps 1 and 2) to update your app. -* **Breaking**: the following methods have been removed: +* **Breaking change**: Migration to the new Firebase Crashlytics SDK. Follow the [migration guide](https://firebase.google.com/docs/crashlytics/upgrade-sdk?platform=android) (steps 1 and 2) to update your app. +* **Breaking change**: the following methods have been removed: * `setUserEmail` * `setUserName` * `getVersion` * `isDebuggable` -* **Breaking**: the methods `setInt`, `setDouble`, `setString` and `setBool` have been replaced by `setCustomKey`. +* **Breaking change**: the methods `setInt`, `setDouble`, `setString` and `setBool` have been replaced by `setCustomKey`. * Fixes a bug that prevented keys from being set on iOS devices. ## 0.1.3+3 From 0c883fa485852515614a90bba12460a317061658 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Sat, 4 Jul 2020 23:51:34 +0200 Subject: [PATCH 27/28] Send logs and keys are they are set --- packages/firebase_crashlytics/CHANGELOG.md | 1 + .../FirebaseCrashlyticsPlugin.java | 21 +++---- .../Classes/FirebaseCrashlyticsPlugin.m | 21 +++---- .../lib/firebase_crashlytics.dart | 2 - .../lib/src/firebase_crashlytics.dart | 62 ++++++++----------- 5 files changed, 46 insertions(+), 61 deletions(-) diff --git a/packages/firebase_crashlytics/CHANGELOG.md b/packages/firebase_crashlytics/CHANGELOG.md index fdc7cff20fcc..718a52735171 100644 --- a/packages/firebase_crashlytics/CHANGELOG.md +++ b/packages/firebase_crashlytics/CHANGELOG.md @@ -9,6 +9,7 @@ * `getVersion` * `isDebuggable` * **Breaking change**: the methods `setInt`, `setDouble`, `setString` and `setBool` have been replaced by `setCustomKey`. +* Logs and keys are sent to Crashlytics as they're set. * Fixes a bug that prevented keys from being set on iOS devices. ## 0.1.4+1 diff --git a/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java b/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java index a3496e0796c2..3bc4fa763aa1 100644 --- a/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java +++ b/packages/firebase_crashlytics/android/src/main/java/io/flutter/plugins/firebase/crashlytics/firebasecrashlytics/FirebaseCrashlyticsPlugin.java @@ -53,18 +53,6 @@ public static void registerWith(Registrar registrar) { public void onMethodCall(MethodCall call, Result result) { final FirebaseCrashlytics crashlytics = FirebaseCrashlytics.getInstance(); if (call.method.equals("Crashlytics#onError")) { - // Add logs. - final List logs = call.argument("logs"); - for (String l : logs) { - crashlytics.log(l); - } - - // Set keys. - final Map keys = call.argument("keys"); - for (String key : keys.keySet()) { - crashlytics.setCustomKey(key, (String) keys.get(key)); - } - // Report crash. final String dartExceptionMessage = (String) call.argument("exception"); final Exception exception = new Exception(dartExceptionMessage); @@ -93,6 +81,15 @@ public void onMethodCall(MethodCall call, Result result) { } else if (call.method.equals("Crashlytics#setUserIdentifier")) { crashlytics.setUserId((String) call.argument("identifier")); result.success(null); + } else if (call.method.equals("Crashlytics#setKey")) { + final String key = (String) call.argument("key"); + final String value = (String) call.argument("value"); + crashlytics.setCustomKey(key, value); + result.success(null); + } else if (call.method.equals("Crashlytics#log")) { + final String msg = (String) call.argument("log"); + crashlytics.log(msg); + result.success(null); } else { result.notImplemented(); } diff --git a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m index 888b0308fbfa..0fb2b6ede8c0 100644 --- a/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m +++ b/packages/firebase_crashlytics/darwin/Classes/FirebaseCrashlyticsPlugin.m @@ -36,18 +36,6 @@ - (instancetype)init { - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result { if ([@"Crashlytics#onError" isEqualToString:call.method]) { - // Add logs. - NSArray *logs = call.arguments[@"logs"]; - for (NSString *log in logs) { - [[FIRCrashlytics crashlytics] logWithFormat:@"%@", log]; - } - - // Set keys. - NSDictionary *keys = call.arguments[@"keys"]; - for (NSString *key in keys) { - [[FIRCrashlytics crashlytics] setCustomValue:keys[key] forKey:key]; - } - // Add additional information from the Flutter framework to the exception reported in // Crashlytics. NSString *information = call.arguments[@"information"]; @@ -78,6 +66,15 @@ - (void)handleMethodCall:(FlutterMethodCall *)call result:(FlutterResult)result } else if ([@"Crashlytics#setUserIdentifier" isEqualToString:call.method]) { [[FIRCrashlytics crashlytics] setUserID:call.arguments[@"identifier"]]; result(nil); + } else if ([@"Crashlytics#setKey" isEqualToString:call.method]) { + NSString *key = call.arguments[@"key"]; + NSString *value = call.arguments[@"value"]; + [[FIRCrashlytics crashlytics] setCustomValue:value forKey:key]; + result(nil); + } else if ([@"Crashlytics#log" isEqualToString:call.method]) { + NSString *msg = call.arguments[@"log"]; + [[FIRCrashlytics crashlytics] logWithFormat:@"%@", msg]; + result(nil); } else { result(FlutterMethodNotImplemented); } diff --git a/packages/firebase_crashlytics/lib/firebase_crashlytics.dart b/packages/firebase_crashlytics/lib/firebase_crashlytics.dart index a57738b63f43..5f198bda8ee6 100644 --- a/packages/firebase_crashlytics/lib/firebase_crashlytics.dart +++ b/packages/firebase_crashlytics/lib/firebase_crashlytics.dart @@ -5,8 +5,6 @@ library firebase_crashlytics; import 'dart:async'; -import 'dart:collection'; -import 'dart:typed_data'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; diff --git a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart index 173416fce9f1..b5873e8c246e 100644 --- a/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart +++ b/packages/firebase_crashlytics/lib/src/firebase_crashlytics.dart @@ -13,12 +13,7 @@ class Crashlytics { /// default this is false. var enableInDevMode = false; - /// Keys to be included with report. - final _keys = {}; - - /// Logs to be included with report. - final _logs = ListQueue(15); - var _logSize = 0; + bool get _shouldReport => !kDebugMode || enableInDevMode; @visibleForTesting static const MethodChannel channel = @@ -43,10 +38,12 @@ class Crashlytics { /// Submits a report of a non-fatal error. /// /// For errors generated by the Flutter framework, use [recordFlutterError] instead. - Future recordError(dynamic exception, StackTrace stack, - {dynamic context}) async { + Future recordError( + dynamic exception, + StackTrace stack, { + dynamic context, + }) async { print('Error caught by Crashlytics plugin :'); - _recordError(exception, stack, context: context); } @@ -54,30 +51,31 @@ class Crashlytics { throw StateError('Error thrown by Crashlytics plugin'); } - /// Add text logging that will be sent with your next report. `msg` will be - /// printed to the console when in debug mode. Each report has a rolling max - /// of 64k of logs, older logs are removed to allow newer logs to fit within - /// the limit. - void log(String msg) { - _logSize += Uint8List.fromList(msg.codeUnits).length; - _logs.add(msg); - // Remove oldest log till logSize is no more than 64K. - while (_logSize > 65536) { - final String first = _logs.removeFirst(); - _logSize -= Uint8List.fromList(first.codeUnits).length; - } + /// Add text logging that will be sent to Crashlytics. + Future log(String msg) async { + if (!_shouldReport) return; + ArgumentError.checkNotNull(msg, 'msg'); + return channel.invokeMethod( + 'Crashlytics#log', + {'log': msg}, + ); } /// Sets a [value] to be associated with a given [key] for your crash data. /// /// The [value] will be converted to a string by calling [toString] on it. /// An error will be thrown if it is null. - void setCustomKey(String key, dynamic value) { + Future setCustomKey(String key, dynamic value) async { + if (!_shouldReport) return; + ArgumentError.checkNotNull(key, 'key'); ArgumentError.checkNotNull(value, 'value'); - // Check that only 64 keys are set. - if (_keys.containsKey(key) || _keys.length <= 64) { - _keys[key] = value.toString(); - } + return channel.invokeMethod( + 'Crashlytics#setKey', + { + 'key': key, + 'value': value.toString(), + }, + ); } /// Specify a user identifier which will be visible in the Crashlytics UI. @@ -142,12 +140,7 @@ class Crashlytics { Iterable information, bool printDetails, }) async { - bool inDebugMode = false; - if (!enableInDevMode) { - assert(inDebugMode = true); - } - - printDetails ??= inDebugMode; + printDetails ??= kDebugMode; final String _information = (information == null || information.isEmpty) ? '' @@ -168,7 +161,8 @@ class Crashlytics { // that Flutter developers are used to seeing. if (stack != null) print('\n$stack'); } - if (!inDebugMode || enableInDevMode) { + + if (_shouldReport) { // The stack trace can be null. To avoid the following exception: // Invalid argument(s): Cannot create a Trace from null. // We can check for null and provide an empty stack trace. @@ -190,8 +184,6 @@ class Crashlytics { 'context': '$context', 'information': _information, 'stackTraceElements': stackTraceElements, - 'logs': _logs.toList(), - 'keys': _keys, }); // Print result. From 66d2d1412356e1f64db384cce168c7ff16b09e66 Mon Sep 17 00:00:00 2001 From: Axel Ogereau-Peltier <49279289+axel-op@users.noreply.github.com> Date: Sun, 5 Jul 2020 00:15:58 +0200 Subject: [PATCH 28/28] Update tests --- .../test/firebase_crashlytics_test.dart | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart index cd5f551fd1cf..25d707f4e4f2 100644 --- a/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart +++ b/packages/firebase_crashlytics/test/firebase_crashlytics_test.dart @@ -25,6 +25,8 @@ void main() { case 'Crashlytics#onError': return 'Error reported to Crashlytics.'; case 'Crashlytics#setUserIdentifier': + case 'Crashlytics#setKey': + case 'Crashlytics#log': return true; default: return false; @@ -33,6 +35,25 @@ void main() { log.clear(); }); + test('log', () async { + crashlytics.enableInDevMode = true; + final msg = 'foo'; + await crashlytics.log(msg); + expect(log[0].method, 'Crashlytics#log'); + expect(log[0].arguments['log'], msg); + }); + + test('setKeys', () async { + crashlytics.enableInDevMode = true; + final key = 'testKey'; + // All values are converted to Strings by Dart code + final value = 'testValue'; + await crashlytics.setCustomKey(key, value); + expect(log[0].method, 'Crashlytics#setKey'); + expect(log[0].arguments['key'], key); + expect(log[0].arguments['value'], value); + }); + test('recordFlutterError', () async { final FlutterErrorDetails details = FlutterErrorDetails( exception: 'foo exception', @@ -44,29 +65,16 @@ void main() { ], context: ErrorDescription('foo context'), ); - crashlytics - ..enableInDevMode = true - ..log('foo') - ..setCustomKey('testBool', true) - ..setCustomKey('testInt', 42) - ..setCustomKey('testDouble', 42.0) - ..setCustomKey('testString', 'bar'); + crashlytics.enableInDevMode = true; await crashlytics.recordFlutterError(details); expect(log[0].method, 'Crashlytics#onError'); expect(log[0].arguments['exception'], 'foo exception'); expect(log[0].arguments['context'], 'foo context'); expect(log[0].arguments['information'], 'test message\nsecond message'); - expect(log[0].arguments['logs'], isNotEmpty); - expect(log[0].arguments['logs'], contains('foo')); - expect(log[0].arguments['keys']['testBool'], 'true'); - expect(log[0].arguments['keys']['testInt'], '42'); - expect(log[0].arguments['keys']['testDouble'], '42.0'); - expect(log[0].arguments['keys']['testString'], 'bar'); }); test('recordError', () async { crashlytics.enableInDevMode = true; - crashlytics.log('foo'); await crashlytics.recordError('foo exception', null, context: "context"); expect(log[0].method, 'Crashlytics#onError'); expect(log[0].arguments['exception'], 'foo exception'); @@ -76,12 +84,6 @@ void main() { log[0].arguments['stackTraceElements'], contains(containsPair('file', 'firebase_crashlytics_test.dart')), ); - expect(log[0].arguments['logs'], isNotEmpty); - expect(log[0].arguments['logs'], contains('foo')); - expect(log[0].arguments['keys']['testBool'], 'true'); - expect(log[0].arguments['keys']['testInt'], '42'); - expect(log[0].arguments['keys']['testDouble'], '42.0'); - expect(log[0].arguments['keys']['testString'], 'bar'); }); test('crash', () {