You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android应用SIGSEGV故障排查:本地存崩溃日志或持续日志监控

解决方案:持续查看日志与离线崩溃日志存储

一、无需重装应用,持续查看实时日志

1. 利用Android Studio的进程绑定与Logcat过滤

别用Android Studio的「重启」按钮(会触发重装),改成在设备上手动重启应用。重启后,在Android Studio的Logcat面板:

  • 顶部进程选择器中,找到应用的新进程(包名标识)选中;
  • 或者设置Logcat过滤规则为package:<你的应用包名>,这样不管应用重启多少次,只要进程属于该包名,日志都会自动显示,无需手动切换。

另外,通过「Run > Attach debugger to Android process」绑定到运行中的应用进程,绑定后Logcat会持续输出该进程日志,应用重启后重新绑定新进程即可,全程不会重装应用。

2. 使用ADB命令行日志工具

直接用ADB命令行绕开Android Studio的限制:

  • 实时查看应用日志:
    adb logcat -s <你的应用包名>
    
  • 将日志保存到电脑本地文件,方便后续排查:
    adb logcat -s <你的应用包名> > crash_log.txt
    

应用重启后,该命令会自动捕获新进程的日志,全程不会触发重装。

二、离线运行时将崩溃日志本地存储

1. Java层异常捕获存储

自定义全局异常处理器,捕获Java层未处理异常并写入本地文件:

public class CrashLogger implements Thread.UncaughtExceptionHandler {
    private final Thread.UncaughtExceptionHandler defaultHandler;
    private final Context appContext;

    public CrashLogger(Context context) {
        appContext = context.getApplicationContext();
        defaultHandler = Thread.getDefaultUncaughtExceptionHandler();
    }

    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        saveCrashLog(throwable);
        // 交给系统默认处理器处理崩溃
        defaultHandler.uncaughtException(thread, throwable);
    }

    private void saveCrashLog(Throwable throwable) {
        File logDir = new File(appContext.getExternalFilesDir(null), "crash_logs");
        if (!logDir.exists()) {
            logDir.mkdirs();
        }
        File logFile = new File(logDir, "crash_" + System.currentTimeMillis() + ".txt");
        try (PrintWriter writer = new PrintWriter(new FileWriter(logFile))) {
            throwable.printStackTrace(writer);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

在Application类的onCreate()中初始化:

@Override
public void onCreate() {
    super.onCreate();
    Thread.setDefaultUncaughtExceptionHandler(new CrashLogger(this));
}

日志会存在设备的Android/data/<你的包名>/files/crash_logs目录下,Android 10+无需额外存储权限。

2. Native层SIGSEGV崩溃捕获存储

SIGSEGV属于原生信号,Java层处理器抓不到,需要在JNI层注册信号处理器:

#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <unistd.h>
#include <android/log.h>

#define LOG_TAG "NativeCrash"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)

static void nativeCrashHandler(int sig) {
    // 构建日志存储路径(应用私有外部存储)
    char logPath[256];
    const char* externalDir = getenv("EXTERNAL_STORAGE");
    if (externalDir == NULL) return;
    snprintf(logPath, sizeof(logPath), "%s/Android/data/<你的包名>/files/crash_logs/native_crash_%ld.txt", externalDir, time(NULL));
    
    FILE* logFile = fopen(logPath, "w");
    if (logFile != NULL) {
        fprintf(logFile, "Native crash triggered by signal: %d\n", sig);
        // 可选:打印调用堆栈(需链接libunwind等库实现)
        fclose(logFile);
        LOGD("Native crash log saved to %s", logPath);
    }
    
    // 恢复系统默认信号处理,避免死循环
    signal(sig, SIG_DFL);
    raise(sig);
}

void registerNativeCrashHandlers() {
    signal(SIGSEGV, nativeCrashHandler);
    signal(SIGABRT, nativeCrashHandler);
    // 可添加其他需捕获的信号:SIGILL、SIGFPE等
}

在JNI_OnLoad中注册处理器:

jint JNI_OnLoad(JavaVM* vm, void* reserved) {
    registerNativeCrashHandlers();
    return JNI_VERSION_1_6;
}

之后用ADB拉取日志到电脑:

adb pull /sdcard/Android/data/<你的包名>/files/crash_logs/ .

内容的提问来源于stack exchange,提问作者Artie Vandelay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.19 14:05:22