Android應(yīng)用的異常捕獲

做為程序員,最不愿意看到的就是自己寫的程序崩潰,特別是遇到?jīng)]有錯(cuò)誤信息的崩潰的時(shí)候滑潘,往往程序員自己也就隨之一起崩潰了粟耻。如何捕獲Android程序產(chǎn)生異常時(shí)的崩潰信息查近,本文提供了隨手可行的方法,希望能夠帶來一些啟發(fā)挤忙,同時(shí)解決一些生產(chǎn)上的難題嗦嗡。

背景

在應(yīng)用從開發(fā)慢慢過渡到線上部署的時(shí)候,開發(fā)者就逐漸切換到依靠程序日志/運(yùn)行狀態(tài)來進(jìn)行問題的排查和解決饭玲。通常一些第三方廠商會(huì)提供這些服務(wù)侥祭,譬如騰訊的bugly,fabric(以前叫crashlytics)茄厘,Umeng等矮冬。 前兩者的異常收集和處理較好,然而有一個(gè)通用的問題就是需要將symbol文件上傳到廠商服務(wù)器次哈,顯然對于注重應(yīng)用安全和IP保護(hù)的開發(fā)者胎署,這個(gè)行為是值得著重權(quán)衡的。而Umeng則注重于運(yùn)營數(shù)據(jù)窑滞,對于異常捕獲沒有特別大的優(yōu)勢琼牧。所以本文的關(guān)注點(diǎn)就是如何在Android項(xiàng)目內(nèi)部實(shí)現(xiàn)自己異常捕獲和分析模塊恢筝。

主要會(huì)包括以下知識點(diǎn)(劃重點(diǎn))

1. 如何捕獲Java異常

2. 如何捕獲Native異常及分析

3. 如何提示用戶發(fā)送錯(cuò)誤信息

1. 如何捕獲Java 異常

這個(gè)問題乍一聽感覺沒有任何難度,這不是用以下的終極處理Crash大法就解決了嗎?

且不說這樣做的對錯(cuò)巨坊,只是并不能很好的解決我們的問題撬槽,問題就在于我們對于會(huì)發(fā)生異常的地方?jīng)]有辦法完全預(yù)知,對于CheckedException 編譯器會(huì)提示我們處理趾撵,然而對于RuntimeException侄柔,總是難以預(yù)防。NPE(Null Pointer Exception)常年占據(jù)Java Eeception的Top 1 不是沒有道理占调。

所以我們的期望是什么暂题,就算我們沒有指定Catch Exception,在程序發(fā)生異常的時(shí)候究珊,也能通知到我們薪者。幸運(yùn)的是,正好就有這樣的方法剿涮。


看一下這個(gè)方法的說明啸胧,一下就明白了

至此,一切都清楚了幔虏,我們要做的就是設(shè)置一個(gè)自定義的UncaughtExceptionHandler纺念,并且設(shè)置為Thread的Default值,這樣在異常發(fā)生時(shí)想括,就可以進(jìn)入到我們的處理流程當(dāng)中陷谱,簡要代碼如下:


2. 如何捕獲Native異常

與Java層的異常不同,Native層的異常捕獲要稍微復(fù)雜一些瑟蜈。難點(diǎn)主要在于當(dāng)Native 層發(fā)生異常時(shí)烟逊,JVM在收到異常信號后會(huì)直接Shutdown,所以我們的Thread.UncaughtExceptionHandler 不會(huì)被執(zhí)行铺根。所以我們必須捕獲Linux的異常信號宪躯,并執(zhí)行我們自己的信號處理函數(shù)。例如如下展示:


在此基礎(chǔ)上位迂,我們還必須自己來實(shí)現(xiàn)Crash Dump生成和解析访雪,著實(shí)不太友好。所以在這里我們引用了一個(gè)三方庫掂林,來幫我們處理臣缀。

Google-Breakpad項(xiàng)目地址


下面我們就來看一下如何集成Breakpad來完成我們需要的異常捕獲。

從上面的Breakpad的結(jié)構(gòu)圖可以看出泻帮,我們需要的是兩塊東西精置,一是Client模塊,這將被集成到App中锣杂,用作Crash的信號捕捉和dump文件生成脂倦;另外一個(gè)就是Process模塊番宁,當(dāng)收集到用戶dump文件時(shí),結(jié)合symbol進(jìn)行crash棧分析赖阻。

2.1 Client模塊集成

通過depot_tools 下載好整個(gè)Breakpad源碼之后蝶押,我們就可以進(jìn)行client module的編譯。通常來說有兩種編譯的方式政供,一是集成到項(xiàng)目中播聪,利用NDK-Build 來進(jìn)行整個(gè)源碼的編譯和集成朽基;第二個(gè)就是使用NDK toolchain來進(jìn)行單獨(dú)編譯布隔,然后將編譯出來的靜態(tài)鏈接庫導(dǎo)入到項(xiàng)目中。兩者沒有很大的區(qū)別稼虎,主要區(qū)別在于前者Breakpad的src代碼會(huì)被集成到項(xiàng)目里衅檀,而后者則是單獨(dú)管理。之前的項(xiàng)目采用的是第二種方法霎俩,導(dǎo)入靜態(tài)鏈接庫哀军。這樣的好處就是項(xiàng)目中jni文件夾里沒有過多跟項(xiàng)目業(yè)務(wù)無關(guān)的代碼,然而有一個(gè)問題沒法避免打却,需要用到的頭文件也需要加到項(xiàng)目中去杉适,這樣也需要一個(gè)手動(dòng)的維護(hù)。再加上Android Studio 2.2 以后對NDK的支持柳击,所以本文就采用集成源碼到項(xiàng)目中來進(jìn)行一個(gè)展示猿推。

?首先是創(chuàng)建jni文件夾:右鍵項(xiàng)目 -> new -> folder -> jni folder

?接著是拷貝breakpad/src 到j(luò)ni folder下,并刪除一些Client不需要的folder捌肴,包括build蹬叭,processor,testing状知,tools等秽五,清理過后的目錄結(jié)構(gòu)應(yīng)該跟以下類似:


?接著是配置Gradle:


這里的Android.mk 如果項(xiàng)目之前沒有的話,那么可以直接拷貝Breakpad 下src\android\sample_app\jni下面的3個(gè)文件到項(xiàng)目中的jni目錄下饥悴,然后根據(jù)之前拷貝的Breakpad目錄結(jié)構(gòu)做如下改動(dòng):





可以看到坦喘,在test_breakpad.cpp中,我們定義了一個(gè)jni 方法setHandler()西设,主要干了幾件事起宽,設(shè)置Dmp文件的生成位置,注冊自己的DumpCallback济榨,并且緊跟著模擬了一個(gè)Crash坯沪。

?最后我們選擇MainActivity 或者Application 中去加載我們的Library并調(diào)用jni方法。


別忘記加上寫SDCard的權(quán)限!

至此擒滑,我們的測試App 就已經(jīng)完成腐晾,運(yùn)行起來之后就可以在Logcat里面看到類似如下的輸出:

Dump path: %s]

/storage/emulated/0/Android/data/com.example.capturecrash/

files/c1d1d3cb-7030-46a2-009b4598-26d2de2d.dmp

這里的dmp文件就包含了我們之后分析Crash的信息了叉弦。

2.2 Dmp文件分析

從Dmp文件中提取有效信息,我們就需要重新回到Breakpad目錄藻糖,進(jìn)行Processor的編譯淹冰。

請確保Linux或者M(jìn)ac 的依賴包都已安裝。成功編譯之后巨柒,我們需要用到兩個(gè)文件樱拴,一是minidump_stackwalk(src/processor/minidump_stackwalk),另一個(gè)是dump_sys(src/tools/linux/dump_sysm/dump_syms)洋满。我們將這兩個(gè)文件拷貝到工作目錄備用晶乔。

同時(shí),我們將$AndroidProject/build/intermediates/ndkBuild/debug/obj/local/armeabi/libtest_google_breakpad.so 和上一步生成的dmp 文件也拷貝到工作目錄牺勾。

接下來我們就開始進(jìn)行dmp文件的分析正罢。

?生成Symbol文件

我們首先采用dump_syms生成了libtest_google_breakpad.so的symbol,然后讀取了symbol文件的第一行驻民,需要的信息是這一串十六進(jìn)制的version code翻具。接下來我們將Symbol文件按照固定路徑進(jìn)行放置:

至此,Symbol文件就準(zhǔn)備完畢回还。

?分析Symbol

然后我們打開result.txt裆泳,就可以發(fā)現(xiàn)有如下類似結(jié)果:

這樣,一個(gè)清晰的Crash Stack Trace就出現(xiàn)了柠硕。

3.如何提示用戶發(fā)送錯(cuò)誤信息

我們在前面已經(jīng)成功的捕獲了Java異常和Native異常工禾,那么接下來要做的就是順理成章的處理,只要提示用戶將我們需要的Java棧和Native Dmp文件發(fā)送給我們仅叫,我們就可以進(jìn)行問題排查和修復(fù)了帜篇。

由于篇幅原因,這里就給出一個(gè)思路诫咱,我們可以在Java Excpetion 和 Native DumpCallback的時(shí)候笙隙,新起一個(gè)進(jìn)程,在這個(gè)進(jìn)程里面進(jìn)行日志上傳坎缭,甚至可以彈出一個(gè)Activity告知用戶竟痰,提升用戶體驗(yàn)。如何在Native DumpCallback新開進(jìn)程并彈出Activity掏呼,這又是一個(gè)較大的話題坏快,我們以后有機(jī)會(huì)再一起探討。:-D

總結(jié)

當(dāng)應(yīng)用上線之后憎夷,脫離了Logcat提供的便利莽鸿,開發(fā)者應(yīng)該如何獲取錯(cuò)誤信息進(jìn)行異常修復(fù),本文提供了一些隨手可行的思路,包含了Java層和Native層不同的處理辦法祥得,通過實(shí)例代碼步步深入兔沃,希望帶給大家一起啟發(fā),同時(shí)解決生產(chǎn)上的一些實(shí)際問題级及。

本文作者:夏欣(點(diǎn)融黑幫)乒疏,就職于點(diǎn)融大前端,Android程序員一枚饮焦。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末怕吴,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子县踢,更是在濱河造成了極大的恐慌转绷,老刑警劉巖,帶你破解...
    沈念sama閱讀 217,277評論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件殿雪,死亡現(xiàn)場離奇詭異暇咆,居然都是意外死亡锋爪,警方通過查閱死者的電腦和手機(jī)丙曙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評論 3 393
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來其骄,“玉大人亏镰,你說我怎么就攤上這事≌” “怎么了索抓?”我有些...
    開封第一講書人閱讀 163,624評論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長毯炮。 經(jīng)常有香客問我逼肯,道長,這世上最難降的妖魔是什么桃煎? 我笑而不...
    開封第一講書人閱讀 58,356評論 1 293
  • 正文 為了忘掉前任篮幢,我火速辦了婚禮,結(jié)果婚禮上为迈,老公的妹妹穿的比我還像新娘三椿。我一直安慰自己,他們只是感情好葫辐,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評論 6 392
  • 文/花漫 我一把揭開白布搜锰。 她就那樣靜靜地躺著,像睡著了一般耿战。 火紅的嫁衣襯著肌膚如雪蛋叼。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,292評論 1 301
  • 那天剂陡,我揣著相機(jī)與錄音狈涮,去河邊找鬼租冠。 笑死,一個(gè)胖子當(dāng)著我的面吹牛薯嗤,可吹牛的內(nèi)容都是我干的顽爹。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼骆姐,長吁一口氣:“原來是場噩夢啊……” “哼镜粤!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起玻褪,我...
    開封第一講書人閱讀 38,992評論 0 275
  • 序言:老撾萬榮一對情侶失蹤肉渴,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后带射,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體同规,經(jīng)...
    沈念sama閱讀 45,429評論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評論 3 334
  • 正文 我和宋清朗相戀三年窟社,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了券勺。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,785評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡灿里,死狀恐怖关炼,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情匣吊,我是刑警寧澤儒拂,帶...
    沈念sama閱讀 35,492評論 5 345
  • 正文 年R本政府宣布,位于F島的核電站色鸳,受9級特大地震影響社痛,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜命雀,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評論 3 328
  • 文/蒙蒙 一蒜哀、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咏雌,春花似錦凡怎、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,723評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至氛雪,卻和暖如春房匆,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,858評論 1 269
  • 我被黑心中介騙來泰國打工浴鸿, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留井氢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,891評論 2 370
  • 正文 我出身青樓岳链,卻偏偏與公主長得像花竞,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子掸哑,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評論 2 354

推薦閱讀更多精彩內(nèi)容