前言
在 Gradle 外掛版本達到 3.4.0 及以上,預設會開啟 R8 進行程式碼優化,以往我們都是使用 SDK 自帶的 proguardgui.bat 來還原堆疊資訊,但在開啟了 R8 混淆後這個方法就失效了,原因是 R8 內部會做各種程式碼優化諸如內聯操作等,並實施行號對映,這時候在堆疊資訊中丟擲的行號就完全不是真實的崩潰位置了......
如何解決?
先來看下 release 版開啟混淆後所丟擲的異常資訊
可以看到,我們實際是在第 45 行丟擲一個 NullPointerException 的,但 Logcat 中的堆疊資訊卻顯示在第 8 行丟擲,通過 IDE 點選跳轉後直接會跳到最上方導包處,也就是無法定位真實位置。
有 2 種解決方法:
- 自行對照混淆後生成的 mapping 檔案,找出對應的真實行號,如下圖,可以看到第 8 行對應著第 45 行。
-
下載 R8 解混淆的 jar 包,點上方的 tgz 即可開始下載,需要科學上網( android.googlesource.com/platform/pr… ),下載完成後解壓到你的 Android SDK 所在位置的 lib 資料夾中,在這個資料夾中你可以看到 原有的 proguard 使用的 jar 包,防止萬一,你最好備份一下將被替換的檔案。當替換完成後,開啟以往使用 proguardgui.bat 的資料夾,這時 proguardgui.bat 無法使用了,必須使用命令列來進行解混淆,也不復雜,步驟如下所示:
-
新建一個 stacktrace.txt 用來複制想要解混淆的堆疊資訊進去,或者你自己有 dump 出來的 stacktrace 檔案也可以直接將檔案丟到資料夾中。
-
複製對應的 mapping 檔案到資料夾中
-
開啟命令列並跳轉到當前資料夾,輸入命令
retrace.bat -verbose mapping.txt stacktrace.txt > out.txt
,按下回車後當前資料夾下會生成一個out.txt
檔案,裡面存放的就是真實的堆疊資訊,如下圖所示。
-
最後
如果你還是覺得上述方法比較麻煩沒有原來的好用的話,其實還有一種,就是禁用 R8 ,用回 Proguard ,在專案根目錄的 gradle.properties 中寫上 android.enableR8=false
即可,然後你可能會在生成 APK 時遇到如下圖的報錯,那就在 proguard-rules.pro 中寫上 -ignorewarnings
,這樣就能順利編譯了,也可以用回 proguardgui.bat 的圖形化介面,前提是你有備份舊的 proguard.jar 和 retrace.jar 。