IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 移动开发 -> CrashHandler -> 正文阅读

[移动开发]CrashHandler

崩溃日志显示Toast并输出至SD Card - 适配Android10

1、工具类

异常捕获Handler

public class CrashHandler implements Thread.UncaughtExceptionHandler {

    private Context mContext;

    // 用来存储应用信息和设备信息
    private Map<String, String> mInfo = new LinkedHashMap<>();

    // 默认的未捕获异常处理器
    private Thread.UncaughtExceptionHandler mDefaultHandler;

    /**
     * instance       实例
     * INSTANCE_LOCK  互斥锁
     */
    private static CrashHandler instance = null;
    private static final Object INSTANCE_LOCK = new Object();

    /**
     * 获取实例
     *
     * @return
     */
    public static CrashHandler getInstance() {
        if (instance == null) {
            synchronized (INSTANCE_LOCK) {
                if (instance == null) {
                    instance = new CrashHandler();
                }
            }
        }
        return instance;
    }

    /**
     * 初始化
     *
     * @param context
     */
    public void init(Context context) {
        mContext = context.getApplicationContext();
        // 获取默认的未捕获异常处理器
        mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
        // 设置CrashHandler为默认的未捕获异常处理器
        Thread.setDefaultUncaughtExceptionHandler(this);
    }


    /**
     * 捕获异常
     *
     * @param t
     * @param ex
     */
    @Override
    public void uncaughtException(@NonNull Thread t, @NonNull Throwable ex) {
        // 处理异常
        handleException(ex);
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        // 结束应用
        if (mDefaultHandler != null) {
            mDefaultHandler.uncaughtException(t, ex);
        } else {
            System.exit(1);
        }
    }

    /**
     * 处理异常 - 输出 Toast 及 输出到 sd card
     *
     * @param ex
     */
    private void handleException(Throwable ex) {
        final Throwable e = ex;
        // Toast提示出现异常
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(mContext, e.getLocalizedMessage(), Toast.LENGTH_SHORT).show();
                Looper.loop();
            }
        }.start();
        // 收集应用信息和设备信息
        collectInfo();
        // 保存崩溃信息到SD卡
        AndroidUtils.saveErrInfoToGalleryByScopedStorage(mContext, outputErrorLogInfo(ex));
    }


    /**
     * 错误日志
     *
     * @param ex
     * @return
     */
    private String outputErrorLogInfo(Throwable ex) {
        String deviceInfo = "";
        for (String key : mInfo.keySet()) {
            deviceInfo += key + "  : " + mInfo.get(key) + "\n";
        }
        return "Error Info : \n" + ex.getLocalizedMessage() + "\n\n" + "Device Info : \n" + deviceInfo;
    }


    /**
     * 收集信息
     */
    private void collectInfo() {
        // 收集BuildConfig类信息
//        collectClassInfo(BuildConfig.class);
        // 收集Build.VERSION类信息
        collectClassInfo(Build.VERSION.class);
        // 收集Build类信息
        collectClassInfo(Build.class);
    }

    /**
     * 收集信息
     *
     * @param cls
     */
    private void collectClassInfo(Class cls) {
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                mInfo.put(field.getName(), field.get(null).toString());
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
    }
}

崩溃日志输出至sd card

public class AndroidUtils {

    public static final String TAG = "AndroidUtils";


    /**
     * ERROR_LOG_FILE_PATH_1 --- Android 10 及以上错误日志存储路径
     * ERROR_LOG_FILE_PATH_2 --- Android 10 以下错误日志存储路径
     * ERROR_LOG_FILE_NAME   --- 错误日志文件名
     */
    public static final String ERROR_LOG_FILE_PATH_1 = "Download/UAT Error Logs";
    public static final String ERROR_LOG_FILE_PATH_2 = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "UAT Error Logs";
    public static final String ERROR_LOG_FILE_NAME = "errLog";

    /**
     * 错误日志输出到 sdk card
     * <p>
     * Android 10 及以上日志路径 --- /storage/sdcard/Download/UAT Error Logs
     * Android 10 以下日志路径   --- /storage/emulated/0/UAT Error Logs
     *
     * @param context
     * @param logContent
     * @return
     */
    public static boolean saveErrInfoToGalleryByScopedStorage(Context context, String logContent) {

        long timestamp = System.currentTimeMillis();
        String time = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss").format(new Date(timestamp));
        String fileName = ERROR_LOG_FILE_NAME + "_" + time + ".txt";

        FileOutputStream fos = null;
        OutputStream os = null;
        try {
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                //Android 10 及以上
                ContentValues values = new ContentValues();
                values.put(MediaStore.Downloads.DISPLAY_NAME, fileName);
                //设置文件类型
                values.put(MediaStore.Downloads.MIME_TYPE, "text/plain");
                //这个方法只可在Android10的手机上执行,设置路径
                values.put(MediaStore.Downloads.RELATIVE_PATH, ERROR_LOG_FILE_PATH_1);
                Uri external = MediaStore.Downloads.EXTERNAL_CONTENT_URI;
                // 写入文件
                Uri uri = context.getContentResolver().insert(external, values);
                if (uri != null) {
                    os = context.getContentResolver().openOutputStream(uri);
                    os.write(logContent.getBytes());
                    os.flush();
                    return true;
                }
            } else {
                //Android 10 以下
                File dir = new File(ERROR_LOG_FILE_PATH_2);
                if (!dir.exists()) {
                    dir.mkdir();
                }
                File file = new File(dir, fileName);
                if (!file.exists()) {
                    file.createNewFile();
                }
                fos = new FileOutputStream(file);
                fos.write(logContent.getBytes());
                fos.flush();
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, Log.getStackTraceString(e));
        } finally {
            closeIO(fos);
            closeIO(os);
        }
        return false;
    }

    /**
     * 关闭流,普通不严重的可采用此函数关闭
     */
    public static void closeIO(Closeable... closeables) {
        if (null == closeables || closeables.length <= 0) {
            return;
        }
        for (Closeable cb : closeables) {
            try {
                if (null == cb) {
                    continue;
                }
                cb.close();
            } catch (Exception e) {
                Log.e(TAG, Log.getStackTraceString(e));
            }
        }
    }
}

2、使用

public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        //崩溃日志
        CrashHandler.getInstance().init(this);
    }
}

程序崩溃闪退之后,在文件管理器中搜索UAT Error Logs文件夹
在这里插入图片描述
在这里插入图片描述

  移动开发 最新文章
Vue3装载axios和element-ui
android adb cmd
【xcode】Xcode常用快捷键与技巧
Android开发中的线程池使用
Java 和 Android 的 Base64
Android 测试文字编码格式
微信小程序支付
安卓权限记录
知乎之自动养号
【Android Jetpack】DataStore
上一篇文章      下一篇文章      查看所有文章
加:2021-07-29 11:46:00  更:2021-07-29 11:46:53 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/2 20:57:29-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码