将所有异常写入文件 [英] Write all exception in file

查看:80
本文介绍了将所有异常写入文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用Timber将一些日志写入设备上的文件.现在,我正在使用HTTP拦截器编写我选择的日志和来自服务器的一些响应.但是我想在文件中写入所有异常(例如致命). Timber或其他库可能吗?

I'm using Timber to write some logs to file which located on device. For now, I'm writing my selected logs and some response from server using HTTP interceptor. But I want to write in file all exception (fatal, for example). Is it possible with Timber or other library?

现在我正在使用Fabric,但我的应用程序并不总是与外部世界建立互联网连接

For now I'm using Fabric, but my app not always have internet connection with outer world

P.S.我想写所有致命的异常而无需try/catch

P.S. I want to write ALL fatal exception without try/catch

public class FileLoggingTree
{
    /**
     * Sends an error message to LogCat and to a log file.
     * @param context The context of the application.
     * @param logMessageTag A tag identifying a group of log messages. Should be a constant in the
     *                      class calling the logger.
     * @param logMessage The message to add to the log.
     */
    public static void e(Context context, String logMessageTag, String logMessage)
    {
        if (!Log.isLoggable(logMessageTag, Log.ERROR))
            return;

        int logResult = Log.e(logMessageTag, logMessage);
        if (logResult > 0)
            logToFile(context, logMessageTag, logMessage);
    }

    /**
     * Sends an error message and the exception to LogCat and to a log file.
     * @param context The context of the application.
     * @param logMessageTag A tag identifying a group of log messages. Should be a constant in the
     *                      class calling the logger.
     * @param logMessage The message to add to the log.
     * @param throwableException An exception to log
     */
    public static void e
    (Context context, String logMessageTag, String logMessage, Throwable throwableException)
    {
        if (!Log.isLoggable(logMessageTag, Log.ERROR))
            return;

        int logResult = Log.e(logMessageTag, logMessage, throwableException);
        if (logResult > 0)
            logToFile(context, logMessageTag,
                    logMessage + "\r\n" + Log.getStackTraceString(throwableException));
    }

// The i and w method for info and warning logs
// should be implemented in the same way as the e method for error logs.

    /**
     * Sends a message to LogCat and to a log file.
     * @param context The context of the application.
     * @param logMessageTag A tag identifying a group of log messages. Should be a constant in the
     *                      class calling the logger.
     * @param logMessage The message to add to the log.
     */
    public static void v(Context context, String logMessageTag, String logMessage)
    {
        // If the build is not debug, do not try to log, the logcat be
        // stripped at compilation.
        if (!BuildConfig.DEBUG || !Log.isLoggable(logMessageTag, Log.VERBOSE))
            return;

        int logResult = Log.v(logMessageTag, logMessage);
        if (logResult > 0)
            logToFile(context, logMessageTag, logMessage);
    }

    /**
     * Sends a message and the exception to LogCat and to a log file.
     * @param logMessageTag A tag identifying a group of log messages. Should be a constant in the
     *                      class calling the logger.
     * @param logMessage The message to add to the log.
     * @param throwableException An exception to log
     */
    public static void v
    (Context context,String logMessageTag, String logMessage, Throwable throwableException)
    {
        // If the build is not debug, do not try to log, the logcat be
        // stripped at compilation.
        if (!BuildConfig.DEBUG || !Log.isLoggable(logMessageTag, Log.VERBOSE))
            return;

        int logResult = Log.v(logMessageTag, logMessage, throwableException);
        if (logResult > 0)
            logToFile(context, logMessageTag,
                    logMessage + "\r\n" + Log.getStackTraceString(throwableException));
    }

// The d method for debug logs should be implemented in the same way as the v method for verbose logs.

    /**
     * Gets a stamp containing the current date and time to write to the log.
     * @return The stamp for the current date and time.
     */
    private static String getDateTimeStamp()
    {
        Date dateNow = Calendar.getInstance().getTime();
        // My locale, so all the log files have the same date and time format
        return (DateFormat.getDateTimeInstance
                (DateFormat.SHORT, DateFormat.SHORT, Locale.CANADA_FRENCH).format(dateNow));
    }

    /**
     * Writes a message to the log file on the device.
     * @param logMessageTag A tag identifying a group of log messages.
     * @param logMessage The message to add to the log.
     */
    private static void logToFile(Context context, String logMessageTag, String logMessage)
    {
        try
        {
            // Gets the log file from the root of the primary storage. If it does
            // not exist, the file is created.
            File logFile = new File(Environment.getRootDirectory(),
                    "TestApplicationLog.txt");
            if (!logFile.exists())
                logFile.createNewFile();
            // Write the message to the log with a timestamp
            BufferedWriter writer = new BufferedWriter(new FileWriter(logFile, true));
            writer.write(String.format("%1s [%2s]:%3s\r\n",
                    getDateTimeStamp(), logMessageTag, logMessage));
            writer.close();
            // Refresh the data so it can seen when the device is plugged in a
            // computer. You may have to unplug and replug to see the latest
            // changes
            MediaScannerConnection.scanFile(context,
                    new String[] { logFile.toString() },
                    null,
                    null);
        }
        catch (IOException e)
        {
            Log.e("com.cindypotvin.Logger", "Unable to log exception to file.");
        }
    }
}

TimberLogger.class

public class TimberLooger extends Timber.DebugTree {
    private static final String TAG = FileLoggingTree.class.getSimpleName();

    private Context context;

    public TimberLooger(Context context) {
        this.context = context;
    }

    @Override
    protected void log(int priority, String tag, String message, Throwable t) {

        try {

            File direct = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/FileLocation");

            if (!direct.exists()) {
                direct.mkdir();
            }

            String fileNameTimeStamp = new SimpleDateFormat("dd-MM-yyyy", Locale.getDefault()).format(new Date());
            String logTimeStamp = new SimpleDateFormat("E MMM dd yyyy 'at' hh:mm:ss:SSS aaa", Locale.getDefault()).format(new Date());

            String fileName = fileNameTimeStamp + ".html";

            File file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) + "/FileLocation" + File.separator + fileName);

            file.createNewFile();

            if (file.exists()) {

                OutputStream fileOutputStream = new FileOutputStream(file, true);

                fileOutputStream.write(("<p style=\"background:lightgray;\"><strong style=\"background:lightblue;\">&nbsp&nbsp" + logTimeStamp + " :&nbsp&nbsp</strong>&nbsp&nbsp" + message + "</p>").getBytes());
                fileOutputStream.close();

            }

            //if (context != null)
            //MediaScannerConnection.scanFile(context, new String[]{file.getAbsolutePath()}, null, null);

        } catch (Exception e) {
            Log.e(TAG, "Error while logging into file : " + e);
        }
    }
}

推荐答案

是的,可以使用Timber将异常写入文件中.为此,您必须创建一个自定义的木材树,如下面的示例(在Kotlin中):

Yes, it's possible to use Timber to write your exceptions to a file. To achieve that you have to create a custom Timber Tree, like the example below (In Kotlin):

import timber.log.Timber

class FileLogTree : Timber.Tree() {

    override fun log(priority: Int, tag: String?, message: String, t: Throwable?) {

        if (priority == Log.ERROR) {
            try {
                val directory = Environment.getExternalStoragePublicDirectory("${Environment.DIRECTORY_DOCUMENTS}/logs")

                if (!directory.exists())
                    directory.mkdirs()

                val fileName = "myLog.txt"

                val file = File("${directory.absolutePath}${File.separator}$fileName")

                file.createNewFile()

                if (file.exists()) {
                    val fos = FileOutputStream(file, true)

                    fos.write("$message\n".toByteArray(Charsets.UTF_8))
                    fos.close()
                }

            } catch (e: IOException){
                Log.println(Log.ERROR,"FileLogTree", "Error while logging into file: $e")
            }
        }
    }
}

稍后,在您的Timber初始化过程中,设置以下自定义树:

Later, on your Timber initialization process, set this custom tree:

Timber.plant(FileLogTree())

在此示例中,Timber会将所有"Timber.e()"日志写入文档/日志文件夹中名为"myLog.txt"的文件中.

In this example, Timber will write all "Timber.e()" logs to a file named "myLog.txt" inside your documents/logs folder.

您还需要WRITE_EXTERNAL_STORAGE权限才能使该自定义树生效.您可以在此答案上了解有关获取此权限的更多信息.

You'll also need the WRITE_EXTERNAL_STORAGE permission for that custom Tree to work. You can read more about getting this permission on this answer.

对于获取所有异常"部分,您必须创建一个自定义的未捕获异常处理程序",并在应用程序(或活动)启动后更改默认的Thread.UncaughtExceptionHandler.为此,请致电:Thread.setDefaultUncaughtExceptionHandler(new YourExceptionHandler(context));.在该处理程序内,您可以选择处理异常(例如调用Timber.e()).

As for the "get all exceptions" part, you'll have to create a custom Uncaught Exception Handler and change the default Thread.UncaughtExceptionHandler once your application (or activities) starts. To do so, call: Thread.setDefaultUncaughtExceptionHandler(new YourExceptionHandler(context));. Inside that handler you can chose what to do with the exception (Like calling Timber.e()).

选中此答案,以了解有关如何实现该信息的更多信息.或者,您可以查看此链接,这个家伙让那些处理程序之一来获取那些崩溃.您可以将其与自定义树一起使用,以将详细信息保存在日志文件中.

Check this answer to learn more on how to implement that. Alternatively, you can take a look at this link, this guy made one of those handlers to get those crashes. You can use that with your custom Tree to save the details on your log file.

这篇关于将所有异常写入文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆