├── README
├── app
├── AndroidManifest.xml
├── generate_header.sh
├── jni
│ ├── Android.mk
│ ├── Application.mk
│ ├── native_lib.cpp
│ └── native_lib.h
├── local.properties
├── pom.xml
├── project.properties
├── res
│ ├── drawable-hdpi
│ │ └── ic_launcher.png
│ ├── drawable-ldpi
│ │ └── ic_launcher.png
│ ├── drawable-mdpi
│ │ └── ic_launcher.png
│ ├── drawable-xhdpi
│ │ └── ic_launcher.png
│ ├── layout
│ │ └── main.xml
│ └── values
│ │ └── strings.xml
└── src
│ └── name
│ └── antonsmirnov
│ └── android
│ └── acra_breakpad
│ └── app
│ ├── App.java
│ ├── MainActivity.java
│ └── NativeLib.java
├── compile.sh
├── lib
├── AndroidManifest.xml
├── generate_header.sh
├── jni
│ ├── Android.mk
│ ├── Application.mk
│ ├── breakpad
│ ├── native_exception_handler.cpp
│ └── native_exception_handler.h
├── pom.xml
├── res
│ └── values
│ │ └── strings.xml
└── src
│ └── name
│ └── antonsmirnov
│ └── android
│ └── acra_breakpad
│ ├── NativeException.java
│ └── NativeExceptionHandler.java
└── pom.xml
/README:
--------------------------------------------------------------------------------
1 | Acra-breakpad
2 | =============
3 |
4 | Integration for Acra and google-breakpad: catch native crashes using ACRA
5 |
6 | How to build:
7 | 0. clone forked ACRA with binary attachments support (https://github.com/4ntoine/acra) and build the project (mvn clean install)
8 | 1. Go to lib/jni
9 | 2. clone (https://code.google.com/p/google-breakpad/source/checkout) or symlink google-breakpad sources to 'lib/jni/breakpad'
10 | 3. edit lib/jni/Android.mk to set current local path after breakpad is build (sorry for doing it in a bit hacky way)
11 | 4. ndk-build
12 | 5. Go to app/jni
13 | 6. ndk-build
14 | 7. Go to project root directory
15 | 8. mvn clean install
16 |
17 | How to test:
18 | 1. Launch the app
19 | 2. Click "Test catch"
20 |
--------------------------------------------------------------------------------
/app/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/app/generate_header.sh:
--------------------------------------------------------------------------------
1 | javah -classpath ./target/classes -o ./jni/native_lib.h name.antonsmirnov.android.acra_breakpad.app.NativeLib
2 |
--------------------------------------------------------------------------------
/app/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | include $(CLEAR_VARS)
4 | LOCAL_MODULE := native
5 | LOCAL_SRC_FILES := native_lib.cpp
6 | LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
7 | #LOCAL_CPP_FEATURES += exceptions
8 |
9 | # ARM (coffeecatch)
10 | #LOCAL_CFLAGS := -funwind-tables -Wl,--no-merge-exidx-entries
11 |
12 | include $(BUILD_SHARED_LIBRARY)
--------------------------------------------------------------------------------
/app/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := all
2 | #APP_CPPFLAGS += -fexceptions
3 | #APP_STL := gnustl_shared
--------------------------------------------------------------------------------
/app/jni/native_lib.cpp:
--------------------------------------------------------------------------------
1 | #include "native_lib.h"
2 |
3 | #include
4 |
5 | void debug(const char *format, ... ) {
6 | va_list argptr;
7 | va_start(argptr, format);
8 | __android_log_vprint(ANDROID_LOG_ERROR, "NATIVE_LIB", format, argptr);
9 | va_end(argptr);
10 | }
11 |
12 | JNIEXPORT jint JNICALL Java_name_antonsmirnov_android_acra_1breakpad_app_NativeLib_native_1func
13 | (JNIEnv *env, jclass self, jstring tmp1, jobject tmp2, jobject tmp3)
14 | {
15 | debug("testing crash\n");
16 |
17 | char *ptr = 0;
18 | *ptr = '!'; // ERROR HERE!
19 |
20 | debug("unreachable\n");
21 | }
--------------------------------------------------------------------------------
/app/jni/native_lib.h:
--------------------------------------------------------------------------------
1 | /* DO NOT EDIT THIS FILE - it is machine generated */
2 | #include
3 | /* Header for class name_antonsmirnov_android_acra_breakpad_app_NativeLib */
4 |
5 | #ifndef _Included_name_antonsmirnov_android_acra_breakpad_app_NativeLib
6 | #define _Included_name_antonsmirnov_android_acra_breakpad_app_NativeLib
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 | /*
11 | * Class: name_antonsmirnov_android_acra_breakpad_app_NativeLib
12 | * Method: native_func
13 | * Signature: (Ljava/lang/String;Ljava/util/List;Ljava/lang/Object;)I
14 | */
15 | JNIEXPORT jint JNICALL Java_name_antonsmirnov_android_acra_1breakpad_app_NativeLib_native_1func
16 | (JNIEnv *, jclass, jstring, jobject, jobject);
17 |
18 | #ifdef __cplusplus
19 | }
20 | #endif
21 | #endif
22 |
--------------------------------------------------------------------------------
/app/local.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must *NOT* be checked into Version Control Systems,
5 | # as it contains information specific to your local configuration.
6 |
7 | # location of the SDK. This is only used by Ant
8 | # For customization when using a Version Control System, please read the
9 | # header note.
10 | sdk.dir=/softdev/android-sdk_r21
11 |
--------------------------------------------------------------------------------
/app/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | 4.0.0
7 |
8 | name.antonsmirnov.android
9 | acra_breakpad_demo
10 | 1.0
11 | apk
12 | acra_breakpad demo app
13 | Acra-breakpad integration demo app
14 |
15 |
16 |
17 | Anton Smirnov
18 | dev@antonsmirnov.name
19 |
20 |
21 |
22 |
23 |
24 |
25 | com.google.android
26 | android
27 | 4.0.1.2
28 | provided
29 |
30 |
31 |
32 |
33 | ch.acra
34 | acra
35 | 5.0.0-SNAPSHOT
36 |
37 |
38 |
39 |
40 | name.antonsmirnov.android
41 | acra_breakpad
42 | 1.0
43 | apklib
44 |
45 |
46 |
47 |
48 |
49 | src
50 |
51 |
52 |
53 | com.jayway.maven.plugins.android.generation2
54 | android-maven-plugin
55 | 3.6.0
56 |
57 |
58 | alignApk
59 | install
60 |
61 |
62 |
63 | ${project.basedir}/src
64 | ${project.basedir}/res
65 |
66 | 16
67 |
68 | true
69 |
70 | true
71 |
72 |
73 |
74 |
75 |
76 |
--------------------------------------------------------------------------------
/app/project.properties:
--------------------------------------------------------------------------------
1 | # This file is automatically generated by Android Tools.
2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED!
3 | #
4 | # This file must be checked in Version Control Systems.
5 | #
6 | # To customize properties used by the Ant build system edit
7 | # "ant.properties", and override values to adapt the script to your
8 | # project structure.
9 | #
10 | # To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
11 | #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
12 |
13 | # Project target.
14 | target=android-16
15 | android.library.reference.1=../lib
16 |
--------------------------------------------------------------------------------
/app/res/drawable-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ntoine/Acra-breakpad/35a681e60175432c24020c12db56f3e8d2d5dd39/app/res/drawable-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/res/drawable-ldpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ntoine/Acra-breakpad/35a681e60175432c24020c12db56f3e8d2d5dd39/app/res/drawable-ldpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/res/drawable-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ntoine/Acra-breakpad/35a681e60175432c24020c12db56f3e8d2d5dd39/app/res/drawable-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/res/drawable-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/4ntoine/Acra-breakpad/35a681e60175432c24020c12db56f3e8d2d5dd39/app/res/drawable-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/res/layout/main.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/app/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | Acra-breakpad demo
4 | Error title
5 | Error text
6 | Please describe how to reproduce the crash
7 |
8 |
--------------------------------------------------------------------------------
/app/src/name/antonsmirnov/android/acra_breakpad/app/App.java:
--------------------------------------------------------------------------------
1 | package name.antonsmirnov.android.acra_breakpad.app;
2 |
3 | import android.app.Application;
4 | import org.acra.ACRA;
5 | import org.acra.ReportField;
6 | import org.acra.ReportingInteractionMode;
7 | import org.acra.annotation.ReportsCrashes;
8 |
9 | /**
10 | * ACRA config
11 | */
12 | @ReportsCrashes(
13 | // need to set custom report fields to add APPLICATION_LOG file
14 | customReportContent = {
15 | ReportField.REPORT_ID,
16 | ReportField.APP_VERSION_CODE,
17 | ReportField.APP_VERSION_NAME,
18 | ReportField.ANDROID_VERSION,
19 | ReportField.AVAILABLE_MEM_SIZE,
20 | ReportField.USER_COMMENT,
21 | ReportField.CRASH_DUMP, // make sure you're using 4ntoine-acra or pull request merged to acra
22 | },
23 | formKey = "",
24 | resDialogTitle = R.string.resDialogTitle,
25 | resDialogText = R.string.resDialogText,
26 | resDialogCommentPrompt = R.string.resDialogComment, // required to show user comment field
27 | mode = ReportingInteractionMode.DIALOG,
28 | mailTo = App.SUPPORT_EMAIL)
29 | public class App extends Application {
30 |
31 | public static final String SUPPORT_EMAIL = "test@domain.com";
32 |
33 | @Override
34 | public void onCreate() {
35 | super.onCreate();
36 |
37 | ACRA.init(this);
38 | }
39 | }
40 |
--------------------------------------------------------------------------------
/app/src/name/antonsmirnov/android/acra_breakpad/app/MainActivity.java:
--------------------------------------------------------------------------------
1 | package name.antonsmirnov.android.acra_breakpad.app;
2 |
3 | import android.app.Activity;
4 | import android.os.Bundle;
5 | import android.view.View;
6 | import android.widget.Button;
7 | import name.antonsmirnov.android.acra_breakpad.NativeExceptionHandler;
8 |
9 | public class MainActivity extends Activity {
10 |
11 | private NativeExceptionHandler exceptionHandler = new NativeExceptionHandler();
12 |
13 | private Button testCatchButton;
14 |
15 | @Override
16 | public void onCreate(Bundle savedInstanceState) {
17 | super.onCreate(savedInstanceState);
18 |
19 | // allocate and start handle native exceptions
20 | exceptionHandler.init(null);
21 |
22 | setContentView(R.layout.main);
23 |
24 | bindControls();
25 | initControls();
26 | }
27 |
28 | private void bindControls() {
29 | testCatchButton = (Button) findViewById(R.id.Main_testCatch);
30 | }
31 |
32 | private void initControls() {
33 | testCatchButton.setOnClickListener(new View.OnClickListener() {
34 | @Override
35 | public void onClick(View v) {
36 | testCatch();
37 | }
38 | });
39 | }
40 |
41 | private void testCatch() {
42 | NativeLib lib = new NativeLib();
43 |
44 | // crash
45 | int result = lib.native_func("temp1", null, new Integer(5));
46 | }
47 |
48 | @Override
49 | protected void onDestroy() {
50 | super.onDestroy();
51 |
52 | // release and stop handle native exceptions
53 | exceptionHandler.deinit();
54 | }
55 | }
56 |
--------------------------------------------------------------------------------
/app/src/name/antonsmirnov/android/acra_breakpad/app/NativeLib.java:
--------------------------------------------------------------------------------
1 | package name.antonsmirnov.android.acra_breakpad.app;
2 |
3 | import java.util.List;
4 |
5 | /**
6 | * Test native lib
7 | */
8 | public class NativeLib {
9 |
10 | static {
11 | System.loadLibrary("native");
12 | }
13 |
14 | /**
15 | * error function
16 | */
17 | public native static int native_func(String tmp1, List tmp2, Object tmp3);
18 | }
19 |
--------------------------------------------------------------------------------
/compile.sh:
--------------------------------------------------------------------------------
1 | mvn clean install -Dandroid.sdk.path=/softdev/android-sdk_r21/
2 |
--------------------------------------------------------------------------------
/lib/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/lib/generate_header.sh:
--------------------------------------------------------------------------------
1 | javah -classpath ./target/classes -o ./jni/native_exception_handler.h name.antonsmirnov.android.acra_breakpad.NativeExceptionHandler
2 |
--------------------------------------------------------------------------------
/lib/jni/Android.mk:
--------------------------------------------------------------------------------
1 | LOCAL_PATH := $(call my-dir)
2 |
3 | # symlink 'breakpad' to breakpad directory
4 | include $(LOCAL_PATH)/breakpad/android/google_breakpad/Android.mk
5 |
6 | # set local path
7 | LOCAL_PATH := /Users/asmirnov/Documents/dev/src/Acra-breakpad/lib/jni/
8 |
9 | include $(CLEAR_VARS)
10 | LOCAL_MODULE := native_exception_handler
11 | LOCAL_SRC_FILES := native_exception_handler.cpp
12 | LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog
13 |
14 | # link to breakpad
15 | LOCAL_STATIC_LIBRARIES += breakpad_client
16 |
17 | # ARM (for getting full stacktrace)
18 | #LOCAL_CFLAGS := -funwind-tables -Wl,--no-merge-exidx-entries
19 |
20 | include $(BUILD_SHARED_LIBRARY)
--------------------------------------------------------------------------------
/lib/jni/Application.mk:
--------------------------------------------------------------------------------
1 | APP_ABI := all
2 | APP_STL := gnustl_shared
3 | #APP_MODULES += breakpad_client
4 | APP_PLATFORM := android-8
--------------------------------------------------------------------------------
/lib/jni/breakpad:
--------------------------------------------------------------------------------
1 | ../../../google-breakpad-read-only/
--------------------------------------------------------------------------------
/lib/jni/native_exception_handler.cpp:
--------------------------------------------------------------------------------
1 | #include "native_exception_handler.h"
2 |
3 | #include "client/linux/handler/exception_handler.h"
4 | #include "client/linux/handler/minidump_descriptor.h"
5 |
6 | #include
7 |
8 | // debug/release (comment for release)
9 | #define DEBUG 1
10 |
11 | void debug(const char *format, ... ) {
12 | #ifdef DEBUG
13 | va_list argptr;
14 | va_start(argptr, format);
15 | __android_log_vprint(ANDROID_LOG_ERROR, "NATIVE_EXCEPTION_HANDLER", format, argptr);
16 | va_end(argptr);
17 | #endif
18 | }
19 |
20 | static jclass ExceptionHandlerClass = NULL;
21 | static jmethodID ExceptionHandlerMethod;
22 |
23 | static jclass ExceptionClass = NULL;
24 | static jmethodID ExceptionConstructor;
25 |
26 | static JavaVM *vm;
27 |
28 | bool breakpad_callback(const google_breakpad::MinidumpDescriptor& descriptor, void* context, bool succeeded) {
29 | const char * c_path = descriptor.path();
30 | debug("Dump path: %s\n", c_path);
31 |
32 | JNIEnv* env = NULL;
33 |
34 | if (vm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK)
35 | {
36 | debug("Failed to get the environment");
37 | return false;
38 | }
39 |
40 | debug("attaching thread ...");
41 | vm->AttachCurrentThread(&env, NULL);
42 |
43 | // create exception
44 | jstring j_path = env->NewStringUTF(c_path);
45 | jobject j_exception = env->NewObject(ExceptionClass, ExceptionConstructor, j_path);
46 |
47 | // throw exception
48 | env->CallStaticVoidMethod(ExceptionHandlerClass, ExceptionHandlerMethod, j_exception);
49 | env->DeleteLocalRef(j_exception);
50 |
51 | debug("exception handled");
52 |
53 | return succeeded;
54 | }
55 |
56 | // have to be create in heap
57 | static google_breakpad::MinidumpDescriptor *descriptor = NULL;
58 | static google_breakpad::ExceptionHandler *eh = NULL;
59 |
60 | void release()
61 | {
62 | if (descriptor != NULL) {
63 | delete descriptor;
64 | descriptor = NULL;
65 | }
66 |
67 | if (eh != NULL) {
68 | delete eh;
69 | eh = NULL;
70 | }
71 | }
72 |
73 | JNIEXPORT void JNICALL Java_name_antonsmirnov_android_acra_1breakpad_NativeExceptionHandler_nativeSetReportsDirectory
74 | (JNIEnv *env, jobject self, jstring j_reportsDirectory)
75 | {
76 | debug("init breakpad");
77 |
78 | const char *c_reportsDirectory = env->GetStringUTFChars(j_reportsDirectory, 0);
79 |
80 | debug("set reports directory: %s\n", c_reportsDirectory);
81 | std::string str_reportsDirectory(c_reportsDirectory);
82 | env->ReleaseStringUTFChars(j_reportsDirectory, c_reportsDirectory);
83 |
84 | // release if already init
85 | release();
86 |
87 | descriptor = new google_breakpad::MinidumpDescriptor(str_reportsDirectory);
88 | eh = new google_breakpad::ExceptionHandler(*descriptor, NULL, breakpad_callback, NULL, true, -1);
89 |
90 | debug("init breakpad done");
91 | }
92 |
93 | /*
94 | * Class: name_antonsmirnov_android_acra_breakpad_NativeExceptionHandler
95 | * Method: nativeRelease
96 | * Signature: ()V
97 | */
98 | JNIEXPORT void JNICALL Java_name_antonsmirnov_android_acra_1breakpad_NativeExceptionHandler_nativeRelease(JNIEnv *env, jobject self)
99 | {
100 | release();
101 | }
102 |
103 |
104 | void bind(JNIEnv *env)
105 | {
106 | ExceptionHandlerClass = (jclass)env->NewGlobalRef(env->FindClass("name/antonsmirnov/android/acra_breakpad/NativeExceptionHandler"));
107 | if (ExceptionHandlerClass == NULL)
108 | debug("ExceptionHandlerClass not bound");
109 |
110 | ExceptionHandlerMethod = env->GetStaticMethodID(ExceptionHandlerClass, "handleException", "(Lname/antonsmirnov/android/acra_breakpad/NativeException;)V");
111 | if (ExceptionHandlerMethod == NULL)
112 | debug("ExceptionHandlerMethod not bound");
113 |
114 | ExceptionClass = (jclass)env->NewGlobalRef(env->FindClass("name/antonsmirnov/android/acra_breakpad/NativeException"));
115 | if (ExceptionClass == NULL)
116 | debug("ExceptionClass not bound");
117 |
118 | ExceptionConstructor = env->GetMethodID(ExceptionClass, "", "(Ljava/lang/String;)V");
119 | if (ExceptionConstructor == NULL)
120 | debug("ExceptionConstructor not bound");
121 | }
122 |
123 | void unbind(JNIEnv *env)
124 | {
125 | if (ExceptionHandlerClass != NULL) {
126 | env->DeleteGlobalRef(ExceptionHandlerClass);
127 | ExceptionHandlerClass = NULL;
128 | }
129 |
130 | ExceptionHandlerMethod = NULL;
131 |
132 | if (ExceptionClass != NULL) {
133 | env->DeleteGlobalRef(ExceptionClass);
134 | ExceptionClass = NULL;
135 | }
136 |
137 | ExceptionConstructor = NULL;
138 | }
139 |
140 | // happens when library is loaded
141 | jint JNI_OnLoad(JavaVM* aVm, void* aReserved)
142 | {
143 | debug("JNI_OnLoad()");
144 |
145 | JNIEnv *env;
146 |
147 | if (aVm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK)
148 | {
149 | debug("Failed to get the environment");
150 | return -1;
151 | }
152 |
153 | bind(env);
154 | vm = aVm;
155 |
156 | return JNI_VERSION_1_6;
157 | }
158 |
159 | void JNI_OnUnload(JavaVM *aVm, void *reserved)
160 | {
161 | debug("JNI_OnUnload()");
162 |
163 | JNIEnv *env;
164 | if (aVm->GetEnv(reinterpret_cast(&env), JNI_VERSION_1_6) != JNI_OK)
165 | {
166 | debug("Failed to get the environment");
167 | return;
168 | }
169 |
170 | unbind(env);
171 | release();
172 | vm = NULL;
173 | }
--------------------------------------------------------------------------------
/lib/jni/native_exception_handler.h:
--------------------------------------------------------------------------------
1 | /* DO NOT EDIT THIS FILE - it is machine generated */
2 | #include
3 | /* Header for class name_antonsmirnov_android_acra_breakpad_NativeExceptionHandler */
4 |
5 | #ifndef _Included_name_antonsmirnov_android_acra_breakpad_NativeExceptionHandler
6 | #define _Included_name_antonsmirnov_android_acra_breakpad_NativeExceptionHandler
7 | #ifdef __cplusplus
8 | extern "C" {
9 | #endif
10 | /*
11 | * Class: name_antonsmirnov_android_acra_breakpad_NativeExceptionHandler
12 | * Method: nativeSetReportsDirectory
13 | * Signature: (Ljava/lang/String;)V
14 | */
15 | JNIEXPORT void JNICALL Java_name_antonsmirnov_android_acra_1breakpad_NativeExceptionHandler_nativeSetReportsDirectory
16 | (JNIEnv *, jobject, jstring);
17 |
18 | /*
19 | * Class: name_antonsmirnov_android_acra_breakpad_NativeExceptionHandler
20 | * Method: nativeRelease
21 | * Signature: ()V
22 | */
23 | JNIEXPORT void JNICALL Java_name_antonsmirnov_android_acra_1breakpad_NativeExceptionHandler_nativeRelease
24 | (JNIEnv *, jobject);
25 |
26 | #ifdef __cplusplus
27 | }
28 | #endif
29 | #endif
30 |
--------------------------------------------------------------------------------
/lib/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
6 | 4.0.0
7 |
8 | name.antonsmirnov.android
9 | acra_breakpad
10 | 1.0
11 | apklib
12 | acra_breakpad lib
13 | Acra-breakpad integration
14 |
15 |
16 |
17 | Anton Smirnov
18 | dev@antonsmirnov.name
19 |
20 |
21 |
22 |
23 |
24 |
25 | com.google.android
26 | android
27 | 4.0.1.2
28 | provided
29 |
30 |
31 |
32 | ch.acra
33 | acra
34 | 5.0.0-SNAPSHOT
35 | provided
36 |
37 |
38 |
39 |
40 |
41 | src
42 |
43 |
44 |
45 | com.jayway.maven.plugins.android.generation2
46 | android-maven-plugin
47 | 3.6.0
48 |
49 |
50 | alignApk
51 | install
52 |
53 |
54 |
55 | ${project.basedir}/src
56 | ${project.basedir}/res
57 |
58 | 16
59 |
60 | true
61 |
62 | true
63 |
64 |
65 |
66 |
67 |
68 |
--------------------------------------------------------------------------------
/lib/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | Choose board type
3 | Unable to detect Arduino board type automatically. Choose it from the list:
4 | Push \'Reset\' hardware button on the board within {0} seconds
5 |
--------------------------------------------------------------------------------
/lib/src/name/antonsmirnov/android/acra_breakpad/NativeException.java:
--------------------------------------------------------------------------------
1 | package name.antonsmirnov.android.acra_breakpad;
2 |
3 | /**
4 | * Native exception with stacktrace from native code
5 | */
6 | public class NativeException extends RuntimeException {
7 |
8 | private String reportPath;
9 |
10 | public String getReportPath() {
11 | return reportPath;
12 | }
13 |
14 | public NativeException(String reportPath) {
15 | this.reportPath = reportPath;
16 | }
17 | }
18 |
--------------------------------------------------------------------------------
/lib/src/name/antonsmirnov/android/acra_breakpad/NativeExceptionHandler.java:
--------------------------------------------------------------------------------
1 | package name.antonsmirnov.android.acra_breakpad;
2 |
3 | import android.app.Application;
4 | import android.os.Environment;
5 | import android.os.SystemClock;
6 | import org.acra.ACRA;
7 |
8 | import java.io.File;
9 |
10 | /**
11 | * Native exception handler
12 | */
13 | public class NativeExceptionHandler {
14 |
15 | static {
16 | System.loadLibrary("gnustl_shared");
17 | System.loadLibrary("native_exception_handler");
18 | }
19 |
20 | private native void nativeSetReportsDirectory(String directory);
21 |
22 | private File reportDirectory;
23 |
24 | private void setReportsDirectory(File directory) {
25 | this.reportDirectory = directory;
26 |
27 | if (!directory.exists())
28 | directory.mkdirs();
29 |
30 | nativeSetReportsDirectory(reportDirectory.getAbsolutePath());
31 | }
32 |
33 | /**
34 | * If invoked from native code on crash
35 | */
36 | public static void handleException(NativeException e) {
37 | // pass as binary file attachment
38 | ACRA.getConfig().setCrashDumpFile(e.getReportPath());
39 |
40 | ACRA.getErrorReporter().handleException(e);
41 | SystemClock.sleep(1000); // to let ACRA show dialog (otherwise ACRA dialog will not be shown)
42 | }
43 |
44 | /**
45 | * To be initialized once in Application.onCreate()
46 | */
47 | public boolean init(Application app) {
48 | // make sure report file is stored in public available storage to make it available for email app
49 | setReportsDirectory(Environment.getExternalStorageDirectory());
50 | return true;
51 | }
52 |
53 | private native void nativeRelease();
54 |
55 | /**
56 | * Have to be invoked before app quit
57 | */
58 | public void deinit() {
59 | nativeRelease();
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | name.antonsmirnov.android.acra_breakpad
8 | parent
9 | 1.0
10 | pom
11 |
12 |
13 |
14 | Anton Smirnov
15 | dev@antonsmirnov.name
16 |
17 |
18 |
19 |
20 |
21 |
22 | true
23 | org.apache.maven.plugins
24 | maven-compiler-plugin
25 | 2.3.2
26 |
27 | 1.5
28 | 1.5
29 |
30 |
31 |
32 |
33 |
34 |
35 | ./lib
36 | ./app
37 |
38 |
39 |
--------------------------------------------------------------------------------