如何進行 APK 的閃退除錯

這篇文章將會記錄,當您的開發的應用程式已經安裝到使用者的手機上了,此時,發生了閃退現象,但您沒有任何支援閃退問題紀錄的工具來幫助您顯示問題;這個時候,您可以透過此篇文章,進行低階 Log 除錯。
這篇文章將會使用 Xamarin.Forms 的 Todo 範例程式,您可以從此下載這個專案。

設定 Todo 專案會發生異常閃退

  1. 請開啟 Todo 專案
  2. 滑鼠右擊 TodoPCL>Targets>Todo.Android專案,選擇 設定為起始專案
  3. 專案組態可以選擇 Debug
  4. 請將手機插到電腦 USB 上,並且進入到 USB 偵錯模式。
  5. 在方案總管中,展開 TodoPCL > Targets > Todo.Android 專案,使用滑鼠雙擊 Properties 節點
  6. 切換到 Android Options 標籤頁次,接著請在標題 Linking 節點上,選擇 Sdk Assemblies Only,接著,執行這個專案
    此時,您會發現這個專案可以正常在您的手機上執行
    TodoAndOpt1
  7. 在方案總管中,展開 TodoPCL > Targets > Todo.Android 專案,使用滑鼠雙擊 Properties 節點
  8. 切換到 Android Options 標籤頁次,接著請在標題 Linking 節點上,選擇 Sdk and User Assemblies,接著,執行這個專案
    此時,您會發現到您的專案無法在手機上執行。
    現在,您的手機上已經有一個 Xamarin.Forms 製作的應用程式,並且一旦執行這個應用程式,該程式就會閃退。
    TodoAndOpt1

準備進行閃退應用程式偵錯

  1. 請將有安裝閃退應用程式的手機,接上電腦,而該手機必須進入開發者模式,並允許 USB 除錯。
  2. 使用 Visual Studio 開啟這個 Todo 專案。
  3. 點選功能表 工具 > Android > Android Device Logging... 開啟 Android Device Logging 視窗
    AndroidDeviceLog
  4. 若 Android Device Logging 視窗內,看不到任何訊息
    • 請點選左上方的手機螢幕圖示
    • 在開啟的 Select Device 對話窗內,選擇您的手機,並且點選 OK 按鈕
    AndroidDeviceLogWin
  5. 在 Android Device Logging 視窗下,請確認長的如下圖
    • 確認下圖標示 (1) 的地方,為正在進行蒐集 Log 狀態
    • 請切換到 Text View 模式
    • 當要進行應用程式閃退問題蒐集前,可以點選 Clear 按鈕,隨時清空多餘的訊息。
    AndroidDeviceLog設定

進行應用程式閃退問題蒐集

  1. 請點選 Clear 按鈕
  2. 請在手機中執行有問題的程式
  3. 當程式閃退之後,請點選 停止紀錄訊息按鈕,此時,Android Device Logging 視窗如下所示
    AndroidDeviceLog偵測結束
  4. Android Device Logging 視窗內,按下 Ctrl + A 接著按下 Ctrl + C ,把所有的訊息複製下到。
    您可以將這些內容貼到如 記事本 程式內來做分析
  5. 請搜尋這個關鍵字 FATAL EXCEPTION: mai 找到此次異常閃退的問題紀錄
    • 在 java.lang.RuntimeException: 之下的紀錄,為 Android 這裡 Java 發出的持行時期例外異常
    • 在 Caused by: android.runtime.JavaProxyThrowable: 之後的紀錄,說明了 Xamarin.Android 這裡產生的例外異常紀錄。
    • 底下訊息可以看出
      Position 6:31. No method listItemSelected found on type Todo.TodoItemListX 應用程式在這個時候,找不到 Todo.TodoItemListX 這個類別的建構式。而真正的原因是,Xamarin.Android 的 Linker 在進行組件連結的時候,因為使用靜態分析方法,導致 Todo.TodoItemListX 這個類別被 Linker 移除掉了。
      • Force finishing activity Todo.Android/md5321ee62e7307662a691059f7f382b8e6.MainActivity 這個訊息則是記錄下,這個應用程式此時要結束執行了,也就是要閃退了。
07-28 19:33:12.845 E/AndroidRuntime(13163): FATAL EXCEPTION: main
07-28 19:33:12.845 E/AndroidRuntime(13163): Process: Todo.Android, PID: 13163
07-28 19:33:12.845 E/AndroidRuntime(13163): java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
07-28 19:33:12.845 E/AndroidRuntime(13163):     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:695)
07-28 19:33:12.845 E/AndroidRuntime(13163): Caused by: java.lang.reflect.InvocationTargetException
07-28 19:33:12.845 E/AndroidRuntime(13163):     at java.lang.reflect.Method.invoke(Native Method)
07-28 19:33:12.845 E/AndroidRuntime(13163):     at java.lang.reflect.Method.invoke(Method.java:372)
07-28 19:33:12.845 E/AndroidRuntime(13163):     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:900)
07-28 19:33:12.845 E/AndroidRuntime(13163):     ... 1 more
07-28 19:33:12.845 E/AndroidRuntime(13163): Caused by: android.runtime.JavaProxyThrowable: Xamarin.Forms.Xaml.XamlParseException: Position 6:31. No method listItemSelected found on type Todo.TodoItemListX
07-28 19:33:12.845 E/AndroidRuntime(13163):   at Xamarin.Forms.Xaml.ApplyPropertiesVisitor.SetPropertyValue (System.Object xamlelement, XmlName propertyName, System.Object value, System.Object rootElement, INode node, Xamarin.Forms.Xaml.HydratationContext context, IXmlLineInfo lineInfo) <0xf092e618 + 0x0035b> in <filename unknown>:0 
07-28 19:33:12.845 E/AndroidRuntime(13163):   at Xamarin.Forms.Xaml.ApplyPropertiesVisitor.Visit (Xamarin.Forms.Xaml.ValueNode node, INode parentNode) <0xf092df98 + 0x0034b> in <filename unknown>:0 
07-28 19:33:12.845 E/AndroidRuntime(13163):   at Xamarin.Forms.Xaml.ValueNode.Accept (IXamlNodeVisitor visitor, INode parentNode) <0xf0942878 + 0x00023> in <filename unknown>:0 
07-28 19:33:12.845 E/AndroidRuntime(13163):   at Xamarin.Forms.Xaml.ElementNode.Accept (IXamlNodeVisitor visitor, INode parentNode) <0xf09428f8 + 0x000f7> in <filename unknown>:0
  1. 解決方式請參考下圖,這是因為:
    • 使用標題 Skip linking assemblies: 下的欄位,輸入 QuickTodo ,表示,這個組件不需要進行 Link 連結分析處理。
    • Todo.TodoItemListX 這個類別位於 QuickTodo 這個組件內。
    • 請反覆這些步驟,把需要排除的組件逐一加回來即可。
    修正Linker錯誤