Hello,
I want to share what I did to handle Javascript Exceptions in native code.
Today I use good crash analytic tool www.crashlytics.com that helps me to analyse exceptions and crashes. But what happens if something happens wrong in Ionic? I use Ionic word because Ionic framework filters all exceptions and therefore for most errors the Exception seems like:
ReferenceError: bfbfbbf is not defined
at new <anonymous> (file:///android_asset/www/js/groups/groupsController.js:62:2)
at d (file:///android_asset/www/lib/js/ionic/1.0.0-beta.11-ionic.bundle.min.js:65:479)
at Object.instantiate (file:///android_asset/www/lib/js/ionic/1.0.0-beta.11-ionic.bundle.min.js:66:103)
at file:///android_asset/www/lib/js/ionic/1.0.0-beta.11-ionic.bundle.min.js:97:467
at d (file:///android_asset/www/lib/js/ionic/1.0.0-beta.11-ionic.bundle.min.js:340:27957)
at file:///android_asset/www/lib/js/ionic/1.0.0-beta.11-ionic.bundle.min.js:340:28433
at N (file:///android_asset/www/lib/js/ionic/1.0.0-beta.11-ionic.bundle.min.js:85:92)
at g (file:///android_asset/www/lib/js/ionic/1.0.0-beta.11-ionic.bundle.min.js:78:61)
at N (file:///android_asset/www/lib/js/ionic/1.0.0-beta.11-ionic.bundle.min.js:85:33)
at g (file:///android_asset/www/lib/js/ionic/1.0.0-beta.11-ionic.bundle.min.js:78:82)
So how to catch it and send Exception report?
app.config(function($provide) {
$provide.decorator("$exceptionHandler", function($delegate, $injector) {
return function(exception, cause) {
if (false) { //(appState !== "...") { // We want to only send the error in this case
$delegate(exception, cause);
} else {
//appState == null;
var MyCordovaService = $injector.get("MyCordovaService");
console.debug({reason: exception, message: exception.message, stack: exception.stack});
var data = {
message: "Exception: " + exception.message,
stack: exception.stack
};
// here we send report to native side
MyCordovaService.reportClientError(data).then(function(data) {
console.debug('reportClientError success', data);
}, function(error) {
console.debug('reportClientError fail!', error);
});
// Call The original Angular Exception Handler
$delegate(exception, cause);
}
};
});
});
Android side:
private boolean reportClientToCrashlytics(final JSONArray args, final CallbackContext callbackContext) {
this.cordova.getThreadPool().execute( new Runnable() {
public void run() {
try {
JSONObject root = args.optJSONObject(0);
Log.d(TAG, "sendAcceptEvent: " + root.toString());
JSONObject eventStructure = root.getJSONObject("eventStructure");
String message = eventStructure.getString("message");
String stack = eventStructure.getString("stack");
try {
throw new WmIonicException(message + "\n==============================" + stack);
} catch (Exception e) {
e.printStackTrace();
WmAnalyticsReport.reportException(e);
}
} catch (JSONException e) {
e.printStackTrace();
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, ContactManager.NOT_SUPPORTED_ERROR));
}
}
});
return true;
}
public class WmAnalyticsReport {
private WmAnalyticsReport() {}
public static void reportException(Throwable e){
Crashlytics.logException(e);
}
}