├── .gitignore
├── app
├── .gitignore
├── build.gradle
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wsy
│ │ └── crashcatcher
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ │ ├── CMakeLists.txt
│ │ └── test_crash.cpp
│ ├── java
│ │ └── com
│ │ │ └── wsy
│ │ │ └── crashcatcher
│ │ │ └── MainActivity.java
│ └── res
│ │ ├── drawable-v24
│ │ └── ic_launcher_foreground.xml
│ │ ├── drawable
│ │ └── ic_launcher_background.xml
│ │ ├── layout
│ │ └── activity_main.xml
│ │ ├── mipmap-anydpi-v26
│ │ ├── ic_launcher.xml
│ │ └── ic_launcher_round.xml
│ │ ├── mipmap-hdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-mdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ ├── mipmap-xxxhdpi
│ │ ├── ic_launcher.png
│ │ └── ic_launcher_round.png
│ │ └── values
│ │ ├── colors.xml
│ │ ├── strings.xml
│ │ └── styles.xml
│ └── test
│ └── java
│ └── com
│ └── wsy
│ └── crashcatcher
│ └── ExampleUnitTest.java
├── build.gradle
├── crashdumper
├── .gitignore
├── build.gradle
├── consumer-rules.pro
├── proguard-rules.pro
└── src
│ ├── androidTest
│ └── java
│ │ └── com
│ │ └── wsy
│ │ └── crashcatcher
│ │ └── ExampleInstrumentedTest.java
│ ├── main
│ ├── AndroidManifest.xml
│ ├── cpp
│ │ ├── CMakeLists.txt
│ │ ├── crash_dumper.cpp
│ │ ├── readelf.cpp
│ │ ├── readelf.h
│ │ ├── stack_tracer.cpp
│ │ └── stack_tracer.h
│ └── java
│ │ └── com
│ │ └── wsy
│ │ └── crashcatcher
│ │ ├── CrashDumper.java
│ │ ├── HandleMode.java
│ │ └── NativeCrashListener.java
│ └── test
│ └── java
│ └── com
│ └── wsy
│ └── crashcatcher
│ └── ExampleUnitTest.java
├── gradle.properties
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── readme.md
├── sample_log.txt
├── screenshot.png
└── settings.gradle
/.gitignore:
--------------------------------------------------------------------------------
1 | *.iml
2 | .gradle
3 | /local.properties
4 | /.idea/caches
5 | /.idea/libraries
6 | /.idea/modules.xml
7 | /.idea/workspace.xml
8 | /.idea/navEditor.xml
9 | /.idea/assetWizardSettings.xml
10 | .DS_Store
11 | /build
12 | /captures
13 | .externalNativeBuild
14 | .cxx
15 |
--------------------------------------------------------------------------------
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/app/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.application'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.3"
6 |
7 | defaultConfig {
8 | applicationId "com.wsy.crashcatcher"
9 | minSdkVersion 21
10 | targetSdkVersion 29
11 | versionCode 1
12 | versionName "1.0"
13 |
14 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
15 | ndk{
16 | // abiFilters "armeabi-v7a"
17 | abiFilters "arm64-v8a"
18 | }
19 | }
20 |
21 | buildTypes {
22 | release {
23 | minifyEnabled false
24 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
25 | }
26 | }
27 | externalNativeBuild {
28 | cmake {
29 | path "src/main/cpp/CMakeLists.txt"
30 | version "3.10.2"
31 | }
32 | }
33 | }
34 |
35 | dependencies {
36 | implementation fileTree(dir: "libs", include: ["*.jar"])
37 | implementation 'androidx.appcompat:appcompat:1.1.0'
38 | implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
39 | implementation project(path: ':crashdumper')
40 | testImplementation 'junit:junit:4.12'
41 | androidTestImplementation 'androidx.test.ext:junit:1.1.1'
42 | androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0'
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/app/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/app/src/androidTest/java/com/wsy/crashcatcher/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.wsy.crashcatcher;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.wsy.crashcatcher", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/app/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
5 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
--------------------------------------------------------------------------------
/app/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | # For more information about using CMake with Android Studio, read the
2 | # documentation: https://d.android.com/studio/projects/add-native-code.html
3 |
4 | # Sets the minimum version of CMake required to build the native library.
5 |
6 | cmake_minimum_required(VERSION 3.4.1)
7 |
8 | # Creates and names a library, sets it as either STATIC
9 | # or SHARED, and provides the relative paths to its source code.
10 | # You can define multiple libraries, and CMake builds them for you.
11 | # Gradle automatically packages shared libraries with your APK.
12 | add_library( # Sets the name of the library.
13 | test_crash
14 |
15 | # Sets the library as a shared library.
16 | SHARED
17 |
18 | # Provides a relative path to your source file(s).
19 | test_crash.cpp
20 | )
21 |
22 | # Searches for a specified prebuilt library and stores the path as a
23 | # variable. Because CMake includes system libraries in the search path by
24 | # default, you only need to specify the name of the public NDK library
25 | # you want to add. CMake verifies that the library exists before
26 | # completing its build.
27 |
28 | find_library( # Sets the name of the path variable.
29 | log-lib
30 |
31 | # Specifies the name of the NDK library that
32 | # you want CMake to locate.
33 | log)
34 |
35 | # Specifies libraries CMake should link to your target library. You
36 | # can link multiple libraries, such as libraries you define in this
37 | # build script, prebuilt third-party libraries, or system libraries.
38 |
39 | target_link_libraries( # Specifies the target library.
40 | test_crash
41 |
42 | # Links the target library to the log library
43 | # included in the NDK.
44 | ${log-lib})
--------------------------------------------------------------------------------
/app/src/main/cpp/test_crash.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 |
4 | #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,"wsy" ,__VA_ARGS__)
5 |
6 | void raiseError(int signal) {
7 | raise(signal);
8 | }
9 |
10 | extern "C"
11 | JNIEXPORT void JNICALL
12 | Java_com_wsy_crashcatcher_MainActivity_nativeCrash(JNIEnv *env, jobject thiz) {
13 | raiseError(SIGABRT);
14 | }
--------------------------------------------------------------------------------
/app/src/main/java/com/wsy/crashcatcher/MainActivity.java:
--------------------------------------------------------------------------------
1 | package com.wsy.crashcatcher;
2 |
3 | import androidx.appcompat.app.AppCompatActivity;
4 |
5 | import android.os.Build;
6 | import android.os.Bundle;
7 | import android.os.Looper;
8 | import android.util.Log;
9 | import android.view.View;
10 | import android.widget.CheckBox;
11 | import android.widget.CompoundButton;
12 | import android.widget.RadioGroup;
13 | import android.widget.TextView;
14 |
15 | import com.wsy.crashcatcher.CrashDumper;
16 | import com.wsy.crashcatcher.HandleMode;
17 | import com.wsy.crashcatcher.NativeCrashListener;
18 |
19 | import java.io.FileInputStream;
20 | import java.io.IOException;
21 |
22 | public class MainActivity extends AppCompatActivity implements RadioGroup.OnCheckedChangeListener {
23 | static {
24 | System.loadLibrary("test_crash");
25 | }
26 |
27 | private static final String TAG = "MainActivity";
28 |
29 | native void nativeCrash();
30 |
31 | private RadioGroup radioGroup;
32 | private TextView tvCrashLog;
33 |
34 | @Override
35 | protected void onCreate(Bundle savedInstanceState) {
36 | super.onCreate(savedInstanceState);
37 | setContentView(R.layout.activity_main);
38 | initView();
39 | }
40 |
41 | private void initView() {
42 | tvCrashLog = findViewById(R.id.tv_crash_log);
43 | radioGroup = findViewById(R.id.rg_handle_mode);
44 | radioGroup.setOnCheckedChangeListener(this);
45 | }
46 |
47 | public void crash(View view) {
48 | nativeCrash();
49 | }
50 |
51 |
52 | private String readContentFromFile(String path) {
53 | FileInputStream fis = null;
54 | try {
55 | fis = new FileInputStream(path);
56 | byte[] data = new byte[fis.available()];
57 | fis.read(data);
58 | fis.close();
59 | return new String(data);
60 | } catch (IOException e) {
61 | e.printStackTrace();
62 | return null;
63 | }
64 | }
65 |
66 | @Override
67 | public void onCheckedChanged(RadioGroup group, int checkedId) {
68 | HandleMode handleMode;
69 | switch (checkedId){
70 | case R.id.rb_notice_callback:
71 | handleMode = HandleMode.NOTICE_CALLBACK;
72 | break;
73 | case R.id.rb_raise_error:
74 | handleMode = HandleMode.RAISE_ERROR;
75 | break;
76 | case R.id.rb_do_nothing:
77 | default:
78 | handleMode = HandleMode.DO_NOTHING;
79 | break;
80 | }
81 |
82 | CrashDumper.init(getFilesDir().getAbsolutePath(), new NativeCrashListener() {
83 | @Override
84 | public void onSignalReceived(int signal, final String logPath) {
85 | final String content = readContentFromFile(logPath);
86 | Log.i(TAG, "onSignalReceived: " + content);
87 | runOnUiThread(new Runnable() {
88 | @Override
89 | public void run() {
90 | tvCrashLog.setText(content);
91 | }
92 | });
93 | }
94 | }, handleMode);
95 | }
96 | }
97 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable-v24/ic_launcher_foreground.xml:
--------------------------------------------------------------------------------
1 |
7 |
8 |
9 |
15 |
18 |
21 |
22 |
23 |
24 |
30 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/ic_launcher_background.xml:
--------------------------------------------------------------------------------
1 |
2 |
7 |
10 |
15 |
20 |
25 |
30 |
35 |
40 |
45 |
50 |
55 |
60 |
65 |
70 |
75 |
80 |
85 |
90 |
95 |
100 |
105 |
110 |
115 |
120 |
125 |
130 |
135 |
140 |
145 |
150 |
155 |
160 |
165 |
170 |
171 |
--------------------------------------------------------------------------------
/app/src/main/res/layout/activity_main.xml:
--------------------------------------------------------------------------------
1 |
2 |
8 |
12 |
17 |
22 |
23 |
27 |
32 |
37 |
42 |
47 |
48 |
49 |
56 |
57 |
61 |
62 |
63 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
--------------------------------------------------------------------------------
/app/src/main/res/values/colors.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 | #6200EE
4 | #3700B3
5 | #03DAC5
6 |
--------------------------------------------------------------------------------
/app/src/main/res/values/strings.xml:
--------------------------------------------------------------------------------
1 |
2 | CrashCatcher
3 |
--------------------------------------------------------------------------------
/app/src/main/res/values/styles.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
9 |
10 |
--------------------------------------------------------------------------------
/app/src/test/java/com/wsy/crashcatcher/ExampleUnitTest.java:
--------------------------------------------------------------------------------
1 | package com.wsy.crashcatcher;
2 |
3 | import org.junit.Test;
4 |
5 | import static org.junit.Assert.*;
6 |
7 | /**
8 | * Example local unit test, which will execute on the development machine (host).
9 | *
10 | * @see Testing documentation
11 | */
12 | public class ExampleUnitTest {
13 | @Test
14 | public void addition_isCorrect() {
15 | assertEquals(4, 2 + 2);
16 | }
17 | }
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | // Top-level build file where you can add configuration options common to all sub-projects/modules.
2 | buildscript {
3 | repositories {
4 | google()
5 | jcenter()
6 | }
7 | dependencies {
8 | classpath "com.android.tools.build:gradle:4.0.0"
9 |
10 | // NOTE: Do not place your application dependencies here; they belong
11 | // in the individual module build.gradle files
12 | }
13 | }
14 |
15 | allprojects {
16 | repositories {
17 | google()
18 | jcenter()
19 | }
20 | }
21 |
22 | task clean(type: Delete) {
23 | delete rootProject.buildDir
24 | }
--------------------------------------------------------------------------------
/crashdumper/.gitignore:
--------------------------------------------------------------------------------
1 | /build
--------------------------------------------------------------------------------
/crashdumper/build.gradle:
--------------------------------------------------------------------------------
1 | apply plugin: 'com.android.library'
2 |
3 | android {
4 | compileSdkVersion 29
5 | buildToolsVersion "29.0.3"
6 |
7 | defaultConfig {
8 | minSdkVersion 21
9 | targetSdkVersion 29
10 | versionCode 1
11 | versionName "1.0"
12 |
13 | testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
14 | consumerProguardFiles "consumer-rules.pro"
15 | ndk {
16 | abiFilters "arm64-v8a","armeabi-v7a"
17 | }
18 | }
19 |
20 | buildTypes {
21 | release {
22 | minifyEnabled false
23 | proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
24 | }
25 | }
26 | externalNativeBuild {
27 | cmake {
28 | path "src/main/cpp/CMakeLists.txt"
29 | version "3.10.2"
30 | }
31 | }
32 | }
--------------------------------------------------------------------------------
/crashdumper/consumer-rules.pro:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/wangshengyang1996/CrashCatcher/3d7cc5314c8b54e4528b7a676e769e07b3fcd19c/crashdumper/consumer-rules.pro
--------------------------------------------------------------------------------
/crashdumper/proguard-rules.pro:
--------------------------------------------------------------------------------
1 | # Add project specific ProGuard rules here.
2 | # You can control the set of applied configuration files using the
3 | # proguardFiles setting in build.gradle.
4 | #
5 | # For more details, see
6 | # http://developer.android.com/guide/developing/tools/proguard.html
7 |
8 | # If your project uses WebView with JS, uncomment the following
9 | # and specify the fully qualified class name to the JavaScript interface
10 | # class:
11 | #-keepclassmembers class fqcn.of.javascript.interface.for.webview {
12 | # public *;
13 | #}
14 |
15 | # Uncomment this to preserve the line number information for
16 | # debugging stack traces.
17 | #-keepattributes SourceFile,LineNumberTable
18 |
19 | # If you keep the line number information, uncomment this to
20 | # hide the original source file name.
21 | #-renamesourcefileattribute SourceFile
--------------------------------------------------------------------------------
/crashdumper/src/androidTest/java/com/wsy/crashcatcher/ExampleInstrumentedTest.java:
--------------------------------------------------------------------------------
1 | package com.wsy.crashcatcher;
2 |
3 | import android.content.Context;
4 |
5 | import androidx.test.platform.app.InstrumentationRegistry;
6 | import androidx.test.ext.junit.runners.AndroidJUnit4;
7 |
8 | import org.junit.Test;
9 | import org.junit.runner.RunWith;
10 |
11 | import static org.junit.Assert.*;
12 |
13 | /**
14 | * Instrumented test, which will execute on an Android device.
15 | *
16 | * @see Testing documentation
17 | */
18 | @RunWith(AndroidJUnit4.class)
19 | public class ExampleInstrumentedTest {
20 | @Test
21 | public void useAppContext() {
22 | // Context of the app under test.
23 | Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
24 | assertEquals("com.wsy.crashcatcher.test", appContext.getPackageName());
25 | }
26 | }
--------------------------------------------------------------------------------
/crashdumper/src/main/AndroidManifest.xml:
--------------------------------------------------------------------------------
1 |
3 |
4 | /
5 |
--------------------------------------------------------------------------------
/crashdumper/src/main/cpp/CMakeLists.txt:
--------------------------------------------------------------------------------
1 | cmake_minimum_required(VERSION 3.4.1)
2 |
3 | add_library(
4 | crash_dumper
5 |
6 | SHARED
7 |
8 | crash_dumper.cpp
9 | stack_tracer.cpp
10 | readelf.cpp)
11 |
12 |
13 | find_library(
14 | log-lib
15 |
16 | log)
17 |
18 | target_link_libraries(
19 | crash_dumper
20 |
21 | ${log-lib})
--------------------------------------------------------------------------------
/crashdumper/src/main/cpp/crash_dumper.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include
3 | #include
4 | #include
5 | #include