Android 6.0(API 級別 23)除了提供諸多新特性和功能外,還對系統(tǒng)和 API 行為做出了各種變更。本文重點介紹您應(yīng)該了解并在開發(fā)應(yīng)用時加以考慮的一些主要變更。
如果您之前發(fā)布過 Android 應(yīng)用,請注意您的應(yīng)用可能受到這些平臺變更的影響。
運行時權(quán)限
此版本引入了一種新的權(quán)限模式,如今,用戶可直接在運行時管理應(yīng)用權(quán)限。這種模式讓用戶能夠更好地了解和控制權(quán)限,同時為應(yīng)用開發(fā)者精簡了安裝和自動更新過程。用戶可為所安裝的各個應(yīng)用分別授予或撤銷權(quán)限。
對于以 Android 6.0(API 級別 23)或更高版本為目標(biāo)平臺的應(yīng)用,請務(wù)必在運行時檢查和請求權(quán)限。要確定您的應(yīng)用是否已被授予權(quán)限,請調(diào)用新增的 checkSelfPermission() 方法。要請求權(quán)限,請調(diào)用新增的 requestPermissions() 方法。即使您的應(yīng)用并不以 Android 6.0(API 級別 23)為目標(biāo)平臺,您也應(yīng)該在新權(quán)限模式下測試您的應(yīng)用。
低電耗模式和應(yīng)用待機模式
此版本引入了針對空閑設(shè)備和應(yīng)用的最新節(jié)能優(yōu)化技術(shù)。這些功能會影響所有應(yīng)用,因此請務(wù)必在這些新模式下測試您的應(yīng)用。
低電耗模式:如果用戶拔下設(shè)備的電源插頭,并在屏幕關(guān)閉后的一段時間內(nèi)使其保持不活動狀態(tài),設(shè)備會進入低電耗模式,在該模式下設(shè)備會嘗試讓系統(tǒng)保持休眠狀態(tài)。在該模式下,設(shè)備會定期短時間恢復(fù)正常工作,以便進行應(yīng)用同步,還可讓系統(tǒng)執(zhí)行任何掛起的操作。
應(yīng)用待機模式:應(yīng)用待機模式允許系統(tǒng)判定應(yīng)用在用戶未主動使用它時處于空閑狀態(tài)。當(dāng)用戶有一段時間未觸摸應(yīng)用時,系統(tǒng)便會作出此判定。如果拔下了設(shè)備電源插頭,系統(tǒng)會為其視為空閑的應(yīng)用停用網(wǎng)絡(luò)訪問以及暫停同步和作業(yè)。
取消支持 Apache HTTP 客戶端
Android 6.0 版移除了對 Apache HTTP 客戶端的支持。如果您的應(yīng)用使用該客戶端,并以 Android 2.3(API 級別 9)或更高版本為目標(biāo)平臺,請改用 HttpURLConnection 類。此 API 效率更高,因為它可以通過透明壓縮和響應(yīng)緩存減少網(wǎng)絡(luò)使用,并可最大限度降低耗電量。要繼續(xù)使用 Apache HTTP API,您必須先在 build.gradle 文件中聲明以下編譯時依賴項:
android {
useLibrary 'org.apache.http.legacy'
}
BoringSSL
Android 正在從使用 OpenSSL 庫轉(zhuǎn)向使用 BoringSSL 庫。如果您要在應(yīng)用中使用 Android NDK,請勿鏈接到并非 NDK API 組成部分的加密庫,如 libcrypto.so 和 libssl.so。這些庫并非公共 API,可能會在不同版本和設(shè)備上毫無征兆地發(fā)生變化或出現(xiàn)故障。此外,您還可能讓自己暴露在安全漏洞的風(fēng)險之下。請改為修改原生代碼,以通過 JNI 調(diào)用 Java 加密 API,或靜態(tài)鏈接到您選擇的加密庫。
硬件標(biāo)識符訪問權(quán)
為給用戶提供更嚴格的數(shù)據(jù)保護,從此版本開始,對于使用 WLAN API 和 Bluetooth API 的應(yīng)用,Android 移除了對設(shè)備本地硬件標(biāo)識符的編程訪問權(quán)。WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getAddress() 方法現(xiàn)在會返回常量值 02:00:00:00:00:00。
現(xiàn)在,要通過藍牙和 WLAN 掃描訪問附近外部設(shè)備的硬件標(biāo)識符,您的應(yīng)用必須擁有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 權(quán)限。
- WifiManager.getScanResults()
- BluetoothDevice.ACTION_FOUND
- BluetoothLeScanner.startScan()
注:當(dāng)運行 Android 6.0(API 級別 23)的設(shè)備發(fā)起后臺 WLAN 或藍牙掃描時,在外部設(shè)備看來,該操作的發(fā)起來源是一個隨機化 MAC 地址。
通知
此版本移除了 Notification.setLatestEventInfo() 方法。請改用 Notification.Builder 類來構(gòu)建通知。要重復(fù)更新通知,請重復(fù)使用 Notification.Builder 實例。調(diào)用 build() 方法可獲取更新后的 Notification 實例。
adb shell dumpsys notification 命令不再打印輸出您的通知文本。請改用 adb shell dumpsys notification **noredact 命令打印輸出 notification 對象中的文本。
音頻管理器變更
不再支持通過 AudioManager 類直接設(shè)置音量或?qū)⑻囟ㄒ纛l流靜音。setStreamSolo() 方法已棄用,您應(yīng)該改為調(diào)用 requestAudioFocus() 方法。類似地,setStreamMute() 方法也已棄用,請改為調(diào)用 adjustStreamVolume() 方法并傳入方向值 ADJUST_MUTE 或 ADJUST_UNMUTE。
文本選擇
現(xiàn)在,當(dāng)用戶在您的應(yīng)用中選擇文本時,您可以在一個浮動工具欄中顯示“剪切”、“復(fù)制”和“粘貼”等文本選擇操作。
要實現(xiàn)可用于文本選擇的浮動工具欄,請在您的現(xiàn)有應(yīng)用中做出以下更改:
- 在 View 對象或 Activity 對象中,將 ActionMode 調(diào)用從 startActionMode(Callback) 更改為startActionMode(Callback, ActionMode.TYPE_FLOATING)。
- 改為使用 ActionMode.Callback 的現(xiàn)有實現(xiàn)擴展 ActionMode.Callback2。
- 替代 onGetContentRect() 方法,用于提供 Rect 內(nèi)容對象(如文本選擇矩形)在視圖中的坐標(biāo)。
- 如果矩形的定位不再有效,并且這是唯一需要聲明為無效的元素,請調(diào)用 invalidateContentRect() 方法。
請注意,如果您使用 Android 支持庫 22.2 修訂版,浮動工具欄不向后兼容,默認情況下 appcompat 會獲得對 ActionMode 對象的控制權(quán)。這會禁止顯示浮動工具欄。要在 ActionMode 中啟用 AppCompatActivity 支持,請調(diào)用 getDelegate(),然后對返回的 setHandleNativeActionModesEnabled() 對象調(diào)用 AppCompatDelegate,并將輸入?yún)?shù)設(shè)置為 false。此調(diào)用會將 ActionMode 對象的控制權(quán)交還給框架。在運行 Android 6.0(API 級別 23)的設(shè)備上,框架可以支持 ActionBar 模式或浮動工具欄模式;而在運行 Android 5.1(API 級別 22)或之前版本的設(shè)備上,框架僅支持 ActionBar 模式。
瀏覽器書簽變更
此版本移除了對全局書簽的支持。android.provider.Browser.getAllBookmarks() 和 android.provider.Browser.saveBookmark() 方法現(xiàn)已移除。同樣,READ_HISTORY_BOOKMARKS 權(quán)限和 WRITE_HISTORY_BOOKMARKS 權(quán)限也已移除。如果您的應(yīng)用以 Android 6.0(API 級別 23)或更高版本為目標(biāo)平臺,請勿從全局提供程序訪問書簽或使用書簽權(quán)限。您的應(yīng)用應(yīng)改為在內(nèi)部存儲書簽數(shù)據(jù)。
Android 密鑰庫變更
從此版本開始,Android 密鑰庫提供程序不再支持 DSA。但仍支持 ECDSA。
停用或重置安全鎖定屏幕時(例如,由用戶或設(shè)備管理員執(zhí)行此類操作時),系統(tǒng)將不再刪除需要閑時加密的密鑰,但在上述事件期間會刪除需要閑時加密的密鑰。
WLAN 和網(wǎng)絡(luò)連接變更
此版本對 WLAN API 和 Networking API 引入了以下行為變更。
- 現(xiàn)在,您的應(yīng)用只能更改由您創(chuàng)建的 WifiConfiguration 對象的狀態(tài)。系統(tǒng)不允許您修改或刪除由用戶或其他應(yīng)用創(chuàng)建的 WifiConfiguration 對象。
- 在之前的版本中,如果應(yīng)用利用帶有 disableAllOthers=true 設(shè)置的 enableNetwork() 強制設(shè)備連接特定 WLAN 網(wǎng)絡(luò),設(shè)備將會斷開與移動數(shù)據(jù)網(wǎng)絡(luò)等其他網(wǎng)絡(luò)的連接。在此版本中,設(shè)備不再斷開與上述其他網(wǎng)絡(luò)的連接。如果您的應(yīng)用的 targetSdkVersion 為 “20” 或更低,則會固定連接所選 WLAN 網(wǎng)絡(luò)。如果您的應(yīng)用的 targetSdkVersion 為 “21” 或更高,請使用多網(wǎng)絡(luò) API(如 openConnection()、bindSocket() 和新增的 bindProcessToNetwork() 方法)來確保通過所選網(wǎng)絡(luò)傳送網(wǎng)絡(luò)流量。
相機服務(wù)變更
在此版本中,相機服務(wù)中共享資源的訪問模式已從之前的“先到先得”訪問模式更改為高優(yōu)先級進程優(yōu)先的訪問模式。對服務(wù)行為的變更包括:
- 根據(jù)客戶端應(yīng)用進程的“優(yōu)先級”授予對相機子系統(tǒng)資源的訪問權(quán),包括打開和配置相機設(shè)備。帶有對用戶可見 Activity 或前臺 Activity 的應(yīng)用進程一般會被授予較高的優(yōu)先級,從而使相機資源的獲取和使用更加可靠;
- 當(dāng)高優(yōu)先級的應(yīng)用嘗試使用相機時,系統(tǒng)可能會“驅(qū)逐”正在使用相機客戶端的低優(yōu)先級應(yīng)用。在已棄用的 Camera API 中,這會導(dǎo)致系統(tǒng)為被驅(qū)逐的客戶端調(diào)用 onError()。在 Camera2 API 中,這會導(dǎo)致系統(tǒng)為被驅(qū)逐的客戶端調(diào)用 onDisconnected();
- 在配備相應(yīng)相機硬件的設(shè)備上,不同的應(yīng)用進程可同時獨立打開和使用不同的相機設(shè)備。但現(xiàn)在,如果在多進程用例中同時訪問相機會造成任何打開的相機設(shè)備的性能或能力嚴重下降,相機服務(wù)會檢測到這種情況并禁止同時訪問。即使并沒有其他應(yīng)用直接嘗試訪問同一相機設(shè)備,此變更也可能導(dǎo)致低優(yōu)先級客戶端被“驅(qū)逐”。
- 更改當(dāng)前用戶會導(dǎo)致之前用戶帳戶擁有的應(yīng)用內(nèi)活動相機客戶端被驅(qū)逐。對相機的訪問僅限于訪問當(dāng)前設(shè)備用戶擁有的用戶個人資料。舉例來說,這意味著,當(dāng)用戶切換到其他帳戶后,“來賓”帳戶實際上無法讓使用相機子系統(tǒng)的進程保持運行狀態(tài)。
運行時
ART 運行時環(huán)境現(xiàn)在可正確實現(xiàn) newInstance() 方法的訪問規(guī)則。此變更修正了之前版本中 Dalvik 無法正確檢查訪問規(guī)則的問題。如果您的應(yīng)用使用 newInstance() 方法,并且您想重寫訪問檢查,請調(diào)用 setAccessible() 方法(將輸入?yún)?shù)設(shè)置為 true)。如果您的應(yīng)用使用 v7 appcompat 庫或 v7 recyclerview 庫,則您必須更新應(yīng)用以使用這些庫的最新版本。否則,請務(wù)必更新從 XML 引用的任何自定義類,以便能夠訪問它們的類構(gòu)造函數(shù)。
此版本更新了動態(tài)鏈接程序的行為。動態(tài)鏈接程序現(xiàn)在可以識別庫的 soname 與其路徑之間的差異(公開錯誤 6670),并且現(xiàn)在已實現(xiàn)了按 soname 搜索。之前包含錯誤的 DT_NEEDED 條目(通常是開發(fā)計算機文件系統(tǒng)上的絕對路徑)卻仍工作正常的應(yīng)用,如今可能會出現(xiàn)加載失敗。
現(xiàn)已正確實現(xiàn) dlopen(3) RTLD_LOCAL 標(biāo)記。請注意,RTLD_LOCAL 是默認值,因此不顯式使用 RTLD_LOCAL 的 dlopen(3) 調(diào)用將受到影響(除非您的應(yīng)用顯式使用 RTLD_GLOBAL)。使用 RTLD_LOCAL 時,在隨后通過調(diào)用 dlopen(3) 加載的庫中并不能使用這些符號(這與由 DT_NEEDED 條目引用的情況截然不同)。
在之前版本的 Android 上,如果您的應(yīng)用請求系統(tǒng)加載包含文本重定位信息的共享庫,系統(tǒng)會顯示警告,但仍允許加載共享庫。從此版本開始,如果您的應(yīng)用的目標(biāo) SDK 版本為 23 或更高,則系統(tǒng)會拒絕加載該庫。為幫助您檢測庫是否加載失敗,您的應(yīng)用應(yīng)該記錄 dlopen(3) 失敗日志,并在日志中加入 dlerror(3) 調(diào)用返回的問題描述文本。要詳細了解如何處理文本重定位,請參閱此指南。
APK 驗證
該平臺現(xiàn)在執(zhí)行的 APK 驗證更為嚴格。如果在清單中聲明的文件在 APK 中并不存在,該 APK 將被視為已損壞。移除任何內(nèi)容后必須重新簽署 APK。
USB 連接
默認情況下,現(xiàn)在通過 USB 端口進行的設(shè)備連接設(shè)置為僅充電模式。要通過 USB 連接訪問設(shè)備及其內(nèi)容,用戶必須明確地為此類交互授予權(quán)限。如果您的應(yīng)用支持用戶通過 USB 端口與設(shè)備進行交互,請將必須顯式啟用交互考慮在內(nèi)。
Android for Work 變更
此版本包含下列針對 Android for Work 的行為變更:
個人上下文中的工作聯(lián)系人。 Google 撥號器通話記錄現(xiàn)在會在用戶查看通話記錄時顯示工作聯(lián)系人。將 setCrossProfileCallerIdDisabled() 設(shè)置為 true 可在 Google 撥號器通話記錄中隱藏托管配置文件聯(lián)系人。僅當(dāng)您將 setBluetoothContactSharingDisabled() 設(shè)置為 false 時,才可以通過藍牙將工作聯(lián)系人隨個人聯(lián)系人一起顯示給設(shè)備。默認情況下,它設(shè)置為 true。
WLAN 配置刪除 :現(xiàn)在,當(dāng)刪除某個托管配置文件時,將會移除由配置文件所有者添加的 WLAN 配置(例如,通過調(diào)用 addNetwork() 方法添加的配置)。
WLAN 配置鎖定 :如果 WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN 不為零,則用戶無法再修改或刪除任何由活動設(shè)備所有者創(chuàng)建的 WLAN 配置。用戶仍可創(chuàng)建和修改其自己的 WLAN 配置?;顒釉O(shè)備所有者擁有編輯或刪除任何 WLAN 配置(包括并非由其創(chuàng)建的配置)的權(quán)限。
通過添加 Google 帳戶下載設(shè)備規(guī)范控制器 :向托管環(huán)境以外的設(shè)備添加需要通過設(shè)備規(guī)范控制器 (DPC) 應(yīng)用管理的 Google 帳戶時,帳戶添加流程現(xiàn)在會提示用戶安裝相應(yīng)的 WPC。在設(shè)備初始設(shè)置向?qū)е型ㄟ^ Settings > Accounts 添加帳戶時,也會出現(xiàn)此行為。
-
對特定 DevicePolicyManager API 行為的變更 :
調(diào)用 setCameraDisabled() 方法只會影響調(diào)用該方法的用戶的相機;從托管配置文件調(diào)用它不會影響主用戶運行的相機應(yīng)用。
此外,setKeyguardDisabledFeatures() 方法現(xiàn)在除了可供設(shè)備所有者使用外,還可供配置文件所有者使用。
-
配置文件所有者可設(shè)置以下鍵盤鎖限制:
- KEYGUARD_DISABLE_TRUST_AGENTS 和 KEYGUARD_DISABLE_FINGERPRINT,它們影響配置文件上級用戶的鍵盤鎖設(shè)置。
- KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS,它只影響應(yīng)用在托管配置文件中生成的通知。
DevicePolicyManager.createAndInitializeUser() 方法和 DevicePolicyManager.createUser() 方法已棄用。
當(dāng)給定用戶的應(yīng)用在前臺運行時,setScreenCaptureDisabled() 方法現(xiàn)在也會屏蔽輔助結(jié)構(gòu)。
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM 現(xiàn)在默認為 SHA256。出于向后兼容性考慮,仍然支持 SHA1,但未來將會取消該支持。EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM 現(xiàn)在只接受 SHA*256。
Android 6.0(API 級別 23)中曾經(jīng)存在的 Device initializer API 現(xiàn)已刪除
EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS 已刪除,因此 NFC 占位配置無法通過編程解鎖受恢復(fù)出廠設(shè)置保護的設(shè)備
您現(xiàn)在可以使用 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE extra 在對托管設(shè)備進行 NFC 配置期間向設(shè)備所有者應(yīng)用傳遞數(shù)據(jù)。
Android for Work API 針對 M 運行時權(quán)限(包括 Work 配置文件、輔助層及其他內(nèi)容)進行了優(yōu)化。新增的 DevicePolicyManager 權(quán)限 API 不會影響 M 之前版本的應(yīng)用。
當(dāng)用戶退出通過 ACTION_PROVISION_MANAGED_PROFILE 或 ACTION_PROVISION_MANAGED_DEVICE intent 發(fā)起的設(shè)置流程的同步部分時,系統(tǒng)現(xiàn)在會返回 RESULT_CANCELED 結(jié)果代碼。
-
對其他 API 的變更:
- 流量消耗:android.app.usage.NetworkUsageStats 類已重命名為 NetworkStats。
-
對全局設(shè)置的變更:
- 這些設(shè)置不再通過 setGlobalSettings() 進行設(shè)置:
- BLUETOOTH_ON
- DEVELOPMENT_SETTINGS_ENABLED
- MODE_RINGER
- NETWORK_PREFERENCE
- WIFI_ON
- 這些全局設(shè)置現(xiàn)在可通過 setGlobalSettings() 進行設(shè)置:
- WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN
- 這些設(shè)置不再通過 setGlobalSettings() 進行設(shè)置: