[譯] 如何用 Android vitals 解決應用程序的質量問題

兩篇中的第一篇:修復 ANR 事件和過分喚醒是如何提升應用在 Play Store 上的表現的

對於一個應用開發者來講,沒有比開心的用戶更好的衡量成功的標準,並且最好是有不少這樣的用戶。實現這一目標的最佳方式是擁有一我的人都想用的優秀應用,不過咱們所說的「優秀」指的是什麼呢?它能夠歸結爲兩件事:功能和應用質量。前者最終取決於你的創造力和選擇的商業模式,然後者能夠客觀地衡量和改進。html

在去年進行的一項 Google 內部研究中,咱們查看了 Play Store 中的一星評論,發現超過 40% 的人提到應用穩定性的問題。相對的,人們會用更高的評分和更好的評論持續獎勵那些表現最佳的應用。這使得它們在 Google Play 上得到更好的排名,而好的排名有助於提升安裝量。不只如此,用戶還會更加投入,並願意在這些應用程序上花費更多的時間和金錢。前端

所以,解決應用程序的穩定性問題能夠在很大程度上決定它有多成功。java

爲了提供一個客觀的質量衡量標準,使你能夠輕鬆發現應用須要解決哪些穩定性問題,咱們在 Play Console 中添加了一個名爲 Android vitals 的新模塊。這個模塊能夠告訴你應用程序的性能和穩定性問題,而不須要在代碼中添加儀器或庫。當你的應用程序運行在衆多設備上的時候,Android vitals 會收集關於應用程序性能的匿名指標。即便在使用硬件實驗室進行測試時,它也會以其餘方式難以得到的規模爲你提供信息。android

Android vitals 能夠提醒你的問題包括崩潰、應用程序無響應(ANR)和渲染時間。這些問題都直接影響你的用戶對應用的體驗和見解。此外,還有一類用戶可能不會直接與你的應用關聯的不良應用行爲:好比耗電的速度比預期的要快。ios

在本文中,我將着眼於如下兩個問題:git

  • 過分喚醒。這會影響電池的續航時間,若是用戶沒法及時充電,可能會致使他們沒法使用設備。這種行爲極可能會讓用戶迅速卸載你的應用。
  • 應用程序無響應(ANR)事件。這些事件發生在你的應用程序 UI 凍結的時候。發生凍結時,若是你的應用位於前臺,會彈出對話框讓用戶選擇關閉應用或等待響應。從用戶的角度來看,這種行爲與應用崩潰同樣糟糕。用戶可能不會當即卸載你的應用,但若是 ANR 持續存在,用戶極可能會尋找替代的應用。

過分喚醒

那麼,喚醒是什麼以及它們什麼時候變得過分呢?github

爲了延長電池的續航時間,屏幕關閉後,Android 設備將經過禁用主 CPU 內核進入深度睡眠模式。除非用戶喚醒設備,不然設備會盡量長時間地保持在此狀態。可是,有一些重要事件須要喚醒 CPU 並提醒用戶,例如,當鬧鐘響起或有新的聊天消息到達時。這些警報能夠經過喚醒警報(wakeup alarm)來處理,但正如我將要解釋的那樣,這並非必須的。到目前爲止,喚醒彷佛是一件好事,它能夠顯示重要的事件引發用戶的注意,可是若是有太多這種事件那麼電池壽命就會受到影響。編程

Android vitals 如何顯示過分喚醒?

瞭解你的應用是否在驅動過多的喚醒是 Android vitals 的重要任務。收集的有關你應用行爲的匿名數據用於顯示自設備徹底充電後,每小時經歷超過 10 次喚醒的用戶的百分比。要查看的關鍵點是一個紅色的圖標;這個圖標告訴你,你的應用已超出不良行爲閾值。而這個閾值表示你的應用屬於 Google Play 上表現較差的應用,你應該考慮改善其行爲。後端

喚醒警報是否有其餘替代方法?

在指定時間或間隔後喚醒設備的主要方法是使用 AlarmManager API 的 RTC_WAKEUP 或 ELAPSED_REALTIME_WAKEUP 標誌來安排警報。可是必定要注意謹慎地使用此功能,並且只有在其餘調度和通知機制不能更好地提供服務的狀況下。當你想要使用喚醒警報時,請注意考慮如下幾點:api

  • 若是你須要根據網絡返回的數據來顯示信息,能夠考慮使用消息推送來實現,例如 Firebase Cloud Messaging。使用這種機制而不是按期拉取新數據,你的應用只有在須要時纔會被喚醒。

  • 若是你沒法使用消息推送而且依賴按期拉取,能夠考慮使用 JobScheduler 或者是 Firebase JobDispatcher(甚至是 SyncManager 來獲取賬戶數據)。這些是比 AlarmManager 更高級別的 API,並且爲更智能的按期任務提供如下好處:

    A) 批處理 —— 許多任務將被批量處理以使設備睡眠時間更長,而不是屢次喚醒系統來執行這些任務。

    B) 條件 —— 你能夠指定必須知足某些條件才能執行你的任務,例如網絡可用性或電池的充電狀態。使用這些條件能夠避免沒必要要的設備喚醒和應用運行。

    C) 持續性和自動重試 —— 任務能夠持續執行(即便從新啓動也能夠),而且能夠在發生故障時自動重試。

    D) Doze 兼容性 —— 任務只有在不受 Doze 模式限制或應用程序待機時纔會執行。

只有當消息推送和按期任務不適合你的工做時,你才應該使用 AlarmManager 安排喚醒警報。或者從另外一個角度來看,只有當你須要在特定時間啓動鬧鐘時才須要使用喚醒警報,不管網絡或其餘條件如何。

Android vitals 顯示過分喚醒時你應該怎麼作?

要解決過分喚醒的問題,請先肯定你的應用在哪些地方設置了喚醒警報,而後下降觸發這些警報的頻率。

要肯定你的應用在哪些地方設置了喚醒警報,請在 Android Studio 中打開 AlarmManager 類,右鍵單擊 RTC_WAKEUP 或 ELAPSED_REALTIME_WAKEUP 字段並選擇 「Find Usages」。這將顯示你項目中用到這些標誌的全部實例。審查每個實例,看看你是否能夠切換到更智能的定時任務機制中的一種。

你還能夠在 Find Usages 選項中將範圍設置爲「項目和庫」,以肯定你的依賴庫是否使用了 AlarmManager API。若是是,你應該考慮使用替代庫或向做者報告這個問題。

若是你決定必須使用喚醒警報,那麼若是你提供了符合如下要求的警報標籤,則 Play Console 能夠提供更好的分析數據:

  • 在你的警報標籤名稱中包含你的包名、類名或方法名。這也能夠幫助你輕鬆識別警報設置在你源碼中的什麼位置。
  • 請勿使用 Class#getName() 做爲警報名稱,由於它可能會被 Proguard 混淆。改用硬編碼的字符串。
  • 不要將計數器或其餘惟一標識符添加到警報標籤,由於系統可能會丟棄標籤,並且沒法將它們聚合成有用的數據。

應用程序無響應

那麼,什麼是應用程序無響應(ANR),它又是如何影響用戶的呢?

對於用戶來講,ANR 是當他們嘗試與你的應用進行交互時,該界面被凍結。界面保持凍結幾秒鐘後,會顯示一個對話框,讓用戶選擇等待或強制應用程序退出。

從應用程序開發的角度來看,當應用程序由於執行耗時操做(如磁盤或網絡讀寫)阻塞主線程時,就會發生 ANR。主線程(有時稱爲 UI 線程)負責響應用戶事件並刷新屏幕上每秒繪製六十次的內容。所以,將任何可能延遲其工做的操做都轉移到後臺線程是相當重要的。

Android vitals 如何顯示 ANR?

使用收集到的有關你應用 ANR 事件的匿名數據,Android vitals 提供了有關 ANR 的多個級別的詳細信息。主屏幕顯示你應用程序中發生 ANR 的 Activity 的概況。這顯示了用戶經歷過至少一次 ANR 的每日會話的百分比,以及以前最近 30 天的單獨報告。還提供了不良行爲的閾值。

詳細信息視圖的 ANR 比例頁面顯示了 ANR 比例隨時間變化的詳細信息,以及按應用版本、Activity 名稱、ANR 類型和 Android 版本顯示的 ANR 信息。你能夠經過 APK 版本號、支持的設備、操做系統版本和時間段來過濾這些數據。

你還能夠從 ANRs & crashes 部分獲取更多詳細信息。

ANR 的常見緣由是什麼?

如前所述,當應用程序進程阻塞主線程時就會發生 ANR。幾乎任何緣由均可能致使這種阻塞,但最多見的緣由包括:

  • 在主線程上執行磁盤或網絡讀寫操做。這是迄今爲止 ANR 最多見的緣由。雖然大多數開發人員都認爲你不該該在主線程上讀取或寫入數據到磁盤或網絡,但有時咱們總會無心間這麼作。在理想狀況下從磁盤讀取幾個字節可能不會致使 ANR,可是這毫不是一個好主意。若是用戶使用的設備閃存很慢怎麼辦?若是他們的設備受到來自其餘應用程序同時讀取和寫入的巨大壓力,而你的應用程序在隊列中等待執行「快速」讀取操做時又該怎麼辦?切勿在主線程上執行讀寫操做。
  • 在主線程上執行長時間計算。那麼內存裏的計算會怎麼樣呢?RAM 不會受長時間訪問的影響,較小的操做應該沒問題。可是,當你開始在循環中執行復雜計算或處理大型數據集時,能夠輕鬆阻塞主線程。能夠考慮調整包含數百萬像素的大圖像的大小,或解析大塊的 HTML 文本,而後在 TextView 中顯示。通常來講,最好讓你的應用在後臺執行這些操做。
  • 從主線程向另外一個進程運行同步綁定調用。與磁盤或網絡操做相似,在跨進程邊界進行阻塞調用時,程序執行會傳遞到你沒法控制的某個位置。若是其餘進程很忙怎麼辦?若是它須要訪問磁盤或網絡來響應你的請求怎麼辦?另外,數據傳遞給另外一個進程須要進行序列化和反序列化,這也須要時間。最好從後臺線程進行進程間調用。
  • 使用同步。即便你將繁重的操做移動到後臺線程,也須要與主線程進行通訊以顯示進度或計算的結果。多線程編程並不容易,並且在使用同步進行鎖定時,一般很難保證不會阻塞執行。在最糟糕的狀況下,它甚至可能致使死鎖,線程之間互相阻塞永久等待下去。最好不要本身設計同步,使用專門的解決方案會更好一些,好比 Handler,從後臺線程傳遞不可變的數據到主線程。

我如何檢測 ANR 的緣由?

查找 ANR 的緣由可能會很是棘手,就拿 URL 類來講吧。 你以爲肯定兩個 URL 是否相同的 URL#equals 方法是否會被阻塞?SharedPreferences 又會怎樣?若是你在後臺從中讀取值,能夠在主線程上調用 getSharedPreferences 方法嗎?在這兩種狀況下,答案是這些均可能是長時間阻塞操做。

幸運的是,StrictMode 使查找 ANR 再也不靠猜的。在調試版本中使用這個工具能夠捕獲主線程上意外的磁盤和網絡訪問。在應用程序啓動時使用 StrictMode#setThreadPolicy 能夠自定義你想要檢測的內容,包括磁盤和網絡讀寫,甚至能夠經過 StrictMode#noteSlowCall 在應用程序中觸發自定義的慢速調用。你還能夠選擇 StrictMode 在檢測到阻塞調用時如何提醒你:經過讓應用程序崩潰、Log 信息或者是顯示對話框。更多詳細信息,請參閱 ThreadPolicy.Builder類

一旦你消除了主線程中的阻塞調用,記得在將你的應用程序發佈到 Play Store 以前關閉 StrictMode。

消除過分喚醒和 ANR 將提升應用程序的質量和可用性,提升評分和評論,進而實現更多安裝。經過查看 Android vitals,你能夠快速輕鬆地發現是否存在須要解決的問題。在代碼中查找和解決這些問題並不老是那麼直截了當,但有些工具和技術能夠幫你更高效地完成這些工做。

Android vitals 還能夠給你提供更多幫助,我會在下一篇文章裏介紹更多這些功能。我將在 5 月 8 日星期二下午 3 點,在 Google I/O 2018 大會上和同事 Fergus Hurley 以及 Joel Newman 一塊兒演示 「Android vitals:調試應用程序性能和收穫獎勵」 的環節。若是你在那裏或者想經過直播瞭解更多關於 Android vitals、最新的 Play Console 和 Android Studio 工具以及幫助你提升應用質量的意見,請加入咱們。


若是你對 Android vitals 有任何想法或疑問,請經過 #AskPlayDev 發送推特告知咱們。咱們會經過 @GooglePlayDev 回覆你,咱們也會按期在上面分享有關如何在 Google Play 上取得成功的新聞和提示。

若是發現譯文存在錯誤或其餘須要改進的地方,歡迎到 掘金翻譯計劃 對譯文進行修改並 PR,也可得到相應獎勵積分。文章開頭的 本文永久連接 即爲本文在 GitHub 上的 MarkDown 連接。


掘金翻譯計劃 是一個翻譯優質互聯網技術文章的社區,文章來源爲 掘金 上的英文分享文章。內容覆蓋 AndroidiOS前端後端區塊鏈產品設計人工智能等領域,想要查看更多優質譯文請持續關注 掘金翻譯計劃官方微博知乎專欄

相關文章
相關標籤/搜索