Android实现APP奔溃日志记录保存

public class CrashHandler implements java.lang.Thread.UncaughtExceptionHandler {
    private java.lang.Thread.UncaughtExceptionHandler defaultUncaughtExceptionHandler;

    public void init() {
        defaultUncaughtExceptionHandler = java.lang.Thread.getDefaultUncaughtExceptionHandler();
        java.lang.Thread.setDefaultUncaughtExceptionHandler(this);
    }

    @Override
    public void uncaughtException(Thread t, Throwable e) {
        java.lang.String externalStorageDirectoryPath = android.os.Environment.getExternalStorageDirectory().getAbsolutePath();
        java.text.DateFormat dateFormatForDate = new java.text.SimpleDateFormat("yyyy-MM-dd", java.util.Locale.getDefault());
        java.util.Date date = new java.util.Date();
        java.lang.String path = externalStorageDirectoryPath  + java.io.File.separator + "crash-" + dateFormatForDate.format(date) + ".log";
        java.lang.StringBuilder stringBuilder = new java.lang.StringBuilder();
        java.text.DateFormat dateFormatForDateTime = new java.text.SimpleDateFormat("yyyy-MM-dd HH:mm:ss", java.util.Locale.getDefault());
        java.lang.String currentTime = dateFormatForDateTime.format(date);
        stringBuilder.append("CrashTime:").append(currentTime).append("\r\n");
        java.io.StringWriter stringWriter = new java.io.StringWriter();
        java.io.PrintWriter printWriter = new java.io.PrintWriter(stringWriter);
        e.printStackTrace(printWriter);
        java.lang.String stackTrace = stringWriter.toString();
        stringBuilder.append(stackTrace);
        try {
            java.io.File logFile = new java.io.File(path);
            java.io.FileWriter fileWriter = new java.io.FileWriter(logFile, true);
            fileWriter.write(stringBuilder.toString());
            fileWriter.close();
        } catch (java.io.IOException ioException) {
            ioException.printStackTrace();
        }
        if (defaultUncaughtExceptionHandler != null) {
            defaultUncaughtExceptionHandler.uncaughtException(t, e);
        } else {
            android.os.Process.killProcess(android.os.Process.myPid());
        }
    }
}

然后在自定义Application类的onCreate方法初始化即可

@Override
public void onCreate() {
    super.onCreate();
    CrashHandler crashHandler = new CrashHandler();
    crashHandler.init();

}

### 安卓开发应用闪退解决方案 安卓应用在实际运行过程中可能因多种原因导致闪退。以下是针对常见问题及其对应的解决方案: #### 1. **内存泄漏** 内存泄漏可能导致应用程序占用过多资源而崩溃。可以通过工具检测并修复潜在的内存泄漏问题。 ```java // 使用 LeakCanary 工具库来检测内存泄漏 dependencies { debugImplementation 'com.squareup.leakcanary:leakcanary-android' } ``` 如果发现有未释放的对象,应确保及时清理不再使用的对象实例[^3]。 #### 2. **权限缺失** 某些操作(如访问文件系统、摄像头等)需要特定权限。如果没有声明必要的权限,程序会抛出 `SecurityException` 并终止运行。 ```xml <!-- AndroidManifest.xml 中添加所需权限 --> <uses-permission android:name="android.permission.CAMERA"/> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> ``` 对于 Android 6.0 及以上版本,还需要动态请求权限: ```java if (ContextCompat.checkSelfPermission(this, Manifest.permission.CAMERA) != PackageManager.PERMISSION_GRANTED) { ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.CAMERA}, REQUEST_CODE); } ``` #### 3. **生命周期管理不当** 当 Activity 或 Fragment 的状态发生变化时(例如屏幕旋转),未能正确处理生命周期事件可能导致异常退出。可以在配置中指定忽略某些变化: ```xml <!-- 防止横竖屏切换引发重启 --> <activity android:name=".YourActivity" android:configChanges="orientation|keyboardHidden|screenSize" android:screenOrientation="portrait"> </activity> ``` 此方法适用于避免由于方向改变引起的重新加载行为[^2]。 #### 4. **第三方依赖冲突** 项目中的多个库可能存在版本兼容性问题,这通常表现为 `NoClassDefFoundError` 或其他类加载错误。通过检查 Gradle 文件中的依赖树可以帮助定位此类问题: ```bash ./gradlew :app:dependencies ``` 一旦发现问题,则需统一各模块所使用的库版本号。 #### 5. **NDK/Native Code 错误** 涉及 C/C++ 编写的原生代码也可能成为不稳定因素之一。调试这类问题较为复杂,建议启用更详细的日志记录以便追踪根源所在。 ```cpp #include <android/log.h> #define LOG_TAG "NativeCode" #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG ,__VA_ARGS__) LOGE("An error occurred!"); ``` #### 6. **ProGuard/R8混淆规则不足** 发布版 APK 经过 ProGuard 或 R8 处理后,若保留规则定义不够全面,可能会破坏原有逻辑结构从而引起现象。因此要仔细校验 `.pro` 文件的内容是否涵盖了所有必需的部分[^4]。 --- ### 示例代码片段 以下是一个简单的全局异常捕获器实现,用于收集未被捕获的异常信息并向服务器发送报告: ```java public class CrashHandler implements Thread.UncaughtExceptionHandler { private static final String TAG = "CrashHandler"; @Override public void uncaughtException(Thread thread, Throwable throwable) { Log.e(TAG, "Uncaught exception detected", throwable); // 将堆栈跟踪保存至本地或者上传远程服务端 StringWriter sw = new StringWriter(); PrintWriter pw = new PrintWriter(sw); throwable.printStackTrace(pw); String stackTrace = sw.toString(); // 停留几秒钟让用户看到提示后再关闭应用 try {Thread.sleep(3000);} catch (InterruptedException ignored){} System.exit(-1); // 强制结束进程 } } ``` 注册该处理器只需一步即可完成: ```java Thread.setDefaultUncaughtExceptionHandler(new CrashHandler()); ``` ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值