Android exception capture

Posted by .Darkman on Mon, 04 May 2020 19:04:05 +0200

Android exception capture and write text

Application scenario

 The developed software application inevitably has various problems in the actual scene, but the developers can't debug in real time on the spot, and the remote can't present the scene, so that
 It can't solve this problem. The best solution is to integrate Tencent's mobile analysis. It can monitor every step of the user's operation in real time and the place where the problem occurs. However, if the software
 This method has no effect in the Intranet environment, so you can catch the exception and write it to the text. You can debug according to this text

Code

/**
*  Inherit UncaughtExceptionHandler all unhandled exceptions are handled by this class
*/
public class CrashHandler implements Thread.UncaughtExceptionHandler {
    private Context context;
    public static final String TAG = "CrashHandler";
    //System default UncaughtException handling class
    private Thread.UncaughtExceptionHandler mDefaultHandler;
    //CrashHandler instance
    private static CrashHandler crashHandler;
    //Used to store device information and exception information
    private Map<String, String> infos = new HashMap<>();
    //To format the date as part of the log file name
    private DateFormat formatter = new SimpleDateFormat("yyyy-MM-dd-HH-mm-ss");


    /**
     * Ensure that there is only one instance of CrashHandler
     */
    private CrashHandler() {
    }


    /**
     * Get CrashHandler instance in singleton mode
     * @return
     */
    public static CrashHandler getInstance() {
        if (crashHandler == null) {
            crashHandler = new CrashHandler();
        }
        return crashHandler;
    }


     /**
     * This method must be initialized in Application.
     */
    public void init(Context context) {
            this.context = context;
            //Get the default UncaughtException processor of the system
            mDefaultHandler = Thread.getDefaultUncaughtExceptionHandler();
            //Set the CrashHandler as the default processor of the program
            Thread.setDefaultUncaughtExceptionHandler(this);
        }


    /**
     * When UncaughtException occurs, it will be transferred to this function for processing
     */
    @Override
    public void uncaughtException(Thread thread, Throwable throwable) {
        if (!handleException(throwable) && mDefaultHandler != null) {
            //If the user does not handle it, let the system default exception handler handle it
            mDefaultHandler.uncaughtException(thread, throwable);
        } else {
            try {
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                Log.e(TAG, "error : ", e);
            }
            //Exit program
            android.os.Process.killProcess(android.os.Process.myPid());
            System.exit(1);
        }
    }


   /**
     * Custom error handling, collecting error information and sending error report are all done here
     * @param ex
     * @return true:If the exception information is handled; otherwise, false is returned
     */
    private boolean handleException(Throwable ex) {
        if (ex == null) {
            return false;
        }
        Log.d("Exception:", ex.getMessage());
        new Thread() {
            @Override
            public void run() {
                Looper.prepare();
                Toast.makeText(context, "I'm sorry,Program exception,About to exit crash View error log in folder", 
                        Toast.LENGTH_LONG).show();
                Looper.loop();
            }
        }.start();
        //Collect device parameter information
        collectDeviceInfo(context);
        //Save log information
        saveCrashInfoFile(ex);
        return true;
    }


   /**
     * Save error information to file
     * @param ex
     * @return Returns the name of the file for easy transfer to the server
     */
    private String saveCrashInfoFile(Throwable ex) {
        StringBuffer sb = new StringBuffer();
        for (Map.Entry<String, String> entry : infos.entrySet()) {
            String key = entry.getKey();
            String value = entry.getValue();
            sb.append(key + "=" + value + "\n");
        }
        Writer writer = new StringWriter();
        PrintWriter printWriter = new PrintWriter(writer);
        ex.printStackTrace(printWriter);
        Throwable cause = ex.getCause();
        while (cause != null) {
            cause.printStackTrace(printWriter);
            cause = cause.getCause();
        }
        printWriter.close();
        String result = writer.toString();
        sb.append(result);
        try {
            long timestamp = System.currentTimeMillis();
            String time = formatter.format(new Date());
            String fileName = "crash-" + time + "-" + timestamp + ".txt";
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                String path = Environment.getExternalStorageDirectory().toString()+"/crash/";
                File dir = new File(path);
                if (!dir.exists()) {
                    dir.mkdirs();
                }

                FileOutputStream fos = new FileOutputStream(path + fileName);
                fos.write(sb.toString().getBytes());
                fos.close();
            }
            return fileName;
        } catch (Exception e) {
            Log.e(TAG, "an error occured while writing file...", e);
        }
        return null;
    }


   /**
     * Collect device parameter information
     * @param ctx
     */
    private void collectDeviceInfo(Context ctx) {
        try {
            PackageManager pm = ctx.getPackageManager();
            PackageInfo pi = pm.getPackageInfo(ctx.getPackageName(), PackageManager.GET_ACTIVITIES);
            if (pi != null) {
                String versionName = pi.versionName == null ? "null" : pi.versionName;
                String versionCode = pi.versionCode + "";
                infos.put("versionName", versionName);
                infos.put("versionCode", versionCode);
            }
        } catch (PackageManager.NameNotFoundException e) {
            Log.e(TAG, "an error occured when collect package info", e);
        }

        //Reflection mechanism obtains all fields including private fields
        Field[] fields = Build.class.getDeclaredFields();
        for (Field field : fields) {
            try {
                field.setAccessible(true);
                //Get the object according to the field. If it is a static field, any value can be passed in, including null
                infos.put(field.getName(), field.get(null).toString());
                Log.d(TAG, field.getName() + " : " + field.get(null));
            } catch (Exception e) {
                Log.e(TAG, "an error occured when collect crash info", e);
            }
        }
    }

Source download

Remarks

   This method refers to a project. The source of this project is uncertain and the original link cannot be given. It is hereby stated

Topics: Android Mobile