Skip to content

Commit

Permalink
[firebase_crashlytics]Firebase Crashlytics plugin (flutter#1080)
Browse files Browse the repository at this point in the history
* Add Crashlytics support
  • Loading branch information
kroikie authored Mar 20, 2019
1 parent 7e7149b commit 5c20e7d
Show file tree
Hide file tree
Showing 77 changed files with 2,817 additions and 0 deletions.
8 changes: 8 additions & 0 deletions packages/firebase_crashlytics/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
.DS_Store
.dart_tool/

.packages
.pub/
pubspec.lock

build/
10 changes: 10 additions & 0 deletions packages/firebase_crashlytics/.metadata
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b
channel: beta

project_type: plugin
5 changes: 5 additions & 0 deletions packages/firebase_crashlytics/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
## 0.0.1

* Initial release of Firebase Crashlytics plugin.
This version reports uncaught errors as non-fatal exceptions in the
Firebase console.
27 changes: 27 additions & 0 deletions packages/firebase_crashlytics/LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// Copyright 2019 The Chromium Authors. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are
// met:
//
// * Redistributions of source code must retain the above copyright
// notice, this list of conditions and the following disclaimer.
// * Redistributions in binary form must reproduce the above
// copyright notice, this list of conditions and the following disclaimer
// in the documentation and/or other materials provided with the
// distribution.
// * Neither the name of Google Inc. nor the names of its
// contributors may be used to endorse or promote products derived from
// this software without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
104 changes: 104 additions & 0 deletions packages/firebase_crashlytics/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
# firebase_crashlytics plugin

A Flutter plugin to use the [Firebase Crashlytics Service](https://firebase.google.com/docs/crashlytics/).

[![pub package](https://img.shields.io/pub/v/firebase_crashlytics.svg)](https://pub.dartlang.org/packages/firebase_crashlytics)

For Flutter plugins for other Firebase products, see [FlutterFire.md](https://github.com/flutter/plugins/blob/master/FlutterFire.md).

*Note*: This plugin is still under development, and some APIs might not be available yet. [Feedback](https://github.com/flutter/flutter/issues) and [Pull Requests](https://github.com/flutter/plugins/pulls) are most welcome!

## Usage

### Import the firebase_crashlytics plugin
To use the firebase_crashlytics plugin, follow the [plugin installation instructions](https://pub.dartlang.org/packages/firebase_crashlytics#pub-pkg-tab-installing).

### Android integration

Enable the Google services by configuring the Gradle scripts as such.

1. Add Fabric repository to the `[project]/android/build.gradle` file.
```
repositories {
google()
jcenter()
// Additional repository for fabric resources
maven {
url 'https://maven.fabric.io/public'
}
}
```

2. Add the classpaths to the `[project]/android/build.gradle` file.
```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.2.0'
// Add fabric classpath
classpath 'io.fabric.tools:gradle:1.26.1'
}
```

2. Add the apply plugins to the `[project]/android/app/build.gradle` file.
```gradle
// ADD THIS AT THE BOTTOM
apply plugin: 'io.fabric'
apply plugin: 'com.google.gms.google-services'
```

*Note:* If this section is not completed you will get an error like this:
```
java.lang.IllegalStateException:
Default FirebaseApp is not initialized in this process [package name].
Make sure to call FirebaseApp.initializeApp(Context) first.
```

*Note:* When you are debugging on Android, use a device or AVD with Google Play services.
Otherwise you will not be able to use Firebase Crashlytics.

### iOS Integration

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. If on Xcode 10 Add your app's built Info.plist location to the Build Phase's Input Files field.
Eg: `$(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
// This is only to be used for confirming that reports are being
// submitted as expected. It is not intended to be used for everyday
// development.
Crashlytics.instance.reportInDevMode = true;
// Pass all uncaught errors to Crashlytics.
FlutterError.onError = (FlutterErrorDetails details) {
Crashlytics.instance.onError(details);
};
runApp(MyApp());
}
```

## Example

See the [example application](https://github.com/flutter/plugins/tree/master/packages/firebase_crashlytics/example) source
for a complete sample app using the Firebase Crashlytics.

## Issues and feedback

Please file [issues](https://github.com/flutter/flutter/issues/new)
to send feedback or report a bug. Thank you!
8 changes: 8 additions & 0 deletions packages/firebase_crashlytics/android/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
42 changes: 42 additions & 0 deletions packages/firebase_crashlytics/android/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
group 'io.flutter.plugins.firebase.crashlytics.firebasecrashlytics'
version '1.0-SNAPSHOT'

buildscript {
repositories {
google()
jcenter()
}

dependencies {
classpath 'com.android.tools.build:gradle:3.3.1'
}
}

rootProject.allprojects {
repositories {
google()
jcenter()
maven {
url 'https://maven.fabric.io/public'
}
}
}

apply plugin: 'com.android.library'

android {
compileSdkVersion 27

defaultConfig {
minSdkVersion 16
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
lintOptions {
disable 'InvalidPackage'
}
}

dependencies {
implementation 'com.google.firebase:firebase-core:16.0.7'
implementation 'com.crashlytics.sdk.android:crashlytics:2.9.9'
}
1 change: 1 addition & 0 deletions packages/firebase_crashlytics/android/gradle.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
org.gradle.jvmargs=-Xmx1536M
1 change: 1 addition & 0 deletions packages/firebase_crashlytics/android/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
rootProject.name = 'firebase_crashlytics'
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="io.flutter.plugins.firebase.crashlytics.firebasecrashlytics">
</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package io.flutter.plugins.firebase.crashlytics.firebasecrashlytics;

import android.util.Log;
import com.crashlytics.android.Crashlytics;
import io.fabric.sdk.android.Fabric;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import io.flutter.plugin.common.PluginRegistry.Registrar;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/** FirebaseCrashlyticsPlugin */
public class FirebaseCrashlyticsPlugin implements MethodCallHandler {

public static final String TAG = "CrashlyticsPlugin";

/** Plugin registration. */
public static void registerWith(Registrar registrar) {
final MethodChannel channel =
new MethodChannel(registrar.messenger(), "plugins.flutter.io/firebase_crashlytics");
channel.setMethodCallHandler(new FirebaseCrashlyticsPlugin());
}

@Override
public void onMethodCall(MethodCall call, Result result) {
if (call.method.equals("Crashlytics#onError")) {
// Add logs.
List<String> logs = call.argument("logs");
for (String log : logs) {
Crashlytics.log(log);
}

// Set keys.
List<Map<String, Object>> keys = call.argument("keys");
for (Map<String, Object> key : keys) {
switch ((String) key.get("type")) {
case "int":
Crashlytics.setInt((String) key.get("key"), (int) key.get("value"));
break;
case "double":
Crashlytics.setDouble((String) key.get("key"), (double) key.get("value"));
break;
case "string":
Crashlytics.setString((String) key.get("key"), (String) key.get("value"));
break;
case "boolean":
Crashlytics.setBool((String) key.get("key"), (boolean) key.get("value"));
break;
}
}

// Report crash.
Exception exception = new Exception("Dart Error");
List<Map<String, String>> errorElements = call.argument("stackTraceElements");
List<StackTraceElement> elements = new ArrayList<>();
for (Map<String, String> errorElement : errorElements) {
StackTraceElement stackTraceElement = generateStackTraceElement(errorElement);
if (stackTraceElement != null) {
elements.add(stackTraceElement);
}
}
exception.setStackTrace(elements.toArray(new StackTraceElement[elements.size()]));

Crashlytics.setString("exception", (String) call.argument("exception"));
Crashlytics.logException(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"));
result.success(null);
} else {
result.notImplemented();
}
}

/**
* Extract StackTraceElement from Dart stack trace element.
*
* @param errorElement Map representing the parts of a Dart error.
* @return Stack trace element to be used as part of an Exception stack trace.
*/
private StackTraceElement generateStackTraceElement(Map<String, String> errorElement) {
try {
String fileName = errorElement.get("file");
String lineNumber = errorElement.get("line");
String className = errorElement.get("class");
String methodName = errorElement.get("method");

return new StackTraceElement(className, methodName, fileName, Integer.parseInt(lineNumber));
} catch (Exception e) {
Log.e(TAG, "Unable to generate stack trace element from Dart side error.");
return null;
}
}
}
Loading

0 comments on commit 5c20e7d

Please sign in to comment.