diff --git a/README.md b/README.md index 76a3dea..e5f5323 100755 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ It requires Cordova 6.x or newer (tested on 7.0.0) and has APIs for iOS and Andr The iOS version uses Fabric SDK 1.7.5 and Crashlytics SDK 3.10.1 framework bundles which are located in `lib/ios`. -The Android version uses Gradle to get the Fabric SDK (`io.fabric.tools:gradle:1.+`) and the Crashlytics SDK (`com.crashlytics.sdk.android:crashlytics:2.9.1`) from Maven repositories when the plugin is added. +The Android version uses Gradle to get the Fabric SDK (`io.fabric.tools:gradle:1.+`) and the Crashlytics SDK (`com.crashlytics.sdk.android:crashlytics:2.9.3`) from Maven repositories when the plugin is added. # Install @@ -133,6 +133,32 @@ The desired package versions are pulled from [package.json](./package.json): } ``` +## Opt-in reporting + +By default this plugin will automatically intialize the Fabric SDK on app startup and therefore assumes implicit user consent that information such as crash reports or analytics can be collected. + +Under the [EU's GDPR rules](https://www.eugdpr.org/) you may need to ensure that your users have given consent. + +This means you may need to [enable opt-in reporting](https://docs.fabric.io/apple/crashlytics/advanced-setup.html#enable-opt-in-reporting) to ask users consent before intializing the Fabric SDK which immediately begins reporting Answers and Crashlytics data. + +This plugin can be configured for manual initialization by setting the `FABRIC_AUTO_INIT` plugin variable to `false` when the plugin is installed: +```bash +cordova plugin add cordova-fabric-plugin --variable FABRIC_AUTO_INIT=false --variable FABRIC_API_KEY=XXX --variable FABRIC_API_SECRET=xxx +``` + +This enables you to gain user consent before manually intializing the SDK by calling: +```javascript +window.fabric.core.initialize(); +``` + +You can check if the plugin has already been initialized with: + +```javascript +window.fabric.core.isInitialized(function(initialized){ + console.log("Fabric SDK " + (initialized ? "is" : "is not") + " initialized"); +}); +``` + # Contributing If you wish to contribute please see `CONTRIBUTING.md`. diff --git a/hooks/lib/ios-helper.js b/hooks/lib/ios-helper.js index c3d4d71..36ad047 100644 --- a/hooks/lib/ios-helper.js +++ b/hooks/lib/ios-helper.js @@ -20,7 +20,7 @@ module.exports = { addShellScriptBuildPhase: function (context, xcodeProjectPath) { var pluginConfig = utilities.getPluginConfig("ios"); - var xcode = context.requireCordovaModule("xcode"); + var xcode = require("xcode"); // Read and parse the XCode project (.pxbproj) from disk. // File format information: http://www.monobjc.net/xcode-project-file-format.html @@ -75,7 +75,7 @@ module.exports = { */ removeShellScriptBuildPhase: function (context, xcodeProjectPath) { - var xcode = context.requireCordovaModule("xcode"); + var xcode = require("xcode"); // Read and parse the XCode project (.pxbproj) from disk. // File format information: http://www.monobjc.net/xcode-project-file-format.html diff --git a/lib/ios/Crashlytics.framework/Crashlytics b/lib/ios/Crashlytics.framework/Crashlytics index 426b699..79eb516 100755 Binary files a/lib/ios/Crashlytics.framework/Crashlytics and b/lib/ios/Crashlytics.framework/Crashlytics differ diff --git a/lib/ios/Crashlytics.framework/Info.plist b/lib/ios/Crashlytics.framework/Info.plist index dad66d9..bfa2831 100644 Binary files a/lib/ios/Crashlytics.framework/Info.plist and b/lib/ios/Crashlytics.framework/Info.plist differ diff --git a/lib/ios/Crashlytics.framework/submit b/lib/ios/Crashlytics.framework/submit index b7e84f3..3fda5cf 100755 Binary files a/lib/ios/Crashlytics.framework/submit and b/lib/ios/Crashlytics.framework/submit differ diff --git a/lib/ios/Crashlytics.framework/uploadDSYM b/lib/ios/Crashlytics.framework/uploadDSYM index 971940b..8deb7c9 100755 Binary files a/lib/ios/Crashlytics.framework/uploadDSYM and b/lib/ios/Crashlytics.framework/uploadDSYM differ diff --git a/lib/ios/Fabric.framework/Fabric b/lib/ios/Fabric.framework/Fabric index bfb04ac..3057fdf 100755 Binary files a/lib/ios/Fabric.framework/Fabric and b/lib/ios/Fabric.framework/Fabric differ diff --git a/lib/ios/Fabric.framework/Info.plist b/lib/ios/Fabric.framework/Info.plist index 5664ef6..46b5064 100644 Binary files a/lib/ios/Fabric.framework/Info.plist and b/lib/ios/Fabric.framework/Info.plist differ diff --git a/lib/ios/Fabric.framework/uploadDSYM b/lib/ios/Fabric.framework/uploadDSYM index 9cb23e7..2e823ac 100755 Binary files a/lib/ios/Fabric.framework/uploadDSYM and b/lib/ios/Fabric.framework/uploadDSYM differ diff --git a/lib/ios/README.txt b/lib/ios/README.txt index 1fb9a7c..67db293 100644 --- a/lib/ios/README.txt +++ b/lib/ios/README.txt @@ -6,10 +6,10 @@ https://cocoapods.org/pods/Crashlytics Podspec references: -https://github.com/CocoaPods/Specs/blob/master/Specs/Fabric/1.6.11/Fabric.podspec.json -https://github.com/CocoaPods/Specs/blob/master/Specs/Crashlytics/3.8.5/Crashlytics.podspec.json +https://github.com/CocoaPods/Specs/blob/master/Specs/Fabric/1.8.2/Fabric.podspec.json +https://github.com/CocoaPods/Specs/blob/master/Specs/Crashlytics/3.11.1/Crashlytics.podspec.json Framework package ZIPs: -https://kit-downloads.fabric.io/cocoapods/fabric/1.7.5/fabric.zip -https://kit-downloads.fabric.io/cocoapods/crashlytics/3.10.1/crashlytics.zip +https://kit-downloads.fabric.io/cocoapods/fabric/1.8.2/fabric.zip +https://kit-downloads.fabric.io/cocoapods/crashlytics/3.11.1/crashlytics.zip diff --git a/package.json b/package.json index c46606d..af65028 100644 --- a/package.json +++ b/package.json @@ -57,4 +57,4 @@ "type": "opencollective", "url": "https://opencollective.com/FabricPlugin" } -} \ No newline at end of file +} diff --git a/plugin.xml b/plugin.xml index cf2357d..1a07f83 100755 --- a/plugin.xml +++ b/plugin.xml @@ -1,6 +1,10 @@ - + cordova-fabric-plugin Cordova Fabric.io Plugin @@ -9,6 +13,7 @@ + @@ -41,6 +46,7 @@ + @@ -62,6 +68,8 @@ APIKey $FABRIC_API_KEY + AutoInit + $FABRIC_AUTO_INIT Kits diff --git a/src/android/FabricPlugin.java b/src/android/FabricPlugin.java index 9a822ec..3dec90e 100755 --- a/src/android/FabricPlugin.java +++ b/src/android/FabricPlugin.java @@ -23,6 +23,10 @@ import com.crashlytics.android.answers.SignUpEvent; import com.crashlytics.android.answers.StartCheckoutEvent; +import android.app.Activity; +import android.content.pm.ApplicationInfo; +import android.content.pm.PackageManager; +import android.os.Bundle; import android.util.Log; import java.lang.reflect.Method; @@ -36,17 +40,35 @@ public class FabricPlugin extends CordovaPlugin { private final String pluginName = "FabricPlugin"; + private final String autoInitKey = "FabricPlugin_AutoInit"; + + private boolean initialized = false; @Override protected void pluginInitialize() { - Fabric.with(this.cordova.getActivity().getApplicationContext(), new Crashlytics(), new Answers()); + boolean autoInit = true; + try { + Activity activity = this.cordova.getActivity(); + ApplicationInfo ai = activity.getPackageManager().getApplicationInfo(activity.getPackageName(), PackageManager.GET_META_DATA); + Bundle bundle = ai.metaData; + autoInit = bundle.getBoolean(autoInitKey); + } catch (Exception e) { + Log.e(pluginName, "Failed to load FABRIC_AUTO_INIT meta-data: " + e.getMessage()); + } + if(autoInit){ + initialize(); + } } @Override public boolean execute(final String action, final JSONArray data, final CallbackContext callbackContext) { Log.d(pluginName, pluginName + " called with options: " + data); - if (action.equals("addLog")) { + if (action.equals("initialize")) { + initialize(data, callbackContext); + } else if (action.equals("isInitialized")) { + isInitialized(data, callbackContext); + } else if (action.equals("addLog")) { addLog(data, callbackContext); } else if (action.equals("sendCrash")) { sendCrash(data, callbackContext); @@ -101,6 +123,24 @@ public boolean execute(final String action, final JSONArray data, final Callback return true; } + private void initialize(final JSONArray data, + final CallbackContext callbackContext) { + initialize(); + callbackContext.success(); + } + + private void initialize(){ + if(!initialized){ + Fabric.with(this.cordova.getActivity().getApplicationContext(), new Crashlytics(), new Answers()); + initialized = true; + } + } + + private void isInitialized(final JSONArray data, + final CallbackContext callbackContext) { + callbackContext.success(initialized ? 1 : 0); + } + /* Crashlytics Events */ private void addLog(final JSONArray data, diff --git a/src/android/build-extras.gradle b/src/android/build-extras.gradle index 1e1c7b9..e103df4 100644 --- a/src/android/build-extras.gradle +++ b/src/android/build-extras.gradle @@ -22,7 +22,7 @@ repositories { } dependencies { - compile('com.crashlytics.sdk.android:crashlytics:2.9.1@aar') { + compile('com.crashlytics.sdk.android:crashlytics:2.9.3@aar') { transitive = true; } } diff --git a/src/ios/FabricPlugin.m b/src/ios/FabricPlugin.m index 0b19210..7fdccf7 100755 --- a/src/ios/FabricPlugin.m +++ b/src/ios/FabricPlugin.m @@ -11,6 +11,11 @@ @interface FabricPlugin : CDVPlugin +@property (nonatomic) BOOL initialized; +// Fabric +-(void) initialize:(CDVInvokedUrlCommand *)command; +-(void) isInitialized:(CDVInvokedUrlCommand *)command; + // Answers - (void)sendPurchase:(CDVInvokedUrlCommand*)command; - (void)sendAddToCart:(CDVInvokedUrlCommand*)command; @@ -43,11 +48,37 @@ - (void)sendNonFatalCrash:(CDVInvokedUrlCommand*)command; @implementation FabricPlugin +@synthesize initialized; + #pragma mark - Plugin Initialization - (void)pluginInitialize { - [Fabric with:@[[Crashlytics class], [Answers class]]]; + initialized = false; + NSDictionary* fabricSettings = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"Fabric"]; + bool autoInit = [[fabricSettings objectForKey:@"AutoInit"] boolValue]; + if(autoInit){ + [self _initialize]; + } +} + +- (void) _initialize +{ + if(!initialized){ + [Fabric with:@[[Crashlytics class], [Answers class]]]; + initialized = true; + } +} + +-(void) initialize:(CDVInvokedUrlCommand *)command { + [self _initialize]; + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; +} + +-(void) isInitialized:(CDVInvokedUrlCommand *)command{ + CDVPluginResult* pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:initialized]; + [self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId]; } #pragma mark - Answers diff --git a/typings/cordova-fabric-plugin.d.ts b/typings/cordova-fabric-plugin.d.ts index df08217..de933b5 100644 --- a/typings/cordova-fabric-plugin.d.ts +++ b/typings/cordova-fabric-plugin.d.ts @@ -6,6 +6,23 @@ declare module FabricPlugin { interface FabricPluginStatic { + /** + * Manually initializes the plugin. + * Only relevant if the plugin --variable FABRIC_AUTO_INIT=false + * + * https://docs.fabric.io/android/crashlytics/advanced-setup.html#enable-opt-in-reporting + * https://docs.fabric.io/apple/crashlytics/advanced-setup.html#enable-opt-in-reporting + */ + initialize: (success: () => void) => void; + + /** + * Checks if the plugin is initialized. + * Only relevant if the plugin --variable FABRIC_AUTO_INIT=false + * + * https://docs.fabric.io/android/crashlytics/advanced-setup.html#enable-opt-in-reporting + * https://docs.fabric.io/apple/crashlytics/advanced-setup.html#enable-opt-in-reporting + */ + isInitialized: (success: (initialized: boolean) => void) => void; /** * API for interacting with the Crashlytics kit. diff --git a/www/FabricPlugin.es6 b/www/FabricPlugin.es6 index 77df9ce..348234c 100644 --- a/www/FabricPlugin.es6 +++ b/www/FabricPlugin.es6 @@ -11,6 +11,15 @@ class FabricPlugin { exec(null, null, this.pluginCallName(), method, parameters); } + initialize(success) { + exec(success, null, this.pluginCallName(), "initialize", []); + } + + isInitialized(success) { + exec(success, null, this.pluginCallName(), "isInitialized", []); + } + } + module.exports = new FabricPlugin(); diff --git a/www/FabricPlugin.js b/www/FabricPlugin.js index 74fc2b5..646edaf 100644 --- a/www/FabricPlugin.js +++ b/www/FabricPlugin.js @@ -21,6 +21,16 @@ var FabricPlugin = (function () { value: function execPlugin(method, parameters) { exec(null, null, this.pluginCallName(), method, parameters); } + }, { + key: 'initialize', + value: function initialize(success) { + exec(success, null, this.pluginCallName(), "initialize", []); + } + }, { + key: 'isInitialized', + value: function isInitialized(success) { + exec(success, null, this.pluginCallName(), "isInitialized", []); + } }]); return FabricPlugin;