一 為什么要接入日志打印系統(tǒng)?
相信大家在開發(fā)應用的時候,總會遇到bug,這個時候,如果bug是在我們本地開發(fā)的過程中發(fā)現(xiàn)的,那么我們把手機插入android studio進行聯(lián)調(diào),就可以馬上定位到出錯的堆棧,報錯的信息。但是,在我們的應用發(fā)布出去,給用戶使用的時候,如果出現(xiàn)了bug,那么,我們就很難定位出問題的所在。一般來說,我們需要使用錯誤上報系統(tǒng),把錯誤上報給我們,比如騰訊的bugly,阿里的友盟等第三方的錯誤收集插件。但是很多時候,bugly上報的錯誤并不能正確的把我們需要的錯誤信息反饋給我們,或者說,我們無法定位在出現(xiàn)了bug的時候,用戶之前的操作是什么。在Xlog還沒有上線的時候,我們發(fā)現(xiàn)一個bug需要怎么做呢?首先,我們需要聯(lián)系到這個用戶,爭取獲得用戶的配合。然后我們就發(fā)一個私包給用戶,用戶安裝后,重現(xiàn)剛才的bug,然后我們把操作日志寫入本地的錯誤日志中,讓用戶通過交流軟件發(fā)給我們。臥槽,這個步奏,想掀凳子有木有??
二 為什么使用Xlog?
在上面我們的最后一個問題暴露出來后,為什么我們不自己寫一個日志系統(tǒng)呢?只是把文本寫入本地txt文件中,多么容易的事,一個inputStream OutputStream我們不是很玩的很溜么?何必使用別人的東西??好吧,在回答這個問題的時候,我建議大家先看下這篇文章
https://mp.weixin.qq.com/s/cnhuEodJGIbdodh0IxNeXQ
如果大家嫌這篇文章太長,那么我可以給大家一個簡單的總結(jié),就是:XLog使用流式方式對單行日志進行壓縮,壓縮加密后寫入作為log中間buffer的mmap中。使用xlog方案,除非io損壞或者磁盤沒有可用空間,基本可以保證不會丟失任何一行日志。
一個優(yōu)秀的日志打印系統(tǒng),需要保證:
1. 不能把用戶的隱私信息打印到日志文件里,不能把日志明文打到日志文件里。
2. 不能影響程序的性能。最基本的保證是使用了日志不會導致程序卡頓。
3. 不能因為程序被系統(tǒng)殺掉,或者發(fā)生了 crash,crash 捕捉模塊沒有捕捉到導致部分時間點沒有日志, 要保證程序整個生命周期內(nèi)都有日志。
4. 不能因為部分數(shù)據(jù)損壞就影響了整個日志文件,應該最小化數(shù)據(jù)損壞對日志文件的影響。
所以,既然有XLog這種好東西,我們在沒有把握自己開發(fā)一個更加優(yōu)秀的xlog打印框架,我們就不要重復造輪子了,哈哈。
三 Xlog接入
step 1: 引入XLog依賴,在我們主工程的build.gradle中加入
dependencies {
compile 'com.tencent.mars:mars-xlog:1.0.6'
}
step 2:開始初始化Xlog環(huán)境
private void initXlogEnv(){
System.loadLibrary("stlport_shared");
System.loadLibrary("marsxlog");
final String SDCARD = Environment.getExternalStorageDirectory().getAbsolutePath();
final String logPath = SDCARD + "/xlogdemo/log";
final String cachePath = this.getFilesDir() + "/xlogdemo/xlog";
if (BuildConfig.DEBUG) {
Xlog.appenderOpen(Xlog.LEVEL_DEBUG, Xlog.AppednerModeAsync, cachePath, logPath, "", "");
Xlog.setConsoleLogOpen(true);
} else {
Xlog.appenderOpen(Xlog.LEVEL_INFO, Xlog.AppednerModeAsync, cachePath, logPath, "MarsSample", "");
Xlog.setConsoleLogOpen(false);
}
}
四:開始踩坑之旅
ok到了這里,按照Xlog官方給的接入步奏,我們這個時候應該就可以在我們的sdcard根目錄上看到logFile.log文件了。ok,我們開開心心的來run一下看看

臥槽,官方文檔又來搞事情了
踩坑1:couldn't find "libstlport_shared.so
為什么會出現(xiàn)這個bug?在接入Xlog到我們的項目中時,我建了一個demo,跑出來是不會報錯的,但是一旦接入到我們工程中,就拋了這個錯。在仔細看了官方文檔后,知道了,原來xlog因為考慮依賴包的大小,只提供了armeabi和x86_64兩種cpu架構(gòu)。

而我們的工程中,又是只支持armeabi-v7a架構(gòu)。所以這個時候需要怎么辦呢?
解決方法:這個時候,我們只需要先使用armeabi編譯打包,然后把生成的libstlport_shared.so和libmasxlog.so拷貝到我們的工程中,放在對應log的module中即可,像這樣

踩坑2:沒有對應的sdcard沒有生成目錄文件
如果遇到問題,需要檢查一下是否在manifest中有申請sdcard寫入權(quán)限。還有在android6.0以上系統(tǒng),有沒有動態(tài)去申請存儲權(quán)限。
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
踩坑3:同一個進程中,xlog不可以使用日志打印文件。
踩這個坑的原因是因為我們在日志上報系統(tǒng)中,會需要重點記錄部分用戶行為,而這部分日志上報行為是需要上報給服務端的。所以為了盡量減少日志包的大小,同時讓為了使重要的日志和其它日志相隔開,我們想把這部分抽離出來一個文件,方便服務端分析和管理。但經(jīng)過嘗試后,這個行為xlog是不允許的,首先xlog會拋錯,錯誤信息是當前的日志文件已經(jīng)被打開。
分析:其實這種一個進程只能寫入一個文件是可以理解的,因為如果一個進程多文件的話,xlog需要頻繁的去控制文件流的輸出和關閉,這樣會導致性能問題,也可能會造成日志丟失。
踩坑4:多進程xlog日志打印
xlog是支持多進程打印的,但是多進程打印需要制定每一個進程對應一個文件。在這里,我建議使用進程的名字作為一個文件夾,然后再放入對應的日志文件。這樣便于我們以后日志的管理。當我們開啟更多進程的時候,也會自動生成,不用去一一匹配。