美文网首页Android技术知识Android进阶之路
Android性能优化 Java Crash监控

Android性能优化 Java Crash监控

作者: 进击的包籽 | 来源:发表于2021-06-07 09:24 被阅读0次

    1.什么是Crash

    • Crash也就是APP代码异常奔溃,从而导致App闪退,也许我们在开发的时候测试一切正常,但是在线上,用户量多起来之后,什么五花八门的机子都有,多多少少会发生Crash。
    • 当App奔溃后,我们应及时记录下问题,保存到文件,待下次启动app时,再上传服务器,然后分析错误日志,修改问题。
    • Android 有Java层的Crash,还有Native层Carsh,这次先了解怎么拿到Java层的Crash。

    2.Java层Crash

    • Java的Crash比较简单,Java中的Thread定义了一个接口:UncaughtExceptionHandler,用于处理未捕获的异常导致线程的终止,但是try/catch 的错误捕获不了。
    • 当我们的应用crash的时候,就会走 UncaughtExceptionHandler.uncaughtException ,在该方法中可以获取到异常的信息,通过 Thread.setDefaultUncaughtExceptionHandler 该方法来设置线程的默认异常处理器。
    • 重写完成 uncaughtException 逻辑后,记得再调用一次uncaughtException(t, e),否则可能会白屏,APP也在那傻等。
    • Carsh文件可以保存后上传服务器,也可以在下次打开App上传。

    2.1 保存Crash信息

    public class TestCrashHandler implements Thread.UncaughtExceptionHandler {
        //crash存储文件夹, /Android/data/包名/files/crash_info/目录下
        private static final String CRASH_FILES = "crash_info";
        //crash文件后缀
        private static final String CRASH_FILE_NAME = "_crash.txt";
        private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    
        private static Context mContext;
        private static Thread.UncaughtExceptionHandler uncaughtExceptionHandler;
    
    
        private SimpleDateFormat dateFormat = new SimpleDateFormat(DATE_FORMAT);
    
        public static void init(Context context) {
            mContext = context.getApplicationContext();
    
            uncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler();
            Thread.setDefaultUncaughtExceptionHandler(new TestCrashHandler());
        }
    
        @Override
        public void uncaughtException(@NonNull @NotNull Thread t, @NonNull @NotNull Throwable e) {
            saveCrash(t, e);
        }
    
        /**
         * 将Crash信息保存起来
         *
         * @param t
         * @param e
         */
        private void saveCrash(@NonNull @NotNull Thread t, @NonNull @NotNull Throwable e) {
            //创建文件夹 /Android/data/包名/files/crash_info/目录下
            File dir = mContext.getExternalFilesDir(CRASH_FILES);
            if (!dir.exists()) {
                dir.mkdirs();
            }
            //Crash时间
            String time = dateFormat.format(System.currentTimeMillis());
            File file = new File(dir, time + CRASH_FILE_NAME);
    
            PrintWriter printWriter = null;
            FileWriter fileWriter = null;
            try {
                fileWriter = new FileWriter(file);
                printWriter = new PrintWriter(fileWriter);
                //异常时间
                printWriter.write("Crash_Time : " + time + "\n");
                //手机信息
                printWriter.write(phoneInfo());
                //线程信息
                printWriter.write("Thread : " + t.getName() + "\n");
                //异常信息
                printWriter.write("Exception : " );
                e.printStackTrace( printWriter);
            } catch (IOException | PackageManager.NameNotFoundException ioException) {
                ioException.printStackTrace();
            } finally {
                try {
                    if (printWriter != null) {
                        printWriter.flush();
                        printWriter.close();
                    }
                    if (fileWriter != null) {
                        fileWriter.flush();
                        fileWriter.close();
                    }
                } catch (IOException ioException) {
                    ioException.printStackTrace();
                }
                //如果不写,APP就可能白屏,不闪退,也就是不处理
                if (uncaughtExceptionHandler != null) {
                    uncaughtExceptionHandler.uncaughtException(t, e);
                }
            }
        }
    
        /**
         * 获取App信息、手机信息、获取其他需要的信息
         *
         * @return
         * @throws PackageManager.NameNotFoundException
         */
        private String phoneInfo() throws PackageManager.NameNotFoundException {
            StringBuilder stringBuilder = new StringBuilder();
    
            PackageManager pkm = mContext.getPackageManager();
            PackageInfo packageInfo = pkm.getPackageInfo(mContext.getPackageName(), PackageManager.GET_ACTIVITIES);
    
            //App版本
            stringBuilder.append("App_VersionName : ");
            stringBuilder.append(packageInfo.versionName);
            stringBuilder.append("\n");
            stringBuilder.append("App_VersionCode : ");
            stringBuilder.append(packageInfo.versionCode);
            stringBuilder.append("\n");
    
            //Android版本号
            stringBuilder.append("Android_Version : ");
            stringBuilder.append(Build.VERSION.RELEASE);
            stringBuilder.append("\n");
            stringBuilder.append("Android_VersionCode : ");
            stringBuilder.append(Build.VERSION.SDK_INT);
            stringBuilder.append("\n");
    
            //手机厂商
            stringBuilder.append("Vendor : ");
            stringBuilder.append(Build.MANUFACTURER);
            stringBuilder.append("\n");
    
            //手机型号
            stringBuilder.append("Phone_Model : ");
            stringBuilder.append(Build.MODEL);
            stringBuilder.append("\n");
    
            //CPU架构
            stringBuilder.append("CPU : ");
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                stringBuilder.append(Arrays.toString(Build.SUPPORTED_ABIS));
            } else {
                stringBuilder.append(Build.CPU_ABI);
            }
            stringBuilder.append("\n");
    
            return stringBuilder.toString();
        }
    }
    
    

    2.2 测试

    public class CrashTestReport {
        public static void init(Context application){
            TestCrashHandler.init(application);
        }
        
        /**
         * RuntimeException
         */
        public static void test1(){
            int i = 1/0;
        }
    
        /**
         * StackOverflowError
         */
        public static void test2(){
            test2();
        }
    }
    
    

    2.3 文件里的Crash信息

    • test1方法测试结果,RuntimeException。
    Crash_Time : 2021-06-04 22:43:56
    App_VersionName : 1.0
    App_VersionCode : 1
    Android_Version : 10
    Android_VersionCode : 29
    Vendor : HUAWEI
    Phone_Model : VOG-AL00
    CPU : [arm64-v8a, armeabi-v7a, armeabi]
    Thread : main
    Exception : java.lang.RuntimeException: Unable to start activity ComponentInfo{com.bao.myapplication/com.bao.myapplication.MainActivity}: java.lang.ArithmeticException: divide by zero
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3898)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4081)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2462)
        at android.os.Handler.dispatchMessage(Handler.java:110)
        at android.os.Looper.loop(Looper.java:219)
        at android.app.ActivityThread.main(ActivityThread.java:8393)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
    Caused by: java.lang.ArithmeticException: divide by zero
        at com.bao.myapplication.carsh.CrashTestReport.test1(CrashTestReport.java:11)
        at com.bao.myapplication.MainActivity.onCreate(MainActivity.kt:79)
        at android.app.Activity.performCreate(Activity.java:8121)
        at android.app.Activity.performCreate(Activity.java:8109)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1320)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3871)
        ... 11 more
    
    
    • test2 方法测试结果,StackOverflowError。
    Crash_Time : 2021-06-05 00:49:39
    App_VersionName : 1.0
    App_VersionCode : 1
    Android_Version : 10
    Android_VersionCode : 29
    Vendor : HUAWEI
    Phone_Model : VOG-AL00
    CPU : [arm64-v8a, armeabi-v7a, armeabi]
    Thread : main
    Exception : java.lang.StackOverflowError: stack size 8192KB
       at com.bao.myapplication.carsh.CrashTestReport.test2(CrashTestReport.java:15)
       at com.bao.myapplication.carsh.CrashTestReport.test2(CrashTestReport.java:15)
       at com.bao.myapplication.carsh.CrashTestReport.test2(CrashTestReport.java:15)
       .
       .
       at com.bao.myapplication.carsh.CrashTestReport.test2(CrashTestReport.java:15)
       at com.bao.myapplication.carsh.CrashTestReport.test2(CrashTestReport.java:15)
       at com.bao.myapplication.MainActivity.onCreate(MainActivity.kt:79)
       at android.app.Activity.performCreate(Activity.java:8121)
       at android.app.Activity.performCreate(Activity.java:8109)
       at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1320)
       at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3871)
       at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:4081)
       at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:91)
       at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:149)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:103)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2462)
       at android.os.Handler.dispatchMessage(Handler.java:110)
       at android.os.Looper.loop(Looper.java:219)
       at android.app.ActivityThread.main(ActivityThread.java:8393)
       at java.lang.reflect.Method.invoke(Native Method)
       at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:513)
       at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1055)
    
    

    相关文章

      网友评论

        本文标题:Android性能优化 Java Crash监控

        本文链接:https://www.haomeiwen.com/subject/zeofeltx.html