Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for Crashlytics didCrashOnPreviousExecution & setCustomKey #492

Merged
merged 2 commits into from
Sep 8, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
50 changes: 48 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -113,9 +113,11 @@ To help ensure this plugin is kept updated, new features are added and bugfixes
- [setUserProperty](#setuserproperty)
- [Crashlytics](#crashlytics)
- [setCrashlyticsCollectionEnabled](#setcrashlyticscollectionenabled)
- [didCrashOnPreviousExecution](#didCrashOnPreviousExecution)
- [isCrashlyticsCollectionEnabled](#iscrashlyticscollectionenabled)
- [setCrashlyticsUserId](#setcrashlyticsuserid)
- [sendCrash](#sendcrash)
- [setCrashlyticsCustomKey](#setCrashlyticsCustomKey)
- [logMessage](#logmessage)
- [logError](#logerror)
- [Authentication](#authentication)
Expand Down Expand Up @@ -2007,6 +2009,22 @@ FirebasePlugin.setCrashlyticsCollectionEnabled(shouldSetEnabled, function(){
});
```

### didCrashOnPreviousExecution
Checks whether the app crashed on its previous run.

**Parameters**:
- {function} success - callback function which will be invoked on success.
Will be passed a {boolean} indicating whether the app crashed on its previous run.
- {function} error - (optional) callback function which will be passed a {string} error message as an argument

```javascript
FirebasePlugin.didCrashOnPreviousExecution(function(didCrashOnPreviousExecution){
console.log(`Did crash on previous execution: ${didCrashOnPreviousExecution}`));
}, function(error){
console.error(`Error getting Crashlytics did crash on previous execution: ${error}`);
});
```

### isCrashlyticsCollectionEnabled
Indicates whether Crashlytics collection setting is currently enabled.

Expand All @@ -2023,7 +2041,6 @@ FirebasePlugin.isCrashlyticsCollectionEnabled(function(enabled){
});
```


### setCrashlyticsUserId
Set Crashlytics user identifier.

Expand All @@ -2039,7 +2056,6 @@ See [the Firebase docs for more](https://firebase.google.com/docs/crashlytics/cu
FirebasePlugin.setCrashlyticsUserId("user_id");
```


### sendCrash
Simulates (causes) a fatal native crash which causes a crash event to be sent to Crashlytics (useful for testing).
See [the Firebase documentation](https://firebase.google.com/docs/crashlytics/force-a-crash?authuser=0#force_a_crash_to_test_your_implementation) regarding crash testing.
Expand All @@ -2051,6 +2067,36 @@ Crashes will appear under `Event type = "Crashes"` in the Crashlytics console.
FirebasePlugin.sendCrash();
```

### setCrashlyticsCustomKey
Records a custom key and value to be associated with subsequent fatal and non-fatal reports.

Multiple calls to this method with the same key will update the value for that key.

The value of any key at the time of a fatal or non-fatal event will be associated with that event.

Keys and associated values are visible in the session view on the Firebase Crashlytics console.

A maximum of 64 key/value pairs can be written, and new keys added beyond that limit will be ignored. Keys or values that exceed 1024 characters will be truncated.

**Parameters**:
- {string} key - A unique key
- {string | number | boolean} value - A value to be associated with the given key
- {function} success - (optional) callback function which will be invoked on success
- {function} error - (optional) callback function which will be passed a {string} error message as an argument

```javascript
FirebasePlugin.setCrashlyticsCustomKey('number', 3.5, function(){
console.log("set custom key: number, with value: 3.5");
},function(error){
console.error("Failed to set-custom key", error);
});
FirebasePlugin.setCrashlyticsCustomKey('bool', true);
FirebasePlugin.setCrashlyticsCustomKey('string', 'Ipsum lorem');
// Following is just used to trigger report for Firebase
FirebasePlugin.logMessage("about to send a crash for testing!");
FirebasePlugin.sendCrash();
```

### logMessage
Sends a crash-related log message that will appear in the `Logs` section of the next native crash event.
Note: if you don't then crash, the message won't be sent!
Expand Down
57 changes: 57 additions & 0 deletions src/android/FirebasePlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,9 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
} else if (action.equals("getInfo")) {
this.getInfo(callbackContext);
return true;
} else if (action.equals("didCrashOnPreviousExecution")) {
this.didCrashOnPreviousExecution(callbackContext);
return true;
} else if (action.equals("setConfigSettings")) {
this.setConfigSettings(callbackContext, args.getJSONObject(0));
return true;
Expand Down Expand Up @@ -351,6 +354,9 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
} else if (action.equals("clearAllNotifications")) {
this.clearAllNotifications(callbackContext);
return true;
} else if (action.equals("setCrashlyticsCustomKey")) {
this.setCrashlyticsCustomKey(callbackContext, args);
return true;
} else if (action.equals("logMessage")) {
logMessage(args, callbackContext);
return true;
Expand Down Expand Up @@ -757,6 +763,41 @@ public void run() {
});
}

private void setCrashlyticsCustomKey(final CallbackContext callbackContext, final JSONArray data) {
cordova.getThreadPool().execute(new Runnable() {
public void run() {
if(isCrashlyticsEnabled()){
try {
Object value = data.get(1);
// Floats can be omitted since they're not passed through JSONArray
if(value instanceof Integer) {
firebaseCrashlytics.setCustomKey(data.getString(0), data.getInt(1));
callbackContext.success();
}else if (value instanceof Double) {
firebaseCrashlytics.setCustomKey(data.getString(0), data.getDouble(1));
callbackContext.success();
}else if (value instanceof Long) {
firebaseCrashlytics.setCustomKey(data.getString(0), data.getLong(1));
callbackContext.success();
}else if (value instanceof String) {
firebaseCrashlytics.setCustomKey(data.getString(0), data.getString(1));
callbackContext.success();
}else if (value instanceof Boolean) {
firebaseCrashlytics.setCustomKey(data.getString(0), data.getBoolean(1));
callbackContext.success();
}else {
callbackContext.error("Cannot set custom key - Value is not an acceptable type");
}
}catch(Exception e) {
handleExceptionWithContext(e, callbackContext);
}
}else{
callbackContext.error("Cannot set custom key - Crashlytics collection is disabled");
}
}
});
}

private void logMessage(final JSONArray data,
final CallbackContext callbackContext) {

Expand Down Expand Up @@ -922,6 +963,22 @@ public void run() {
});
}

private void didCrashOnPreviousExecution(final CallbackContext callbackContext) {
cordova.getThreadPool().execute(new Runnable() {
public void run() {
if(isCrashlyticsEnabled()){
try {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK, firebaseCrashlytics.didCrashOnPreviousExecution()));
} catch (Exception e) {
handleExceptionWithContext(e, callbackContext);
}
} else{
callbackContext.error("Cannot query didCrashOnPreviousExecution - Crashlytics collection is disabled");
}
}
});
}

private void setConfigSettings(final CallbackContext callbackContext, final JSONObject config) {
cordova.getThreadPool().execute(new Runnable() {
public void run() {
Expand Down
2 changes: 2 additions & 0 deletions src/ios/FirebasePlugin.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@
// Crashlytics
- (void)setCrashlyticsCollectionEnabled:(CDVInvokedUrlCommand*)command;
- (void)isCrashlyticsCollectionEnabled:(CDVInvokedUrlCommand*)command;
- (void)didCrashOnPreviousExecution:(CDVInvokedUrlCommand *)command;
- (void)setCrashlyticsCustomKey:(CDVInvokedUrlCommand *)command;
- (void)logError:(CDVInvokedUrlCommand*)command;
- (void)logMessage:(CDVInvokedUrlCommand*)command;
- (void)sendCrash:(CDVInvokedUrlCommand*)command;
Expand Down
51 changes: 44 additions & 7 deletions src/ios/FirebasePlugin.m
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ - (void)pluginInitialize {
if([self getGooglePlistFlagWithDefaultValue:FIREBASE_PERFORMANCE_COLLECTION_ENABLED defaultValue:YES]){
[self setPreferenceFlag:FIREBASE_PERFORMANCE_COLLECTION_ENABLED flag:YES];
}

// Set actionable categories if pn-actions.json exist in bundle
[self setActionableNotifications];

Expand All @@ -90,7 +90,7 @@ - (void)pluginInitialize {

// Dynamic actions from pn-actions.json
- (void)setActionableNotifications {

// Parse JSON
NSString *path = [[NSBundle mainBundle] pathForResource:@"pn-actions" ofType:@"json"];
NSData *data = [NSData dataWithContentsOfFile:path];
Expand All @@ -102,20 +102,20 @@ - (void)setActionableNotifications {
for (NSDictionary *item in actionsArray) {
NSMutableArray *buttons = [NSMutableArray new];
NSString *category = [item objectForKey:@"category"];

NSArray *actions = [item objectForKey:@"actions"];
for (NSDictionary *action in actions) {
NSString *actionId = [action objectForKey:@"id"];
NSString *actionTitle = [action objectForKey:@"title"];

[buttons addObject:[UNNotificationAction actionWithIdentifier:actionId
title:NSLocalizedString(actionTitle, nil) options:UNNotificationActionOptionNone]];
}

[categories addObject:[UNNotificationCategory categoryWithIdentifier:category
actions:buttons intentIdentifiers:@[] options:UNNotificationCategoryOptionNone]];
}

// Initialize categories
[[UNUserNotificationCenter currentNotificationCenter] setNotificationCategories:categories];
}
Expand Down Expand Up @@ -285,7 +285,7 @@ - (void)grantPermission:(CDVInvokedUrlCommand *)command {
[self registerForRemoteNotifications];
}
[self handleBoolResultWithPotentialError:error command:command result:granted];

}@catch (NSException *exception) {
[self handlePluginExceptionWithContext:exception :command];
}
Expand Down Expand Up @@ -1086,6 +1086,24 @@ -(BOOL)isCrashlyticsEnabled{
return [self getPreferenceFlag:FIREBASE_CRASHLYTICS_COLLECTION_ENABLED];
}

-(void)didCrashOnPreviousExecution:(CDVInvokedUrlCommand *)command {
[self.commandDelegate runInBackground:^{
@try {
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];

if(![self isCrashlyticsEnabled]){
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Cannot query didCrashOnPreviousExecution - Crashlytics collection is disabled"];
} else {
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:[[FIRCrashlytics crashlytics] didCrashDuringPreviousExecution]];
}

[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}@catch (NSException *exception) {
[self handlePluginExceptionWithContext:exception :command];
}
}];
}

- (void)logError:(CDVInvokedUrlCommand *)command {
[self.commandDelegate runInBackground:^{
NSString* errorMessage = [command.arguments objectAtIndex:0];
Expand Down Expand Up @@ -1141,6 +1159,25 @@ - (void)logMessage:(CDVInvokedUrlCommand*)command{
}];
}

- (void)setCrashlyticsCustomKey:(CDVInvokedUrlCommand*)command{
[self.commandDelegate runInBackground:^{
@try {
NSString* key = [command argumentAtIndex:0 withDefault:@""];
NSString* value = [command argumentAtIndex:1 withDefault:@""];
CDVPluginResult *pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];

if(![self isCrashlyticsEnabled]){
pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"Cannot set custom key/valuee - Crashlytics collection is disabled"];
}else {
[[FIRCrashlytics crashlytics] setCustomValue: value forKey: key];
}
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}@catch (NSException *exception) {
[self handlePluginExceptionWithContext:exception :command];
}
}];
}

- (void)sendCrash:(CDVInvokedUrlCommand*)command{
assert(NO);
}
Expand Down