[2016-06-30]最新的log4j已經集成在DR_support_lib庫中
具體請看: https://coding.net/u/wrcold520/p/DR_support_lib/git/tree/master
[2016-06-28] 1 增加log4j的支持
[2016-06-28] 2 增加全局異常處理(可自定義程序崩潰提示消息,自定義發送錯誤報告到服務器)
[2016-06-28] 3 增加兩種應用退出方法:① appExit,結束掉所有Acitivity的生命周期,正常退出;② appKill,結束掉所有Acitivity的生命周期,殺掉程序進程后退出。
[2016-06-29] 4 增加透明狀態欄和導航欄(默認開啟,藍色背景)
1、新建Android項目
Project: AndroidLog4j
Package:cn.darkranger.log
Activity:MainActivity
2、在libs中添加log4j-1.2.17.jar包
3、添加android-logging-log4j-1.0.3.jar
我看了一下,這里面只有兩個類,我就用反編譯工具反編譯成了java文件,寫入代碼中了
LogCatAppender.java(主要作用是將log在控制台的輸出轉化為Android中的LogCat輸出)
package cn.darkranger.log.log4j; import org.apache.log4j.AppenderSkeleton; import org.apache.log4j.Layout; import org.apache.log4j.PatternLayout; import org.apache.log4j.spi.LoggingEvent; import android.util.Log; /** * 源自 android-logging-log4j-1.0.3.jar * * @author Administrator */ public class LogCatAppender extends AppenderSkeleton { protected Layout tagLayout; public LogCatAppender(Layout messageLayout, Layout tagLayout) { this.tagLayout = tagLayout; setLayout(messageLayout); } public LogCatAppender(Layout messageLayout) { //這里定義的是Tag名稱 this(messageLayout, new PatternLayout("%c")); } public LogCatAppender() { this(new PatternLayout("%c")); } protected void append(LoggingEvent le) { switch (le.getLevel().toInt()) { case 5000: if (le.getThrowableInformation() != null) { Log.v(getTagLayout().format(le), getLayout().format(le), le.getThrowableInformation().getThrowable()); } else { Log.v(getTagLayout().format(le), getLayout().format(le)); } break; case 10000: if (le.getThrowableInformation() != null) { Log.d(getTagLayout().format(le), getLayout().format(le), le.getThrowableInformation().getThrowable()); } else { Log.d(getTagLayout().format(le), getLayout().format(le)); } break; case 20000: if (le.getThrowableInformation() != null) { Log.i(getTagLayout().format(le), getLayout().format(le), le.getThrowableInformation().getThrowable()); } else { Log.i(getTagLayout().format(le), getLayout().format(le)); } break; case 30000: if (le.getThrowableInformation() != null) { Log.w(getTagLayout().format(le), getLayout().format(le), le.getThrowableInformation().getThrowable()); } else { Log.w(getTagLayout().format(le), getLayout().format(le)); } break; case 40000: if (le.getThrowableInformation() != null) { Log.e(getTagLayout().format(le), getLayout().format(le), le.getThrowableInformation().getThrowable()); } else { Log.e(getTagLayout().format(le), getLayout().format(le)); } break; case 50000: if (le.getThrowableInformation() != null) { Log.wtf(getTagLayout().format(le), getLayout().format(le), le.getThrowableInformation().getThrowable()); } else Log.wtf(getTagLayout().format(le), getLayout().format(le)); break; } } public void close() { } public boolean requiresLayout() { return true; } public Layout getTagLayout() { return this.tagLayout; } public void setTagLayout(Layout tagLayout) { this.tagLayout = tagLayout; } }
LogConfig.java(主要作用是配置一些基本的信息)
package cn.darkranger.log.log4j; import java.io.IOException; import org.apache.log4j.Layout; import org.apache.log4j.Level; import org.apache.log4j.LogManager; import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.RollingFileAppender; import org.apache.log4j.helpers.LogLog; /** * 源自 android-logging-log4j-1.0.3.jar * * @author Administrator */ public class LogConfig { private Level rootLevel = Level.DEBUG; /** * ### log文件的格式 * * ### 輸出格式解釋: * ### [%-d{yyyy-MM-dd HH:mm:ss}][Class: %c.%M(%F:%L)] %n[Level: %-5p] - Msg: %m%n * * ### %d{yyyy-MM-dd HH:mm:ss}: 時間,大括號內是時間格式 * ### %c: 全類名 * ### %M: 調用的方法名稱 * ### %F:%L 類名:行號(在控制台可以追蹤代碼) * ### %n: 換行 * ### %p: 日志級別,這里%-5p是指定的5個字符的日志名稱,為的是格式整齊 * ### %m: 日志信息 * ### 輸出的信息大概如下: * ### [時間{時間格式}][信息所在的class.method(className:lineNumber)] 換行 * ### [Level: 5個字符的等級名稱] - Msg: 輸出信息 換行 */ private String filePattern = "[%-d{yyyy-MM-dd HH:mm:ss}][Class: %c.%M(%F:%L)] %n[Level: %-5p] - Msg: %m%n"; /** * ### LogCat控制台輸出格式 * * ### [Class: 信息所在的class.method(className:lineNumber)] 換行 * ### [Level: 5個字符的等級名稱] - Msg: 輸出信息 換行 */ private String logCatPattern = "[Class: %c.%M(%F:%L)] %n[Level: %-5p] - Msg: %m%n"; private String fileName = "android-log4j.log"; private int maxBackupSize = 5; private long maxFileSize = 1024 * 1024 * 5L; private boolean immediateFlush = true; private boolean useLogCatAppender = true; private boolean useFileAppender = true; private boolean resetConfiguration = true; private boolean internalDebugging = false; public LogConfig() { } public LogConfig(String fileName) { setFileName(fileName); } public LogConfig(String fileName, Level rootLevel) { this(fileName); setRootLevel(rootLevel); } public LogConfig(String fileName, Level rootLevel, String filePattern) { this(fileName); setRootLevel(rootLevel); setFilePattern(filePattern); } public LogConfig(String fileName, int maxBackupSize, long maxFileSize, String filePattern, Level rootLevel) { this(fileName, rootLevel, filePattern); setMaxBackupSize(maxBackupSize); setMaxFileSize(maxFileSize); } public void configure() { Logger root = Logger.getRootLogger(); if (isResetConfiguration()) { LogManager.getLoggerRepository().resetConfiguration(); } LogLog.setInternalDebugging(isInternalDebugging()); if (isUseFileAppender()) { configureFileAppender(); } if (isUseLogCatAppender()) { configureLogCatAppender(); } root.setLevel(getRootLevel()); } public void setLevel(String loggerName, Level level) { Logger.getLogger(loggerName).setLevel(level); } private void configureFileAppender() { Logger root = Logger.getRootLogger(); Layout fileLayout = new PatternLayout(getFilePattern()); RollingFileAppender rollingFileAppender; try { rollingFileAppender = new RollingFileAppender(fileLayout, getFileName()); } catch (IOException e) { throw new RuntimeException("Exception configuring log system", e); } rollingFileAppender.setMaxBackupIndex(getMaxBackupSize()); rollingFileAppender.setMaximumFileSize(getMaxFileSize()); rollingFileAppender.setImmediateFlush(isImmediateFlush()); root.addAppender(rollingFileAppender); } private void configureLogCatAppender() { Logger root = Logger.getRootLogger(); Layout logCatLayout = new PatternLayout(getLogCatPattern()); LogCatAppender logCatAppender = new LogCatAppender(logCatLayout); root.addAppender(logCatAppender); } public Level getRootLevel() { return this.rootLevel; } public void setRootLevel(Level level) { this.rootLevel = level; } public String getFilePattern() { return this.filePattern; } public void setFilePattern(String filePattern) { this.filePattern = filePattern; } public String getLogCatPattern() { return this.logCatPattern; } public void setLogCatPattern(String logCatPattern) { this.logCatPattern = logCatPattern; } public String getFileName() { return this.fileName; } public void setFileName(String fileName) { this.fileName = fileName; } public int getMaxBackupSize() { return this.maxBackupSize; } public void setMaxBackupSize(int maxBackupSize) { this.maxBackupSize = maxBackupSize; } public long getMaxFileSize() { return this.maxFileSize; } public void setMaxFileSize(long maxFileSize) { this.maxFileSize = maxFileSize; } public boolean isImmediateFlush() { return this.immediateFlush; } public void setImmediateFlush(boolean immediateFlush) { this.immediateFlush = immediateFlush; } public boolean isUseFileAppender() { return this.useFileAppender; } public void setUseFileAppender(boolean useFileAppender) { this.useFileAppender = useFileAppender; } public boolean isUseLogCatAppender() { return this.useLogCatAppender; } public void setUseLogCatAppender(boolean useLogCatAppender) { this.useLogCatAppender = useLogCatAppender; } public void setResetConfiguration(boolean resetConfiguration) { this.resetConfiguration = resetConfiguration; } public boolean isResetConfiguration() { return this.resetConfiguration; } public void setInternalDebugging(boolean internalDebugging) { this.internalDebugging = internalDebugging; } public boolean isInternalDebugging() { return this.internalDebugging; } }
4、編寫LogUtil.java工具類(主要作用是重新配置Log4j的一些參數,設置成為合適自己項目的log,在這里我們通過調用LogUtil.configLog()就可以了,簡潔)
LogUtil.java
package cn.darkranger.log.log4j; import java.io.File; import java.util.Locale; import org.apache.log4j.Level; import android.os.Environment; /** * LogUtil 工具類 * * @author Administrator * */ @SuppressWarnings("all") public class LogUtil { /** 這里的AppName決定log的文件位置和名稱 **/ private static final String APP_NAME = "MyApp"; /** 設置log文件全路徑,這里是 MyApp/Log/myapp.log **/ private static final String LOG_FILE_PATH = Environment.getExternalStorageDirectory() + File.separator + APP_NAME + File.separator + "Log" + File.separator + APP_NAME.toLowerCase(Locale.CHINA) + ".log"; /** * ### log文件的格式 * * ### 輸出格式解釋: * ### [%-d{yyyy-MM-dd HH:mm:ss}][Class: %c.%M(%F:%L)] %n[Level: %-5p] - Msg: %m%n * * ### %d{yyyy-MM-dd HH:mm:ss}: 時間,大括號內是時間格式 * ### %c: 全類名 * ### %M: 調用的方法名稱 * ### %F:%L 類名:行號(在控制台可以追蹤代碼) * ### %n: 換行 * ### %p: 日志級別,這里%-5p是指定的5個字符的日志名稱,為的是格式整齊 * ### %m: 日志信息 * ### 輸出的信息大概如下: * ### [時間{時間格式}][信息所在的class.method(className:lineNumber)] 換行 * ### [Level: 5個字符的等級名稱] - Msg: 輸出信息 換行 */ private static final String LOG_FILE_PATTERN = "[%-d{yyyy-MM-dd HH:mm:ss}][Class: %c.%M(%F:%L)] %n[Level: %-5p] - Msg: %m%n"; /** 生產環境下的log等級 **/ private static final Level LOG_LEVEL_PRODUCE = Level.ALL; /** 發布以后的log等級 **/ private static final Level LOG_LEVEL_RELEASE = Level.INFO; /** * 配置log4j參數 */ public static void configLog(){ LogConfig logConfig = new LogConfig(); /** 設置Log等級,生產環境下調用setLogToProduce(),發布后調用setLogToRelease() **/ setLogToProduce(logConfig); logConfig.setFileName(LOG_FILE_PATH); logConfig.setLevel("org.apache", Level.ERROR); logConfig.setFilePattern(LOG_FILE_PATTERN); logConfig.setMaxFileSize(1024 * 1024 * 5); logConfig.setImmediateFlush(true); logConfig.configure(); } /** * 將log設置為生產環境 * * @param logConfig */ private static void setLogToProduce(LogConfig logConfig) { logConfig.setRootLevel(LOG_LEVEL_PRODUCE); } /** * 將log設置為發布以后的環境 * * @param logConfig */ private static void setLogToRelease(LogConfig logConfig) { logConfig.setRootLevel(LOG_LEVEL_RELEASE); } }
5、編寫MyApplication.java(繼承Application,然后在onCreate()中調用LogUtil.configLog()方法來配置Log4j,這樣程序一開始就相當於初始化了Log4j的配置)
package cn.darkranger.log.application; import org.apache.log4j.Logger; import android.app.Application; import cn.darkranger.log.log4j.LogUtil; public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); //配置log4j基本參數 LogUtil.configLog(); //獲取Application Log Logger log = Logger.getLogger(MyApplication.class); //輸出MyApplication的信息 log.info("Log4j Is Ready and My Application Was Created Successfully! "); } }
6、修改AndroidManifest.xml(主要有兩個地方,一是添加讀取存儲的權限,二是指定Application為我們剛剛寫的MyApplication)
有下划線的地方就是我們添加的xml代碼
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.darkranger.log" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="22" /> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <application android:name="cn.darkranger.log.application.MyApplication" android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="cn.darkranger.log.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
7、使用Log4j
(1)創建Logger實例
private static Logger log = Logger.getLogger(YourClassName.class);
(2)在代碼中用log記錄信息
log.info("onCreate()");
log.fatal("this is fatal!");
log.error("this is error!");
log.warn("this is warn!");
log.info("this is info!");
log.debug("this is debug!");
log.trace("this is trace!");
(3)MainActivity.java中的示例(紅色的部分就是log的記錄)
package cn.darkranger.log; import org.apache.log4j.Logger; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; public class MainActivity extends AppCompatActivity { private static Logger log = Logger.getLogger(MainActivity.class); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); log.info("onCreate()"); log.fatal("this is fatal!"); log.error("this is error!"); log.warn("this is warn!"); log.info("this is info!"); log.debug("this is debug!"); log.trace("this is trace!"); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.main, menu); log.info("onCreateOptionsMenu()"); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } }
8、結果展示:
控制台輸出(自定義logcat輸出格式:"[Class: %c.%M(%F:%L)] %n[Level: %-5p] - Msg: %m%n"):
平板中的Log位置:計算機\Galaxy Tab A\Tablet\MyApp\Log\myapp.log(相對於計算機)
設備存儲\MyApp\Log\myapp.log(相對於平板)
[2016-06-16 17:14:54][Class: cn.darkranger.log.application.MyApplication.onCreate(MyApplication.java:21)] [Level: INFO ] - Msg: Log4j Is Ready and My Application Was Created Successfully! [2016-06-16 17:14:54][Class: cn.darkranger.log.MainActivity.onCreate(MainActivity.java:17)] [Level: INFO ] - Msg: onCreate() [2016-06-16 17:14:54][Class: cn.darkranger.log.MainActivity.onCreate(MainActivity.java:18)] [Level: FATAL] - Msg: this is fatal! [2016-06-16 17:14:54][Class: cn.darkranger.log.MainActivity.onCreate(MainActivity.java:19)] [Level: ERROR] - Msg: this is error! [2016-06-16 17:14:54][Class: cn.darkranger.log.MainActivity.onCreate(MainActivity.java:20)] [Level: WARN ] - Msg: this is warn! [2016-06-16 17:14:54][Class: cn.darkranger.log.MainActivity.onCreate(MainActivity.java:21)] [Level: INFO ] - Msg: this is info! [2016-06-16 17:14:54][Class: cn.darkranger.log.MainActivity.onCreate(MainActivity.java:22)] [Level: DEBUG] - Msg: this is debug! [2016-06-16 17:14:54][Class: cn.darkranger.log.MainActivity.onCreate(MainActivity.java:23)] [Level: TRACE] - Msg: this is trace! [2016-06-16 17:14:54][Class: cn.darkranger.log.MainActivity.onCreateOptionsMenu(MainActivity.java:30)] [Level: INFO ] - Msg: onCreateOptionsMenu()
項目示例地址: