diff --git a/CHANGELOG.md b/CHANGELOG.md index 9cb867f5c..aba06a601 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,12 @@ # Changelog -## [15.0.2](https://github.com/Instabug/Instabug-Flutter/compare/v14.3.0...15.0.2) (Jul 7, 2025) +## [Unreleased](https://github.com/Instabug/Instabug-Flutter/compare/v15.0.2...dev) + +### Added + +- Add new APIs to support NDK Crashes. ([#607](https://github.com/Instabug/Instabug-Flutter/pull/607)) + +## [15.0.2](https://github.com/Instabug/Instabug-Flutter/compare/v14.3.0...15.0.2) (Jul 7, 2025) ### Added @@ -20,7 +26,6 @@ - Bump Instabug Android SDK to v14.3.1 ([#577](https://github.com/Instabug/Instabug-Flutter/pull/577)). [See release notes](https://github.com/Instabug/Instabug-Android/releases/tag/v14.3.1). - ## [14.3.0](https://github.com/Instabug/Instabug-Flutter/compare/v14.1.0...14.3.0) (April 21, 2025) ### Added diff --git a/android/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java b/android/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java index 075d0da69..8a1831959 100644 --- a/android/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java +++ b/android/src/main/java/com/instabug/flutter/modules/CrashReportingApi.java @@ -70,4 +70,12 @@ public void sendNonFatalError(@NonNull String jsonCrash, @Nullable Map +#include +#include +#include +#include "crasher_2.h" + +/************* SIGSEGV *******************************/ +JNIEXPORT void JNICALL +Java_com_example_InstabugSample_ndk_CppNativeLib_causeSIGSEGVCrash(JNIEnv *env, jobject thiz) { + causeSIGSEGVCrashF1(); +} + +/*****************************************************/ + +/************* SIGABRT *******************************/ +JNIEXPORT void JNICALL +Java_com_example_InstabugSample_ndk_CppNativeLib_causeSIGABRTCrash(JNIEnv *env, jobject thiz) { + causeSIGABRTCrashF1(); +} +/****************************************************/ + +/************* SIGFPE *******************************/ +JNIEXPORT void JNICALL +Java_com_example_InstabugSample_ndk_CppNativeLib_causeSIGFPECrash(JNIEnv *env, jobject thiz) { + causeSIGFPECrashF1(); +} +/***************************************************/ + +/************* SIGILL *******************************/ + +JNIEXPORT void JNICALL +Java_com_example_InstabugSample_ndk_CppNativeLib_causeSIGILLCrash(JNIEnv *env, jobject thiz) { + causeSIGILLCrashF1(); +} +/***************************************************/ + +/************* SIGBUS *******************************/ +JNIEXPORT void JNICALL +Java_com_example_InstabugSample_ndk_CppNativeLib_causeSIGBUSCrash(JNIEnv *env, jobject thiz) { + causeSIGBUSCrashF1(); +} +/***************************************************/ + +/************* SIGTRAP *******************************/ +JNIEXPORT void JNICALL +Java_com_example_InstabugSample_ndk_CppNativeLib_causeSIGTRAPCrash(JNIEnv *env, jobject thiz) { + causeSIGTRAPCrashF1(); +} +/***************************************************/ diff --git a/example/android/app/src/main/cpp/crasher_2.c b/example/android/app/src/main/cpp/crasher_2.c new file mode 100644 index 000000000..5aac24df8 --- /dev/null +++ b/example/android/app/src/main/cpp/crasher_2.c @@ -0,0 +1,47 @@ + + +#include +#include +#include +#include +#include "crasher_3.h" + +/************* SIGSEGV *******************************/ +void causeSIGSEGVCrashF1() { + causeSIGSEGVCrashF2(); +} +/*****************************************************/ + +/************* SIGABRT *******************************/ +void causeSIGABRTCrashF1() { + causeSIGABRTCrashF2(); +} +/****************************************************/ + +/************* SIGFPE *******************************/ + + +void causeSIGFPECrashF1() { + causeSIGFPECrashF2(); +} +/***************************************************/ + +/************* SIGILL *******************************/ + +void causeSIGILLCrashF1() { + causeSIGILLCrashF2(); +} +/***************************************************/ + +/************* SIGBUS *******************************/ + +void causeSIGBUSCrashF1() { + causeSIGBUSCrashF2(); +} +/***************************************************/ + +/************* SIGTRAP *******************************/ +void causeSIGTRAPCrashF1() { + causeSIGTRAPCrashF2(); +} +/***************************************************/ diff --git a/example/android/app/src/main/cpp/crasher_2.h b/example/android/app/src/main/cpp/crasher_2.h new file mode 100644 index 000000000..d435af057 --- /dev/null +++ b/example/android/app/src/main/cpp/crasher_2.h @@ -0,0 +1,58 @@ + + +/************* SIGSEGV *******************************/ +void causeSIGSEGVCrashF3(); + +void causeSIGSEGVCrashF2(); + +void causeSIGSEGVCrashF1(); + +/*****************************************************/ + +/************* SIGABRT *******************************/ +void causeSIGABRTCrashF3(); + +void causeSIGABRTCrashF2(); + +void causeSIGABRTCrashF1(); + +/****************************************************/ + +/************* SIGFPE *******************************/ + +int causeSIGFPECrashF3(); + +void causeSIGFPECrashF2(); + +void causeSIGFPECrashF1(); + +/***************************************************/ + +/************* SIGILL *******************************/ + +void causeSIGILLCrashF3(); + +void causeSIGILLCrashF2(); + +void causeSIGILLCrashF1(); + +/***************************************************/ + +/************* SIGBUS *******************************/ + +void causeSIGBUSCrashF3(); + +void causeSIGBUSCrashF2(); + +void causeSIGBUSCrashF1(); + +/***************************************************/ + +/************* SIGTRAP *******************************/ + +void causeSIGTRAPCrashF3(); + +void causeSIGTRAPCrashF2(); + +void causeSIGTRAPCrashF1(); +/***************************************************/ diff --git a/example/android/app/src/main/cpp/crasher_3.c b/example/android/app/src/main/cpp/crasher_3.c new file mode 100644 index 000000000..c53f5fbc8 --- /dev/null +++ b/example/android/app/src/main/cpp/crasher_3.c @@ -0,0 +1,44 @@ + +#pragma GCC optimize ("O0") +#include +#include +#include +#include +#include "crasher_4.h" + +/************* SIGSEGV *******************************/ +void causeSIGSEGVCrashF2() { + causeSIGSEGVCrashF3(NULL); +} +/*****************************************************/ + +/************* SIGABRT *******************************/ +void causeSIGABRTCrashF2() { + causeSIGABRTCrashF3(); +} +/****************************************************/ + +/************* SIGFPE *******************************/ +void causeSIGFPECrashF2() { + unsigned int *bad_pointer = (unsigned int *)(0xdeadbeef); + *bad_pointer=0xfeedface; +} +/***************************************************/ + +/************* SIGILL *******************************/ +void causeSIGILLCrashF2() { + causeSIGILLCrashF3(); +} +/***************************************************/ + +/************* SIGBUS *******************************/ +void causeSIGBUSCrashF2() { + causeSIGBUSCrashF3(); +} +/***************************************************/ + +/************* SIGTRAP *******************************/ +void causeSIGTRAPCrashF2() { + causeSIGTRAPCrashF3(); +} +/***************************************************/ diff --git a/example/android/app/src/main/cpp/crasher_3.h b/example/android/app/src/main/cpp/crasher_3.h new file mode 100644 index 000000000..ed4039612 --- /dev/null +++ b/example/android/app/src/main/cpp/crasher_3.h @@ -0,0 +1,24 @@ + +/************* SIGSEGV *******************************/ +void causeSIGSEGVCrashF2(); +/*****************************************************/ + +/************* SIGABRT *******************************/ +void causeSIGABRTCrashF2(); +/****************************************************/ + +/************* SIGFPE *******************************/ +void causeSIGFPECrashF2(); +/***************************************************/ + +/************* SIGILL *******************************/ +void causeSIGILLCrashF2(); +/***************************************************/ + +/************* SIGBUS *******************************/ +void causeSIGBUSCrashF2(); +/***************************************************/ + +/************* SIGTRAP *******************************/ +void causeSIGTRAPCrashF2(); +/***************************************************/ diff --git a/example/android/app/src/main/cpp/crasher_4.cpp b/example/android/app/src/main/cpp/crasher_4.cpp new file mode 100644 index 000000000..1b59db3a9 --- /dev/null +++ b/example/android/app/src/main/cpp/crasher_4.cpp @@ -0,0 +1,57 @@ + + +#include +#include +#include +#include +#include + +extern "C" { +/************* SIGSEGV *******************************/ +void causeSIGSEGVCrashF3(volatile int *i) { + //SIGSEGV + volatile int j = 34 / *i; +} +/*****************************************************/ + +/************* SIGABRT *******************************/ +void causeSIGABRTCrashF3() { + //SIGABRT + throw std::invalid_argument("received invalid value"); +} +/****************************************************/ + +/************* SIGFPE *******************************/ +void causeSIGFPECrashF3() { + //SIGFPE + raise(SIGFPE); + pthread_kill(getpid(), SIGFPE); +} +/***************************************************/ + +/************* SIGILL *******************************/ + +int causeSIGILLCrashF3() { + //SIGILL + raise(SIGILL); + pthread_kill(getpid(), SIGILL); +} +/***************************************************/ + +/************* SIGBUS *******************************/ + +void causeSIGBUSCrashF3() { + //SIGBUS + raise(SIGBUS); + pthread_kill(getpid(), SIGBUS); +} +/***************************************************/ + +/************* SIGTRAP *******************************/ + +void causeSIGTRAPCrashF3() { + //SIGBUS + __builtin_trap(); +} +/***************************************************/ +} diff --git a/example/android/app/src/main/cpp/crasher_4.h b/example/android/app/src/main/cpp/crasher_4.h new file mode 100644 index 000000000..8c546ee04 --- /dev/null +++ b/example/android/app/src/main/cpp/crasher_4.h @@ -0,0 +1,24 @@ + +/************* SIGSEGV *******************************/ +void causeSIGSEGVCrashF3(int* i); +/*****************************************************/ + +/************* SIGABRT *******************************/ +void causeSIGABRTCrashF3(); +/****************************************************/ + +/************* SIGFPE *******************************/ +void causeSIGFPECrashF3(); +/***************************************************/ + +/************* SIGILL *******************************/ +int causeSIGILLCrashF3(); +/***************************************************/ + +/************* SIGBUS *******************************/ +void causeSIGBUSCrashF3(); +/***************************************************/ + +/************* SIGTRAP *******************************/ +void causeSIGTRAPCrashF3(); +/***************************************************/ diff --git a/example/android/app/src/main/cpp/native-lib.cpp b/example/android/app/src/main/cpp/native-lib.cpp new file mode 100644 index 000000000..7334aade3 --- /dev/null +++ b/example/android/app/src/main/cpp/native-lib.cpp @@ -0,0 +1,19 @@ +#include +#include +#include + + + + +/* + * Throws invalid argument exception + */ +extern "C" +JNIEXPORT void JNICALL +Java_com_example_InstabugSample_ndk_CppNativeLib_crashNDK(JNIEnv *env, + jobject object) { + __android_log_print(ANDROID_LOG_DEBUG, "NativeC++", "%s", "received invalid value"); + + // in Android SDK it's equivalent to causeSIGABRTCrash() + throw std::invalid_argument("received invalid value"); +} \ No newline at end of file diff --git a/example/android/app/src/main/java/com/example/InstabugSample/ndk/CppNativeLib.java b/example/android/app/src/main/java/com/example/InstabugSample/ndk/CppNativeLib.java new file mode 100644 index 000000000..e9e59ab3a --- /dev/null +++ b/example/android/app/src/main/java/com/example/InstabugSample/ndk/CppNativeLib.java @@ -0,0 +1,24 @@ +package com.example.InstabugSample.ndk; + +import android.util.Log; + +/** + * C++ Native library bridge. + */ +public class CppNativeLib { + + static { + System.loadLibrary("native-lib"); + } + + /** + * Crashes the app with various signals from the C/C++ layer. + */ + public static native void crashNDK(); + public static native void causeSIGSEGVCrash(); + public static native void causeSIGABRTCrash(); + public static native void causeSIGFPECrash(); + public static native void causeSIGILLCrash(); + public static native void causeSIGBUSCrash(); + public static native void causeSIGTRAPCrash(); +} diff --git a/example/android/app/src/main/kotlin/com/example/InstabugSample/InstabugExampleMethodCallHandler.kt b/example/android/app/src/main/kotlin/com/example/InstabugSample/InstabugExampleMethodCallHandler.kt index 17a7d35c6..e56215683 100644 --- a/example/android/app/src/main/kotlin/com/example/InstabugSample/InstabugExampleMethodCallHandler.kt +++ b/example/android/app/src/main/kotlin/com/example/InstabugSample/InstabugExampleMethodCallHandler.kt @@ -1,7 +1,9 @@ package com.example.InstabugSample + import android.os.Handler import android.os.Looper import android.util.Log +import com.example.InstabugSample.ndk.CppNativeLib import com.instabug.crash.CrashReporting import com.instabug.crash.models.IBGNonFatalException import io.flutter.plugin.common.MethodCall @@ -37,6 +39,41 @@ class InstabugExampleMethodCallHandler : MethodChannel.MethodCallHandler { sendOOM() result.success(null) } + CAUSE_NDK_CRASH -> { + Log.d(TAG, "Causing NDK crash") + causeNdkCrash() + result.success(null) + } + CAUSE_SIGSEGV_CRASH -> { + Log.d(TAG, "Causing SIGSEGV crash") + causeSIGSEGVCrash() + result.success(null) + } + CAUSE_SIGABRT_CRASH -> { + Log.d(TAG, "Causing SIGABRT crash") + causeSIGABRTCrash() + result.success(null) + } + CAUSE_SIGFPE_CRASH -> { + Log.d(TAG, "Causing SIGFPE crash") + causeSIGFPECrash() + result.success(null) + } + CAUSE_SIGILL_CRASH -> { + Log.d(TAG, "Causing SIGILL crash") + causeSIGILLCrash() + result.success(null) + } + CAUSE_SIGBUS_CRASH -> { + Log.d(TAG, "Causing SIGBUS crash") + causeSIGBUSCrash() + result.success(null) + } + CAUSE_SIGTRAP_CRASH -> { + Log.d(TAG, "Causing SIGTRAP crash") + causeSIGTRAPCrash() + result.success(null) + } else -> { Log.e(TAG, "onMethodCall for ${call.method} is not implemented") result.notImplemented() @@ -55,6 +92,15 @@ class InstabugExampleMethodCallHandler : MethodChannel.MethodCallHandler { const val SEND_NATIVE_FATAL_HANG = "sendNativeFatalHang" const val SEND_ANR = "sendAnr" const val SEND_OOM = "sendOom" + + // NDK Crash Method Names + const val CAUSE_NDK_CRASH = "causeNdkCrash" + const val CAUSE_SIGSEGV_CRASH = "causeSIGSEGVCrash" + const val CAUSE_SIGABRT_CRASH = "causeSIGABRTCrash" + const val CAUSE_SIGFPE_CRASH = "causeSIGFPECrash" + const val CAUSE_SIGILL_CRASH = "causeSIGILLCrash" + const val CAUSE_SIGBUS_CRASH = "causeSIGBUSCrash" + const val CAUSE_SIGTRAP_CRASH = "causeSIGTRAPCrash" } private fun sendNativeNonFatal(exceptionObject: String?) { @@ -125,4 +171,33 @@ class InstabugExampleMethodCallHandler : MethodChannel.MethodCallHandler { return randomString.toString() } + // NDK Crash Methods + private fun causeNdkCrash() { + CppNativeLib.crashNDK() + } + + private fun causeSIGSEGVCrash() { + CppNativeLib.causeSIGSEGVCrash() + } + + private fun causeSIGABRTCrash() { + CppNativeLib.causeSIGABRTCrash() + } + + private fun causeSIGFPECrash() { + CppNativeLib.causeSIGFPECrash() + } + + private fun causeSIGILLCrash() { + CppNativeLib.causeSIGILLCrash() + } + + private fun causeSIGBUSCrash() { + CppNativeLib.causeSIGBUSCrash() + } + + private fun causeSIGTRAPCrash() { + CppNativeLib.causeSIGTRAPCrash() + } + } diff --git a/example/android/app/src/main/kotlin/com/example/InstabugSample/MainActivity.kt b/example/android/app/src/main/kotlin/com/example/InstabugSample/MainActivity.kt index b6d6f7352..af12f18cf 100644 --- a/example/android/app/src/main/kotlin/com/example/InstabugSample/MainActivity.kt +++ b/example/android/app/src/main/kotlin/com/example/InstabugSample/MainActivity.kt @@ -1,4 +1,4 @@ -package com.instabug.flutter.example +package com.example.InstabugSample import com.example.InstabugSample.InstabugExampleMethodCallHandler import com.example.InstabugSample.InstabugExampleMethodCallHandler.Companion.METHOD_CHANNEL_NAME @@ -10,6 +10,8 @@ class MainActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) - MethodChannel(flutterEngine.dartExecutor.binaryMessenger, METHOD_CHANNEL_NAME).setMethodCallHandler(InstabugExampleMethodCallHandler()) + MethodChannel(flutterEngine.dartExecutor.binaryMessenger, METHOD_CHANNEL_NAME).setMethodCallHandler( + InstabugExampleMethodCallHandler() + ) } } diff --git a/example/android/settings.gradle b/example/android/settings.gradle index 32cfc43dc..e93b1b6a3 100644 --- a/example/android/settings.gradle +++ b/example/android/settings.gradle @@ -20,7 +20,7 @@ pluginManagement { plugins { id "dev.flutter.flutter-plugin-loader" version "1.0.0" - id "com.android.application" version "8.1.0" apply false + id "com.android.application" version "8.2.1" apply false id "org.jetbrains.kotlin.android" version "1.8.22" apply false } diff --git a/example/lib/main.dart b/example/lib/main.dart index 91b0a67e7..80e4cce15 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -5,6 +5,7 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:instabug_flutter/instabug_flutter.dart'; +import 'package:instabug_flutter_ndk/instabug_flutter_ndk.dart'; import 'package:instabug_flutter_example/src/components/apm_switch.dart'; import 'package:instabug_http_client/instabug_http_client.dart'; import 'package:instabug_flutter_example/src/app_routes.dart'; @@ -42,6 +43,8 @@ part 'src/components/traces_content.dart'; part 'src/components/flows_content.dart'; +part 'src/components/ndk_crashes_content.dart'; + void main() { runZonedGuarded( () { @@ -57,6 +60,8 @@ void main() { Zone.current.handleUncaughtError(details.exception, details.stack!); }; + CrashReporting.setNDKEnabled(true); + runApp(const MyApp()); }, CrashReporting.reportCrash, diff --git a/example/lib/src/components/ndk_crashes_content.dart b/example/lib/src/components/ndk_crashes_content.dart new file mode 100644 index 000000000..1b63ef05d --- /dev/null +++ b/example/lib/src/components/ndk_crashes_content.dart @@ -0,0 +1,62 @@ +part of '../../main.dart'; + +class NdkCrashesContent extends StatelessWidget { + const NdkCrashesContent({Key? key}) : super(key: key); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.max, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Platform.isAndroid + ? const Column( + children: [ + InstabugButton( + text: 'Trigger NDK Crash', + onPressed: + InstabugFlutterExampleMethodChannel.causeNdkCrash, + ), + InstabugButton( + text: 'Trigger NDK SIGSEGV Crash', + onPressed: + InstabugFlutterExampleMethodChannel.causeNdkSigsegv, + ), + InstabugButton( + text: 'Trigger NDK SIGABRT Crash', + onPressed: + InstabugFlutterExampleMethodChannel.causeNdkSigabrt, + ), + InstabugButton( + text: 'Trigger NDK SIGFPE Crash', + onPressed: + InstabugFlutterExampleMethodChannel.causeNdkSigfpe, + ), + InstabugButton( + text: 'Trigger NDK SIGILL Crash', + onPressed: + InstabugFlutterExampleMethodChannel.causeNdkSigill, + ), + InstabugButton( + text: 'Trigger NDK SIGBUS Crash', + onPressed: + InstabugFlutterExampleMethodChannel.causeNdkSigbus, + ), + InstabugButton( + text: 'Trigger NDK SIGTRAP Crash', + onPressed: + InstabugFlutterExampleMethodChannel.causeNdkSigtrap, + ), + ], + ) + : const Text( + 'NDK crashes are only available on Android', + style: TextStyle( + fontSize: 14, + color: Colors.grey, + ), + ), + ], + ); + } +} diff --git a/example/lib/src/native/instabug_flutter_example_method_channel.dart b/example/lib/src/native/instabug_flutter_example_method_channel.dart index 9507cc403..e27d6f1bc 100644 --- a/example/lib/src/native/instabug_flutter_example_method_channel.dart +++ b/example/lib/src/native/instabug_flutter_example_method_channel.dart @@ -54,6 +54,63 @@ class InstabugFlutterExampleMethodChannel { log("Failed to send out of memory: '${e.message}'.", name: _tag); } } + + static Future causeNdkCrash() async { + try { + await _channel.invokeMethod(Constants.causeNdkCrashMethodName); + } on PlatformException catch (e) { + log("Failed to cause NDK crash: '${e.message}'.", name: _tag); + } + } + + // NDK Crash Methods + static Future causeNdkSigsegv() async { + try { + await _channel.invokeMethod(Constants.causeNdkSigsegvMethodName); + } on PlatformException catch (e) { + log("Failed to trigger NDK SIGSEGV: '${e.message}'.", name: _tag); + } + } + + static Future causeNdkSigabrt() async { + try { + await _channel.invokeMethod(Constants.causeNdkSigabrtMethodName); + } on PlatformException catch (e) { + log("Failed to trigger NDK SIGABRT: '${e.message}'.", name: _tag); + } + } + + static Future causeNdkSigfpe() async { + try { + await _channel.invokeMethod(Constants.causeNdkSigfpeMethodName); + } on PlatformException catch (e) { + log("Failed to trigger NDK SIGFPE: '${e.message}'.", name: _tag); + } + } + + static Future causeNdkSigill() async { + try { + await _channel.invokeMethod(Constants.causeNdkSigillMethodName); + } on PlatformException catch (e) { + log("Failed to trigger NDK SIGILL: '${e.message}'.", name: _tag); + } + } + + static Future causeNdkSigbus() async { + try { + await _channel.invokeMethod(Constants.causeNdkSigbusMethodName); + } on PlatformException catch (e) { + log("Failed to trigger NDK SIGBUS: '${e.message}'.", name: _tag); + } + } + + static Future causeNdkSigtrap() async { + try { + await _channel.invokeMethod(Constants.causeNdkSigtrapMethodName); + } on PlatformException catch (e) { + log("Failed to trigger NDK SIGTRAP: '${e.message}'.", name: _tag); + } + } } class Constants { @@ -65,4 +122,13 @@ class Constants { static const sendNativeFatalHangMethodName = "sendNativeFatalHang"; static const sendAnrMethodName = "sendAnr"; static const sendOomMethodName = "sendOom"; + + // NDK Crash Method Names + static const causeNdkCrashMethodName = "causeNdkCrash"; + static const causeNdkSigsegvMethodName = "causeSIGSEGVCrash"; + static const causeNdkSigabrtMethodName = "causeSIGABRTCrash"; + static const causeNdkSigfpeMethodName = "causeSIGFPECrash"; + static const causeNdkSigillMethodName = "causeSIGILLCrash"; + static const causeNdkSigbusMethodName = "causeSIGBUSCrash"; + static const causeNdkSigtrapMethodName = "causeSIGTRAPCrash"; } diff --git a/example/lib/src/screens/crashes_page.dart b/example/lib/src/screens/crashes_page.dart index 7e0ec8e76..3c4672ade 100644 --- a/example/lib/src/screens/crashes_page.dart +++ b/example/lib/src/screens/crashes_page.dart @@ -16,6 +16,13 @@ class CrashesPage extends StatelessWidget { Text('Fatal Crashes can only be tested in release mode'), Text('Most of these buttons will crash the application'), FatalCrashesContent(), + SectionTitle('NDK Crashes'), + Text( + 'NDK crashes are native C/C++ crashes that occur in Android applications.'), + Text( + 'These crashes can only be tested on Android devices with NDK support.', + style: TextStyle(color: Colors.orange)), + NdkCrashesContent(), SectionTitle('Crash section'), ], // This trailing comma makes auto-formatting nicer for build methods. ); diff --git a/example/pubspec.lock b/example/pubspec.lock index 99e8f9d56..67ec4194a 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -5,58 +5,58 @@ packages: dependency: transitive description: name: async - sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c" + sha256: d2872f9c19731c2e5f10444b14686eb7cc85c76274bd6c16e1816bff9a3bab63 url: "https://pub.dev" source: hosted - version: "2.11.0" + version: "2.12.0" boolean_selector: dependency: transitive description: name: boolean_selector - sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66" + sha256: "8aab1771e1243a5063b8b0ff68042d67334e3feab9e95b9490f9a6ebf73b42ea" url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" characters: dependency: transitive description: name: characters - sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605" + sha256: f71061c654a3380576a52b451dd5532377954cf9dbd272a78fc8479606670803 url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.0" clock: dependency: transitive description: name: clock - sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf + sha256: fddb70d9b5277016c77a80201021d40a2247104d9f4aa7bab7157b7e3f05b84b url: "https://pub.dev" source: hosted - version: "1.1.1" + version: "1.1.2" collection: dependency: transitive description: name: collection - sha256: a1ace0a119f20aabc852d165077c036cd864315bd99b7eaa10a60100341941bf + sha256: "2f5709ae4d3d59dd8f7cd309b4e023046b57d8a6c82130785d2b0e5868084e76" url: "https://pub.dev" source: hosted - version: "1.19.0" + version: "1.19.1" fake_async: dependency: transitive description: name: fake_async - sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78" + sha256: "6a95e56b2449df2273fd8c45a662d6947ce1ebb7aafe80e550a3f68297f3cacc" url: "https://pub.dev" source: hosted - version: "1.3.1" + version: "1.3.2" file: dependency: transitive description: name: file - sha256: "5fc22d7c25582e38ad9a8515372cd9a93834027aacf1801cf01164dac0ffa08c" + sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4 url: "https://pub.dev" source: hosted - version: "7.0.0" + version: "7.0.1" flutter: dependency: "direct main" description: flutter @@ -108,6 +108,15 @@ packages: relative: true source: path version: "15.0.2" + instabug_flutter_ndk: + dependency: "direct main" + description: + path: "packages/instabug_flutter_ndk" + ref: "feat/support-ndk-crashes" + resolved-ref: "1e075d6b1be1fdd4781403607382fee87d93f604" + url: "https://github.com/Instabug/Instabug-Flutter/" + source: git + version: "0.0.1" instabug_http_client: dependency: "direct main" description: @@ -120,18 +129,18 @@ packages: dependency: transitive description: name: leak_tracker - sha256: "7bb2830ebd849694d1ec25bf1f44582d6ac531a57a365a803a6034ff751d2d06" + sha256: c35baad643ba394b40aac41080300150a4f08fd0fd6a10378f8f7c6bc161acec url: "https://pub.dev" source: hosted - version: "10.0.7" + version: "10.0.8" leak_tracker_flutter_testing: dependency: transitive description: name: leak_tracker_flutter_testing - sha256: "9491a714cca3667b60b5c420da8217e6de0d1ba7a5ec322fab01758f6998f379" + sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573 url: "https://pub.dev" source: hosted - version: "3.0.8" + version: "3.0.9" leak_tracker_testing: dependency: transitive description: @@ -152,10 +161,10 @@ packages: dependency: transitive description: name: matcher - sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb + sha256: dc58c723c3c24bf8d3e2d3ad3f2f9d7bd9cf43ec6feaa64181775e60190153f2 url: "https://pub.dev" source: hosted - version: "0.12.16+1" + version: "0.12.17" material_color_utilities: dependency: transitive description: @@ -168,34 +177,34 @@ packages: dependency: transitive description: name: meta - sha256: bdb68674043280c3428e9ec998512fb681678676b3c54e773629ffe74419f8c7 + sha256: e3641ec5d63ebf0d9b41bd43201a66e3fc79a65db5f61fc181f04cd27aab950c url: "https://pub.dev" source: hosted - version: "1.15.0" + version: "1.16.0" path: dependency: transitive description: name: path - sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.9.0" + version: "1.9.1" platform: dependency: transitive description: name: platform - sha256: "9b71283fc13df574056616011fb138fd3b793ea47cc509c189a6c3fa5f8a1a65" + sha256: "5d6b1b0036a5f331ebc77c850ebc8506cbc1e9416c27e59b439f917a902a4984" url: "https://pub.dev" source: hosted - version: "3.1.5" + version: "3.1.6" process: dependency: transitive description: name: process - sha256: "21e54fd2faf1b5bdd5102afd25012184a6793927648ea81eea80552ac9405b32" + sha256: "107d8be718f120bbba9dcd1e95e3bd325b1b4a4f07db64154635ba03f2567a0d" url: "https://pub.dev" source: hosted - version: "5.0.2" + version: "5.0.3" sky_engine: dependency: transitive description: flutter @@ -205,34 +214,34 @@ packages: dependency: transitive description: name: source_span - sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c" + sha256: "254ee5351d6cb365c859e20ee823c3bb479bf4a293c22d17a9f1bf144ce86f7c" url: "https://pub.dev" source: hosted - version: "1.10.0" + version: "1.10.1" stack_trace: dependency: transitive description: name: stack_trace - sha256: "9f47fd3630d76be3ab26f0ee06d213679aa425996925ff3feffdec504931c377" + sha256: "8b27215b45d22309b5cddda1aa2b19bdfec9df0e765f2de506401c071d38d1b1" url: "https://pub.dev" source: hosted - version: "1.12.0" + version: "1.12.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 + sha256: "969e04c80b8bcdf826f8f16579c7b14d780458bd97f56d107d3950fdbeef059d" url: "https://pub.dev" source: hosted - version: "2.1.2" + version: "2.1.4" string_scanner: dependency: transitive description: name: string_scanner - sha256: "688af5ed3402a4bde5b3a6c15fd768dbf2621a614950b17f04626c431ab3c4c3" + sha256: "921cd31725b72fe181906c6a94d987c78e3b98c2e205b397ea399d4054872b43" url: "https://pub.dev" source: hosted - version: "1.3.0" + version: "1.4.1" sync_http: dependency: transitive description: @@ -245,18 +254,18 @@ packages: dependency: transitive description: name: term_glyph - sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84 + sha256: "7f554798625ea768a7518313e58f83891c7f5024f88e46e7182a4558850a4b8e" url: "https://pub.dev" source: hosted - version: "1.2.1" + version: "1.2.2" test_api: dependency: transitive description: name: test_api - sha256: "664d3a9a64782fcdeb83ce9c6b39e78fd2971d4e37827b9b06c3aa1edc5e760c" + sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd url: "https://pub.dev" source: hosted - version: "0.7.3" + version: "0.7.4" typed_data: dependency: transitive description: @@ -277,10 +286,10 @@ packages: dependency: transitive description: name: vm_service - sha256: f6be3ed8bd01289b34d679c2b62226f63c0e69f9fd2e50a6b3c1c729a961041b + sha256: "0968250880a6c5fe7edc067ed0a13d4bae1577fe2771dcf3010d52c4a9d3ca14" url: "https://pub.dev" source: hosted - version: "14.3.0" + version: "14.3.1" webdriver: dependency: transitive description: @@ -290,5 +299,5 @@ packages: source: hosted version: "3.0.4" sdks: - dart: ">=3.5.0 <4.0.0" + dart: ">=3.7.0 <4.0.0" flutter: ">=3.18.0-18.0.pre.54" diff --git a/example/pubspec.yaml b/example/pubspec.yaml index fe72aaa2d..e800cb856 100644 --- a/example/pubspec.yaml +++ b/example/pubspec.yaml @@ -26,6 +26,11 @@ dependencies: http: ^0.13.0 instabug_flutter: path: ../ + instabug_flutter_ndk: + git: + url: https://github.com/Instabug/Instabug-Flutter/ + path: packages/instabug_flutter_ndk + ref: feat/support-ndk-crashes instabug_http_client: ^2.4.0 dev_dependencies: diff --git a/ios/Classes/Modules/CrashReportingApi.m b/ios/Classes/Modules/CrashReportingApi.m index 0103aa766..fd06bb3cb 100644 --- a/ios/Classes/Modules/CrashReportingApi.m +++ b/ios/Classes/Modules/CrashReportingApi.m @@ -46,4 +46,9 @@ - (void)sendNonFatalErrorJsonCrash:(nonnull NSString *)jsonCrash userAttributes: userAttributes:userAttributes]; } + +- (void)setNDKEnabledIsEnabled:(nonnull NSNumber *)isEnabled error:(FlutterError * _Nullable __autoreleasing * _Nonnull)error { +// This is auto-generated with pigeon, there is no NDK crashes for iOS. +} + @end diff --git a/lib/src/modules/crash_reporting.dart b/lib/src/modules/crash_reporting.dart index e5d0a0e3e..829175fae 100644 --- a/lib/src/modules/crash_reporting.dart +++ b/lib/src/modules/crash_reporting.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:convert'; +import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:instabug_flutter/src/generated/crash_reporting.api.g.dart'; @@ -116,4 +117,14 @@ class CrashReporting { ); return crashData; } + + /// Enables and disables NDK crash reporting. + /// [boolean] isEnabled + /// + /// Requires the [Instabug NDK package](https://pub.dev/packages/instabug_flutter_ndk) to be added to the project for this to work. + static Future setNDKEnabled(bool isEnabled) async { + if (Platform.isAndroid) { + return _host.setNDKEnabled(isEnabled); + } + } } diff --git a/pigeons/crash_reporting.api.dart b/pigeons/crash_reporting.api.dart index 45f4a9cdb..4ac788e88 100644 --- a/pigeons/crash_reporting.api.dart +++ b/pigeons/crash_reporting.api.dart @@ -12,4 +12,6 @@ abstract class CrashReportingHostApi { String? fingerprint, String nonFatalExceptionLevel, ); + + void setNDKEnabled(bool isEnabled); }