1. 程式人生 > >Android日誌列印類LogUtils,能夠定位到類名,方法名以及出現錯誤的行數並儲存日誌檔案

Android日誌列印類LogUtils,能夠定位到類名,方法名以及出現錯誤的行數並儲存日誌檔案

  關注finddreams,一起分享,一起進步!http://blog.csdn.net/finddreams/article/details/45569089      在開發中,我們常常用列印log的方式來除錯我們的應用。在Java中我們常常使用方法System.out.println()來在控制檯列印日誌,以便我們的除錯。Android中有一個專門的類Log來實現在Android系統下日誌的列印,更加方便我們定位程式出現問題的地方。      但是Android官方提供的Log類在實際專案使用中,也不是非常方便。當程式出現錯誤時,我們最希望的就是這個Log類能幫我們定位到是哪個類的哪個方法,甚至於是那一行出現了錯誤。這樣就能給我們的除錯帶來很大的便利。      同時我們也應該想到為了應用程式的安全起見,在app正式上線之前,我們應該要把列印日誌的功能關閉掉,以防別人通過Log來破解你的應用。生產模式的下列印Log,正式模式就把列印日誌的功能關閉掉,要做到Log的靈活關閉與開啟,也需要在原生的Log類上進行一些封裝。      還有一種時候,當我們的程式出現問題崩潰了,我們希望能夠收集到出現異常的原因進行分析,所以可以把Log日誌儲存到一個檔案中,放在SD卡程式建立的目錄下。也可以在使用者聯網的情況下,在程式的後臺把出異常的Log日誌檔案上傳到服務端,方便程式設計師進行分析,解決bug。      今天就給大家分享一個做專案中很實用的一個Log類LogUtils,這個類是從xUtils中提取出來,稍作修改的,有註釋。      示例:

  我們在MainActivity中呼叫一些LogUtils中的方法,注意看行數。     這裡寫圖片描述

 接著看看控制檯列印的日誌是不是像MainActivity呼叫的那樣,Log中有這個類的名字和oncreate方法名,已及當前行數;   這裡寫圖片描述

  看到上圖中的Log日誌是不是很方便定位程式中的問題了,出現異常也能快速的定位到。然後把下面的Log型別在程式的任何地方設定為false則不會列印日誌,使用起來相當的方便。  

 // 容許列印日誌的型別,預設是true,設定為false則不列印
    public static boolean allowD = true;
    public
static boolean allowE = true; public static boolean allowI = true; public static boolean allowV = true; public static boolean allowW = true; public static boolean allowWtf = true;
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

程式碼貼在下面:

package com.finddreams.log;

import java.io.BufferedWriter;
import java.io.File;
import
java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Formatter; import java.util.Locale; import android.os.Environment; import android.text.TextUtils; import android.util.Log; /** * Log工具,類似android.util.Log。 tag自動產生,格式: * customTagPrefix:className.methodName(Line:lineNumber), * customTagPrefix為空時只輸出:className.methodName(Line:lineNumber)。 * http://blog.csdn.net/finddreams */ public class LogUtils { public static String customTagPrefix = "finddreams"; // 自定義Tag的字首,可以是作者名 private static final boolean isSaveLog = false; // 是否把儲存日誌到SD卡中 public static final String ROOT = Environment.getExternalStorageDirectory() .getPath() + "/finddreams/"; // SD卡中的根目錄 private static final String PATH_LOG_INFO = ROOT + "info/"; private LogUtils() { } // 容許列印日誌的型別,預設是true,設定為false則不列印 public static boolean allowD = true; public static boolean allowE = true; public static boolean allowI = true; public static boolean allowV = true; public static boolean allowW = true; public static boolean allowWtf = true; private static String generateTag(StackTraceElement caller) { String tag = "%s.%s(Line:%d)"; // 佔位符 String callerClazzName = caller.getClassName(); // 獲取到類名 callerClazzName = callerClazzName.substring(callerClazzName .lastIndexOf(".") + 1); tag = String.format(tag, callerClazzName, caller.getMethodName(), caller.getLineNumber()); // 替換 tag = TextUtils.isEmpty(customTagPrefix) ? tag : customTagPrefix + ":" + tag; return tag; } /** * 自定義的logger */ public static CustomLogger customLogger; public interface CustomLogger { void d(String tag, String content); void d(String tag, String content, Throwable tr); void e(String tag, String content); void e(String tag, String content, Throwable tr); void i(String tag, String content); void i(String tag, String content, Throwable tr); void v(String tag, String content); void v(String tag, String content, Throwable tr); void w(String tag, String content); void w(String tag, String content, Throwable tr); void w(String tag, Throwable tr); void wtf(String tag, String content); void wtf(String tag, String content, Throwable tr); void wtf(String tag, Throwable tr); } public static void d(String content) { if (!allowD) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.d(tag, content); } else { Log.d(tag, content); } } public static void d(String content, Throwable tr) { if (!allowD) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.d(tag, content, tr); } else { Log.d(tag, content, tr); } } public static void e(String content) { if (!allowE) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.e(tag, content); } else { Log.e(tag, content); } if (isSaveLog) { point(PATH_LOG_INFO, tag, content); } } public static void e(String content, Throwable tr) { if (!allowE) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.e(tag, content, tr); } else { Log.e(tag, content, tr); } if (isSaveLog) { point(PATH_LOG_INFO, tag, tr.getMessage()); } } public static void i(String content) { if (!allowI) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.i(tag, content); } else { Log.i(tag, content); } } public static void i(String content, Throwable tr) { if (!allowI) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.i(tag, content, tr); } else { Log.i(tag, content, tr); } } public static void v(String content) { if (!allowV) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.v(tag, content); } else { Log.v(tag, content); } } public static void v(String content, Throwable tr) { if (!allowV) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.v(tag, content, tr); } else { Log.v(tag, content, tr); } } public static void w(String content) { if (!allowW) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.w(tag, content); } else { Log.w(tag, content); } } public static void w(String content, Throwable tr) { if (!allowW) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.w(tag, content, tr); } else { Log.w(tag, content, tr); } } public static void w(Throwable tr) { if (!allowW) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.w(tag, tr); } else { Log.w(tag, tr); } } public static void wtf(String content) { if (!allowWtf) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.wtf(tag, content); } else { Log.wtf(tag, content); } } public static void wtf(String content, Throwable tr) { if (!allowWtf) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.wtf(tag, content, tr); } else { Log.wtf(tag, content, tr); } } public static void wtf(Throwable tr) { if (!allowWtf) return; StackTraceElement caller = getCallerStackTraceElement(); String tag = generateTag(caller); if (customLogger != null) { customLogger.wtf(tag, tr); } else { Log.wtf(tag, tr); } } private static StackTraceElement getCallerStackTraceElement() { return Thread.currentThread().getStackTrace()[4]; } public static void point(String path, String tag, String msg) { if (isSDAva()) { Date date = new Date(); SimpleDateFormat dateFormat = new SimpleDateFormat("", Locale.SIMPLIFIED_CHINESE); dateFormat.applyPattern("yyyy"); path = path + dateFormat.format(date) + "/"; dateFormat.applyPattern("MM"); path += dateFormat.format(date) + "/"; dateFormat.applyPattern("dd"); path += dateFormat.format(date) + ".log"; dateFormat.applyPattern("[yyyy-MM-dd HH:mm:ss]"); String time = dateFormat.format(date); File file = new File(path); if (!file.exists()) createDipPath(path); BufferedWriter out = null; try { out = new BufferedWriter(new OutputStreamWriter( new FileOutputStream(file, true))); out.write(time + " " + tag + " " + msg + "\r\n"); } catch (Exception e) { e.printStackTrace(); } finally { try { if (out != null) { out.close(); } } catch (IOException e) { e.printStackTrace(); } } } } /** * 根據檔案路徑 遞迴建立檔案 * * @param file */ public static void createDipPath(String file) { String parentFile = file.substring(0, file.lastIndexOf("/")); File file1 = new File(file); File parent = new File(parentFile); if (!file1.exists()) { parent.mkdirs(); try { file1.createNewFile(); } catch (IOException e) { e.printStackTrace(); } } } /** * A little trick to reuse a formatter in the same thread */ private static class ReusableFormatter { private Formatter formatter; private StringBuilder builder; public ReusableFormatter() { builder = new StringBuilder(); formatter = new Formatter(builder); } public String format(String msg, Object... args) { formatter.format(msg, args); String s = builder.toString(); builder.setLength(0); return s; } } private static final ThreadLocal<ReusableFormatter> thread_local_formatter = new ThreadLocal<ReusableFormatter>() { protected ReusableFormatter initialValue() { return new ReusableFormatter(); } }; public static String format(String msg, Object... args) { ReusableFormatter formatter = thread_local_formatter.get(); return formatter.format(msg, args); } public static boolean isSDAva() { if (Environment.getExternalStorageState().equals( Environment.MEDIA_MOUNTED) || Environment.getExternalStorageDirectory().exists()) { return true; } else { return false; } } }