標籤:
Android 7.0行為變化—開發人員應該關注的(官網同步翻譯)
著作權聲明:轉載必須註明本文轉自嚴振傑的部落格: http://blog.yanzhenjie.com
如果想瞭解更多Android7.0的內容,可以順便再看看Android7.0寫給開發人員的一封信(官網同步翻譯)。
如果你的引文夠好,推薦你閱讀官網文章:
Android 7.0 Behavior Changes
Android N 除了提供諸多新特性和功能外,還對系統和 API 行為做出了各種變更。本文重點介紹你應該瞭解並在開發應用時加以考慮的一些重要變更。
如果您之前發布過Android App,請注意你的App可能受到這些平台變更的影響。
電池和記憶體
Android N包括旨在延長裝置電池壽命和減少RAM使用的系統行為變更。這些變更可能會影響您的應用訪問系統資源,以及您的系統通過特定隱式Intent與其他應用互動的方式。
低電耗模式
Android 6.0(API leve 23)引入了低電耗模式,當使用者裝置未插接電源、處於靜止狀態且螢幕關閉時,該模式會延遲CPU和網路訪問,從而延長電池壽命。而Android 7.0則通過在裝置未插接電源且螢幕關閉狀態下、但不一定要處於靜止狀態(例如使用者外出時把手持功能裝在兜兜裡)時應用部分CPU和網路限制,進一步增強了低電耗模式。
低電耗模式如何應用第一級系統活動限制以延長電池壽命的圖示:
當裝置處於充電狀態且螢幕已關閉一定時間後,裝置會進入低電耗模式並應用第一部分限制:關閉應用網路訪問、延遲Work和Sync。如果進入低電耗模式後裝置處於靜止狀態達到一定時間,系統則會對PowerManager.WakeLock、AlarmManager、鬧鈴、GPS和Wi-Fi掃描應用低電耗模式限制。無論是應用部分限制還是全部低電耗模式限制,系統都會喚醒裝置提供一個短時間的維護視窗,在此視窗展示期間,應用程式可以訪問網路並執行所有被延遲的Work/Sync。
低電耗模式如何在裝置處於靜止狀態達到一定時間後應用第二級系統活動限制的圖示:
請注意,啟用螢幕或插接裝置電源時,系統將退出低電耗模式並取消之前的限制。此項新增的行為不會影響有關使你的App適應Android 6.0(API Leve23)中所發布舊版本低電耗模式的建議和最佳實務,如低電耗模式和應用待機模式最佳化中提到的內容。你還是應該遵循這些建議(例如使用 Google Cloud Messaging (GCM) 發送和接收訊息),並且相容新的低電耗模式。
Project Svelte:後台最佳化
Android 7.0刪除了三個隱式廣播,最佳化記憶體使用量和最佳化電量消耗。這個變化是非常必要的,因為隱式廣播會在後台頻繁啟動登入偵聽這些廣播的應用。刪除這些廣播可以顯著提升裝置效能和使用者體驗。
行動裝置會經曆頻繁的串連變更,例如在Wi-Fi和移動資料之間切換時。目前,可以通過在Manifest.xml中註冊一個BroadcastRecevier來監聽隱式CONNECTIVITY_ACTION廣播,讓應用能夠監控這些變更。由於很多App會註冊接收這個廣播,因此單次網路切換即會導致所有應用被喚醒並同時處理此廣播。
同樣的道理,應用可以註冊接收來自其他應用(例如相機)的隱式ACTION_NEW_PICTURE和ACTION_NEW_VIDEO廣播。當使用者使用相機應用拍攝照片時,這些應用即會被喚醒以處理廣播。
為緩解緩解上面的問題,Android 7.0採用了下面最佳化措施:
- 針對Android 7.0開發的應用不會收CONNECTIVITY_ACTION廣播,即使它們已經在
Manifest.xml中註冊了接受這個廣播的BroadcastRecevier因為不會收到。在前台啟動並執行應用如果使用BroadcastReceiver接收通知,則仍可以在主線程中偵聽CONNECTIVITY_CHANGE。
- 應用無法發送或接收
ACTION_NEW_PICTURE或ACTION_NEW_VIDEO廣播。這個改變會影響到所有的App,不僅僅是針對Android 7.0開發的App。
如果你的App使用了任何隱式Intent,您仍需要儘快移除它們的依賴關係,以正確適配Android 7.0的裝置。 Android framework提供多個解決方案來緩解對這些隱式廣播的需求。例如JobScheduler API提供了一個穩健可靠的機制來安排滿足指定條件(例如連入無限流量網路)時所執行的網路操作。您甚至可以使用JobScheduler來適應 Content providers變化。
如需瞭解有關 Android 7.0中後台最佳化以及如何改寫應用的詳細資料,請參閱後台最佳化。
許可權更改
Android 7.0 做了一些許可權更改,這些更改可能會影響到你的App。
系統許可權更改
為了提高私人檔案的安全性,面向 Android 7.0或更高版本的App私人目錄被限制訪問(0700)。此設定可防止私人檔案的中繼資料泄漏,如它們的大小或是否存在(狀態)。此權限原則的更改有多重副作用:
私人檔案的檔案許可權不應再由所有者放寬,為使用MODE_WORLD_READABLE和MODE_WORLD_WRITEABLE而進行的此類嘗試將觸發SecurityException,會導致App崩潰的。
註:迄今為止,這種限制還不能完全執行。App仍可能使用原生API或File API來修改它們的私人目錄許可權。但是Google強烈反對放寬私人目錄的許可權。
傳遞軟體包網域外的 file://URI可能給接收器留下無法訪問的路徑。因此傳遞file://URI會觸發 FileUriExposedException。分享私人檔案內容的推薦方法是使用FileProvider。
- DownloadManager不再按檔案名稱分享私人儲存的檔案。老的App在訪問COLUMN_LOCAL_FILENAME時可能出現無法訪問的路徑。針對Android 7.0或更高版本開發的應用在嘗試訪問COLUMN_LOCAL_FILENAME時會觸發 SecurityException。通過使用DownloadManager.Request.setDestinationInExternalFilesDir()或DownloadManager.Request.setDestinationInExternalPublicDir()將下載位置設定為公用位置的老App仍可以訪問COLUMN_LOCAL_FILENAME中的路徑,但是Google還是強烈反對使用這種方法。訪問由DownloadManager公開的檔案的首選方式是使用ContentResolver.openFileDescriptor()。
應用間共用檔案
對於針對Android 7.0的應用,Android framework執行的StrictMode API禁止向你的App外公開file://URI。如果一個包含檔案URI的Intent發送到你的應用之外,App會發生FileUriExposedException異常。
若要在應用間共用檔案,您應發送一項content://URI,並授予URI臨時存取權限。進行此授權的最簡單方式是使用FileProvider類。如需有關許可權和共用檔案的更多資訊,請參閱共用檔案。
無障礙改進
為提高平台對於視力不佳或視力受損使用者的可用性,Android 7.0做出了一些更改。這些更改正常情況下不需要改你的代碼,不過你要仔細檢查並用你的App測試這些功能,以評估它們對使用者體驗的潛在影響。
螢幕縮放
Android 7.0支援使用者佈建顯示尺寸,以放大或縮小螢幕上的所有元素,從而提升裝置對視力不佳使用者的可訪問性。使用者無法將螢幕縮放至低於最小螢幕寬度sw320dp,該寬度是Nexus 4的寬度,也是常規中等大小手機的寬度。
Android 7.0 系統映像正常大小運行效果:
Android 7.0 系統映像增大顯示尺寸後的效果:
當裝置密度發生更改時,系統會以如下方式通知正在啟動並執行應用:
- 如果是面向API leve 23或更低版本系統的應用,系統會自動終止其所有後台進程。也就是說如果使用者切換後離開你的App,開啟“Settings”更改
Display size設定,則系統會像處理記憶體不足的情況一樣終止該應用。如果應用具有任何前台進程,則系統會如處理運行時變更中所述將配置變更通知給這些進程,就像對待裝置螢幕方向變更一樣,具體大家可以再看看這個超連結。
- 如果是針對Android 7.0的App,則其所有進程(前台和後台)都會收到有關配置變更的通知,如處理運行時變更中所講的那樣。
大多數App並不需要進行任何更改即可支援此功能,不過前提是這些應用遵循Android最佳實務。具體要檢查的事項:
- 在螢幕寬度為 sw320dp 的裝置上測試你的App,並確保其正常運行。
- 當裝置Config發生變更時,更新任何與密度相關的緩衝資訊,例如緩衝位元影像或從網路載入的資源。當應用從暫停狀態恢複運行時,檢查Config的變化。
註:如果你要緩衝與配置相關的資料,則最好也包括相關中繼資料,例如該資料對應的螢幕尺寸或像素密度。儲存這些中繼資料便於你在Config變更後決定是否需要重新整理快取資料。
- 避免用像素單位指定尺寸,因為像素不會隨螢幕密度縮放。應改為使用dp等單位。
設定嚮導中的視覺設定Android 7.0 在“Welcome”頁面中加入了“Vision Settings”,使用者可以在新裝置上操作`無障礙功能設定`: `Magnification gesture`、`Font size`、`Display size`和`TalkBack`。這個變化增加了與不同螢幕設定相關的錯誤的可見度。要測試此功能的影響,你應該在啟用這些設定的狀態下測試應用,可以在`Settings > Accessibility`中找到這些設定。NDK 應用連結至平台庫Android 7.0做了一些命名空間更改,以阻止載入非公開API。如果你使用NDK,則只能使用Android平台提供的公開 API。在下一個官方發布的Android 版本上使用非公開API會導致應用崩潰。為提醒你使用了非公開API,在Android 7.0的裝置上啟動並執行App會在有App調用非公開API時在日誌訊息輸出中產生一個錯誤。此錯誤還會作為訊息顯示在裝置螢幕上,以協助增強你對此情況的認識。你應該檢查應用代碼以刪除使用非公開API,並使用預覽版裝置或模擬器全面測試App。如果您的App依賴平台庫,則請參見NDK文檔,瞭解使用公開API等效替換普通私人API的修複方案。你還可以連結至平台庫,而無需實現此應用,如果App使用的庫是平台的一部分(例如libpng),但不屬於NDK,則更可如此。這種情況下,請確保您的APK包含您打算連結到的所有.so 檔案。
注意:有些第三方庫可能會連結至非公開API。如果您的應用使用這些庫,那麼當您的應用在下一個官方發布的 Android 版本上運行時可能會出現崩潰現象,so,你也要認真檢查使用的第三方庫是否使用了非公開api,例如百度地圖。
App不應該依賴或使用不屬於NDK的原生庫,因為這些庫可能會發生更改,或者從一個Android版本遷移至另一版本的時候發生更改。例如,從OpenSSL切換至BoringSSL即屬於此類更改。此外,不同的裝置可能提供不同層級的相容性,因為不屬於NDK中的平台庫沒有相容性要求。如果你必須在較舊裝置上訪問非NDK庫,則請依據 Android API 層級進行載入。為協助您診斷此類問題,下面列舉了一些在您試圖使用 Android N 開發應用時可能遇到的 Java 和 NDK 錯誤:Java 錯誤樣本:
java.lang.UnsatisfiedLinkError: dlopen failed: library "/system/lib/libcutils.so" is not accessible for the namespace "classloader-namespace"
NDK 錯誤樣本:
dlopen failed: cannot locate symbol "__system_property_get" referenced by ...
以下是遇到這類錯誤的應用的一些典型修複:* 可以使用標準JNI函數來替代使用`libandroid_runtime.so`中的`getJavaVM`和`getJNIEnv`:
AndroidRuntime::getJavaVM -> GetJavaVM from <jni.h>AndroidRuntime::getJNIEnv -> JavaVM::GetEnv orJavaVM::AttachCurrentThread from <jni.h>.
- 可以使用公開
alternative __system_property_get來替代使用libcutils.so中的property_get符號。如需這樣做,請使用 __system_property_get及以下include函數:
#include <sys/system_properties.h>
- 應使用應用本地版本來替代使用
libcrypto.so中的SSL_ctrl符號。例如,你應在.so檔案中靜態連結libcyrpto.a,或者在應用中包含你自己的來自BoringSSL或OpenSSL的動態libcrypto.so。
Android for Work
Android 7.0包含一些針對面向Android for Work的應用的變更,包括對認證安裝、密碼重設、二級使用者管理、裝置標識符存取權限的變更。如果你是要針對Android for Work環境開發應用,則應仔細檢查這些變更並相應地修改你的App代碼。
你必須先安裝授權認證安裝程式,然後DPC才能對其進行設定。對於面向7.0 SDK的設定檔和裝置所有者應用,您應在裝置策略控制器(DPC)調用DevicePolicyManager.setCertInstallerPackage()之前安裝授權認證安裝程式。如果尚未安裝此安裝程式,則系統會引發IllegalArgumentException。
針對裝置管理員的重設密碼限制現在也適用於設定檔所有者。裝置管理員無法再使用DevicePolicyManager.resetPassword()來清除或更改已經設定的密碼。裝置管理員仍可以設定密碼,但只能在裝置沒有密碼、PIN或圖案時這樣做。
即使設定了限制,裝置所有者和設定檔所有者仍可以管理帳戶。而且,即使具有DISALLOW_MODIFY_ACCOUNTS使用者限制,裝置所有者和設定檔所有者仍可調用Account Management API。
裝置所有者可以更輕鬆地管理二級使用者。當裝置在裝置所有者模式下運行時,系統將自動化佈建DISALLOW_ADD_USER限制。這樣可以防止使用者建立非託管二級使用者。此外,CreateUser()和createAndInitializeUser()方法已棄用,取而代之的DevicePolicyManager.createAndManageUser()方法。
裝置所有者可以訪問裝置標識符。裝置所有者可以使用DevicePolicyManagewr.getWifiMacAddress()訪問裝置的Wi-Fi MAC地址。如果裝置上從未啟用Wi-Fi,則此方法將返回一個null值。
工作模式設定控制工作應用訪問。當工作模式關閉時,系統啟動器通過使工作應用顯示為灰色來指示它們不可用。啟用工作模式會再次恢複正常行為。
如需瞭解有關Android 7.0中針對Android for Work所做變更的詳細資料,請參閱Android for Work 更新。
註解保留
Android 7.0在註解可見度被忽略時修複錯誤。這種問題將啟用本不應被允許的運行時訪問註解。 這些註解包括:
* VISIBILITY_BUILD:僅應編譯時間可見。
* VISIBILITY_SYSTEM:運行時應可見,但僅限基本系統。
如果你的App依賴這種行為,請在註解中添加一項運行時必須可用的保留政策。你可通過使用@Retention(RetentionPolicy.RUNTIME) 這樣做。
其他重要說明
如果一個針對較低API層級開發的App在Android 7.0上運行,那麼在使用者更改顯示尺寸時,系統將終止此App進程。App必須能夠正常處理此情景。否則,當使用者從最近使用記錄中恢複運行App時,App將會出現崩潰現象。您應測試應用以確保不會發生此行為。要進行此測試,您可以通過DDMS手動終止應用,可以造成相同的崩潰現象。在螢幕密度發生更改時,系統不會自動終止針對Android 7.0及更高版本開發的App;不過這些App仍可能對配置變更做出不良響應。
Android 7.0上的應用應能夠正常處理配置變更,並且在後續啟動時不會出現崩潰現象。你可以通過更改字型大小 (Setting > Display > Font size) 並隨後從最近使用記錄中恢複運行應用,來驗證App行為。
由於之前的Android版本中的一項錯誤,系統沒有對主線程上的一個TCP Socket的寫入操作嚴格檢查。Android 7.0修複了這個系統錯誤。之前有這種行為的App將會引發android.os.NetworkOnMainThreadException。一般情況下,不建議在主線程上執行網路操作,因為這些操作通常都有可能導致ANR和卡頓,這個應該是中所周知的,大家一般不會犯。
Debug.startMethodTracing()方法族現在預設在你的共用的儲存空間上的軟體包特定目錄中儲存輸出,而非 SD卡頂級。這意味著應用不再需要請求WRITE_EXTERNAL_STORAGE許可權就可以使用這些API。
許多平台API現在開始檢查在Binder事務間發送的大負載,系統現在會將TransactionTooLargeExceptions再次作為RuntimeExceptions引發,而不再只是默默記錄或不拋出這個錯誤。一個常見例子是在Activity.onSaveInstanceState()上儲存過多資料,導致ActivityThread.StopInfo在你的App面向 Android 7.0時引發RuntimeException。
如果應用向View post Runnable任務,並且View未附加到視窗,系統會用View為Runnable任務排隊;在 View附加到視窗之前,Runnable任務不會執行。 此行為會修複以下錯誤:
- 如果一個App是從並非預期Window UI線程的其他線程發布到View,則
Runnable可能會因此運行錯誤。
- 如果
Runnable任務是從並非looper thread的其他線程發布,則應用可能會曝光Runnable任務。
如果Android 7.0上有DELETE_PACKAGES許可權的應用嘗試刪除一個軟體包,但另一項應用已經安裝了這個軟體包,則系統可能要求使用者確認。在這種情況下,應用在調用PackageInstaller.uninstall() 時的返回狀態應為STATUS_PENDING_USER_ACTION。
如果想瞭解更多Android7.0的內容,可以順便再看看Android7.0寫給開發人員的一封信(官網同步翻譯)。
著作權聲明:轉載必須註明本文轉自嚴振傑的部落格: http://blog.yanzhenjie.com
Android 7.0行為變化—開發人員應該關注的(官網同步翻譯)