1. 程式人生 > >Android各個版本的Feature變更

Android各個版本的Feature變更

Android 8.0 相關變更
        後臺執行限制改動預設只只針對Android8.0及以上,不過使用者可以設定將該改動作用於任何應用。 處於後臺的應用不在允許建立後臺服務了,如果建立會丟擲一個IllegalStateException異常。
        應用進入後臺應用時會有一個時間窗,在該時間窗之內應用的後臺服務還是在執行且可以建立後臺服務,該事件視窗結束之後系統會將後臺服務結束。
        應用在後臺可以在任何時候通過NotificationManager.startServiceInForeground()建立前臺服務,startService() 不能使用,bindService()沒有限制。
        移除了大部分的隱式廣播,只保留了少許隱式廣播。保留的隱式廣播
        主要是去除和應用本身無關的廣播,例如ACTION_PACKAGE_REPLACED。只針對自己應用的廣播還是有效,例如ACTION_MY_PACKAGE_REPLACED。
        官方建議使用 JobScheduler代替以上大部分需求場景。
        後臺位置限制改動針對所有API級別 
處於後臺的應用每隔幾小時接收幾次位置更新。
前臺應用行為不變
官方建議使用前臺服務、 Geofencing API 的元素(例如 GeofencingApi 介面)保證位置實時性。
提醒視窗變更針對Android8.0及以上 
新增一個Window Type,TYPE_APPLICATION_OVERLAY。 
顯示在 
TYPE_PHONE 
TYPE_PRIORITY_PHONE 
TYPE_SYSTEM_ALERT 
TYPE_SYSTEM_OVERLAY 
TYPE_SYSTEM_ERROR 
… 
這些視窗之上。
TYPE_APPLICATION_OVERLAY感覺是google 專門用來給開發者做懸浮窗的。
WebView 
        應用的 WebView 物件將在多程序模式下執行。網頁內容在獨立的程序中處理,此程序與包含應用的程序相隔離,以提高安全性。
        Android 自動填充框架提供對自動填充功能的內建支援,因此有關表單資料的儲存、清楚、獲取方法無效(WebSettings:getSaveFormData() setSaveFormData() 和 WebViewDatabase: clearFormData() hasFormData() )。
        ANDROID_ID 
        對於安裝在執行 Android 8.0 的裝置上的應用,ANDROID_ID 的值現在將根據應用簽署金鑰和使用者確定作用域。應用簽署金鑰、使用者和裝置的每個組合都具有唯一的 ANDROID_ID 值。因此,在相同裝置上執行但具有不同簽署金鑰的應用將不會再看到相同的 Android ID(即使對於同一使用者來說,也是如此)
        許可權申請變更只針對Android8.0及以上 
        之前動態申請許可權的時候,如果使用者同意了某個許可權的申請,系統會將該許可權同組的所有許可權都授予給應用。8.0開始只會授予申請的那個許可權,不過之後如果應用在申請之前授權許可權同組的許可權時,系統會自動授予不會提醒使用者進行授權。
原生庫變動針對 Android 8.0及以上 
        如果原生庫包含任何可寫且可執行的載入程式碼段,則不會再載入原生庫。
        集合的處理變動針對 Android 8.0及以上 
為了利用優化的 List.sort(),在 Android 8.0 中,Collections.sort() 是在 List.sort() 的基礎上實現的。

Android O 除了提供諸多新特性和功能外,還對系統和 API 行為做出了各種變更。本文重點介紹您應該瞭解並在開發應用時加以考慮的一些主要變更。

        其中大部分變更會影響所有應用,而不論應用針對的是何種版本的 Android。不過,有幾項變更僅影響針對 Android O 的應用。為清楚起見,本頁面分為兩個部分:針對所有 API 級別的應用和針對 Android O 的應用。

針對所有 API 級別的應用 
        這些行為變更適用於 在 Android O 平臺上執行的 所有應用,無論這些應用是針對哪個 API 級別構建。所有開發者都應檢視這些變更,並修改其應用以正確支援這些變更(如果適用)。

後臺執行限制 
        Android O 為提高電池壽命而引入的變更之一是,當您的應用進入已快取狀態時,如果沒有活動的元件,系統將解除應用具有的所有喚醒鎖。

Android 後臺位置限制 
        為節約電池電量,保持良好的使用者體驗和確保系統健康執行,在執行 Android O 的裝置上使用後臺應用時,降低了後臺應用接收位置更新的頻率。此行為變更會影響包括 Google Play 服務在內的所有接收位置更新的應用。

此類變更會影響以下 API:

Fused Location Provider (FLP) 
Geofencing 
GNSS Measurements 
Location Manager 
Android O 還對特定方法做出了以下變更:

        NotificationManager.startServiceInForeground() 方法將啟動一個前臺服務。啟動前臺服務的老辦法將不再奏效。 
現在,如果針對 Android O 的應用嘗試在限制服務的情況下使用 startService() 方法,則該方法將引發一個 IllegalStateException。 
為確保您的應用按預期方式執行,請完成以下步驟:

檢視您的應用的邏輯,並確保您使用的是最新的位置 API。 
測試您的應用是否在每個用例中都表現出預期行為。 
考慮使用 Fused Location Provider (FLP) 或地理圍欄來處理依賴於使用者當前位置的用例。 
如需瞭解此類變更的詳細資訊,請參閱後臺位置限制。

藍芽 
        Android O 對 ScanRecord.getBytes() 方法檢索的資料長度做出了以下變更:

        getBytes() 方法對於所接收的位元組數不作任何假定。因此,應用不應受所返回的任何最小或最大位元組數的影響。相反,應用應當計算所返回陣列的長度。 
相容藍芽 5 的裝置返回的資料長度可能會超出之前最大 60 個位元組的限制。 
如果遠端裝置未提供掃描響應,則也可能返回少於 60 個位元組的資料。 
輸入和導航 
        隨著 Android 應用出現在 Chrome 作業系統和平板電腦等其他大尺寸裝置上,我們看到,使用者在 Android 應用中又重新開始使用鍵盤導航。在 Android O 中,我們又再次使用鍵盤作為導航輸入裝置,從而為基於箭頭和標籤的導航構建了一種更可靠並且可預測的模型。

如需瞭解如何在您的應用中改善對鍵盤導航的支援,請閱讀支援鍵盤導航指南。

無障礙功能 
現在,無障礙服務可識別應用的 TextView 物件內部的所有 ClickableSpan 例項。

如需瞭解有關如何讓您的應用更便於訪問的更多資訊,請參閱無障礙功能。

安全性 
Android O 包含以下與安全性有關的變更:

此平臺不再支援 SSLv3。 
在與未正確實現 TLS 協議版本協商的伺服器建立 HTTPS 連線時,HttpsURLConnection 不再嘗試回退到之前的 TLS 協議版本並重試的權宜方法。 
        Android O 將使用安全計算 (SECCOMP) 過濾器來過濾所有應用。允許的系統呼叫列表僅限於通過 bionic 公開的系統呼叫。此外,還提供了其他幾個後向相容的系統呼叫,但我們不建議使用這些系統呼叫。 
現在,您的應用的 WebView 物件將在多程序模式下執行。網頁內容在獨立的程序中處理,此程序與包含應用的程序相隔離,以提高安全性。 
如需瞭解與使用原生庫有關的安全性增強的資訊,請參閱原生庫。 
有關提升應用安全性的其他準則,請參閱面向 Android 開發者的安全性。

隱私性 
Android O 對平臺做出了以下與隱私性有關的變更。

現在,平臺改變了識別符號的處理方式。 
        現在,根據應用(而不是根據使用者)來確定 ANDROID_ID 的值範圍。應用軟體包名稱、簽名、使用者和裝置的每個組合都具有唯一的 ANDROID_ID 值。同一個裝置上執行的兩個應用不再出現 Android ID 相同的情況,因此不可能建立關聯。 
只要軟體包名稱和簽名金鑰相同,在軟體包解除安裝或重新安裝時 ANDROID_ID 的值不會改變。 
如果軟體包簽名金鑰是因為更新而發生改變,那麼,ANDROID_ID 的值不會改變。 
Widevine ID 的範圍根據應用來確定。 
        對於在 OTA 之前安裝的應用,除非解除安裝並重新安裝,否則,ANDROID_ID 的值將保持不變。 
如果您要繼續將 Android ID 用於與裝置繫結的免費試用保護,您可以這麼做。請確保軟體包名稱和簽名相一致。 
要藉助一個簡單的標準系統實現應用獲利,請使用廣告 ID。廣告 ID 是 Google Play 服務針對廣告服務提供的唯一 ID,此 ID 可由使用者重置。 
查詢 net.hostname 系統屬性返回的結果為空。 
您無法再假定 APK 駐留在名稱以 -1 或 -2 結尾的目錄中。應用應使用 sourceDir 獲取此目錄,而不能直接使用目錄格式。 
網路連線和 HTTP(S) 連線 
Android O 對網路連線和 HTTP(S) 連線行為做出了以下變更:

        無正文的 OPTIONS 請求具有 Content-Length: 0 標頭。之前,這些請求沒有 Content-Length 標頭。 
HttpURLConnection 在包含斜線的主機或頒發機構名稱後面附加一條斜線,使包含空路徑的網址規範化。例如,它將 http://example.com 轉化為 http://example.com/。 
通過 ProxySelector.setDefault() 設定的自定義代理選擇器僅針對所請求的網址(架構、主機和埠)。因此,僅可根據這些值選擇代理。傳遞至自定義代理選擇器的網址不包含所請求的網址的路徑、查詢引數或片段。 
URI 不能包含空白標籤。 
        之前,平臺支援一種權宜方法,即允許主機名稱中包含空白標籤,但這是對 URI 的非法使用。此權宜方法只是為了確保與舊版 libcore 相容。開發者如果對 API 使用不當,將會看到一條 ADB 訊息:“URI example..com 的主機名包含空白標籤。此格式不正確,將不被未來的 Android 版本所接受。”Android O 廢除了此權宜方法;系統對格式錯誤的 URI 會返回 null。 
Android O 在實現 HttpsURLConnection 時不會執行不安全的 TLS/SSL 協議版本回退。 
對隧道 HTTP(S) 連線處理進行了如下變更: 
        在通過連線建立隧道 HTTP(S) 連線時,系統會在 Host 行中正確放置埠號 (:443) 並將此資訊傳送至中間伺服器。之前,埠號僅出現在 CONNECT 行中。 
        系統不再將隧道連線請求中的 user-agent和和 proxy-authorization標頭髮送至代理伺服器。 
在建立隧道時,系統不再將隧道 Http(s)URLConnection 中的 proxy-authorization標頭髮送至代理。相反,由系統生成 proxy-authorization標頭,在代理響應初始請求傳送 HTTP 407 後將其傳送至此代理。 
        同樣地,系統不再將 user-agent標頭由隧道連線請求複製到建立隧道的代理請求。相反,庫為此請求生成 user-agent標頭。 
        如果之前執行的 connect() 方法失敗,send(java.net.DatagramPacket) 方法將會引發 SocketException。 
        如果存在內部錯誤,DatagramSocket.connect() 會引發 pendingSocketException。對於 Android O 之前的版本,即使 send() 呼叫成功,後續的 recv() 呼叫也會引發 SocketException。為確保一致性,現在這兩個呼叫均會引發 SocketException。 
在回退到 TCP Echo 協議之前,InetAddress.isReachable() 會嘗試執行 ICMP。 
對於某些遮蔽埠 7 (TCP Echo) 的主機(例如 google.com),如果它們接受 ICMP Echo 協議,現在也許能夠訪問它們。 
對於確實無法訪問的主機,此項變更意味著呼叫需要兩倍的時間才能返回結果。 
記錄未捕獲的異常 
        如果某個應用安裝的 Thread.UncaughtExceptionHandler 未移交給預設的 Thread.UncaughtExceptionHandler,則當出現未捕獲的異常時,系統不會終止應用。從 Android O 開始,在此情況下系統將記錄異常堆疊跟蹤情況;在之前的平臺版本中,系統不會記錄異常堆疊跟蹤情況。

       我們建議,自定義 Thread.UncaughtExceptionHandler 實現始終移交給預設處理程式處理;遵循此建議的應用不受 Android O 此項變更的影響。

集合的處理 
        現在,AbstractCollection.removeAll() 和 AbstractCollection.retainAll() 始終引發 NullPointerException;之前,當集合為空時不會引發 NullPointerException。此項變更使行為符合文件要求。

語言區域和國際化 
        Android 7.0(API 級別 24)引入能指定預設類別語言區域的概念,但是某些 API 在本應使用預設 DISPLAY 類別語言區域時,仍然使用不帶引數的通用 Locale.getDefault() 方法。現在,在 Android O 中,以下方法使用 Locale.getDefault(Category.DISPLAY) 來代替 Locale.getDefault():

Currency.getDisplayName() 
Currency.getSymbol() 
Locale.getDisplayScript() 
當為 Locale 引數指定的 displayScript 值不可用時,Locale.getDisplayScript(Locale) 同樣回退到 Locale.getDefault()。

與語言區域和國際化有關的其他變更如下:

        呼叫 Currency.getDisplayName(null) 會引發 NullPointerException,以與文件規定的行為保持一致。 
        改變了時區名稱的分析方法。之前,Android 裝置使用在啟動時取樣的系統時鐘值,快取用於分析日期時間的時區名稱。因此,如果在啟動時或其他較為罕見的情況下系統時鐘出錯,可能對分析產生負面影響。 
現在,一般情況下,在分析時區名稱時分析邏輯將使用 ICU 和當前系統時鐘值。此項變更可提供更加準確的結果,如果您的應用使用 SimpleDateFormat 等類,此結果可能與之前的 Android 版本不同。 
Android O 將 ICU 的版本更新至版本 58。 
聯絡人提供程式使用情況統計方法的變更 
        在之前版本的 Android 中,聯絡人提供程式元件允許開發者獲取每個聯絡人的使用情況資料。此使用情況資料揭示了與某個聯絡人相關聯的每個電子郵件地址和每個電話號碼的資訊,包括與該聯絡人聯絡的次數以及上次聯絡該聯絡人的時間。請求 READ_CONTACTS 許可權的應用可以讀取此資料。

        如果應用請求 READ_CONTACTS 許可權,它們仍可以讀取此資料。從 Android O 開始,使用情況資料查詢會返回近似值,而不是精確值。不過,Android 系統內部仍然會保留精確值,因此,此變更不會影響 auto-complete API。

此行為變更會影響以下查詢引數:

TIMES_CONTACTED 
TIMES_USED 
LAST_TIME_CONTACTED 
LAST_TIME_USED 
應用快捷鍵 
Android O 對應用快捷鍵做出了以下變更:

        com.android.launcher.action.INSTALL_SHORTCUT 廣播不再會對您的應用有任何影響,因為它現在是私有的隱式廣播。相反,    您應使用 ShortcutManager 類中的 requestPinShortcut() 方法建立應用快捷鍵。 
現在,ACTION_CREATE_SHORTCUT Intent 可以建立可使用 ShortcutManager 類進行管理的應用快捷鍵。此 Intent 還可以建立不與 ShortcutManager 互動的舊版啟動器快捷鍵。在以前,此 Intent 只能建立舊版啟動器快捷鍵。 
        現在,使用 requestPinShortcut() 建立的快捷鍵和在處理 ACTION_CREATE_SHORTCUT Intent 的 Activity 中建立的快捷鍵均已轉換為功能齊全的應用快捷鍵。因此,應用現在可以使用 ShortcutManager 中的方法來更新這些快捷鍵。 
舊版快捷鍵仍然保留了它們在舊版 Android 中的功能,但您必須在應用中手動將它們轉換成應用快捷鍵。 
如需瞭解有關應用快捷鍵變更的更多資訊,請參閱固定快捷鍵和小部件預覽功能指南。

提醒視窗 
如果應用使用 SYSTEM_ALERT_WINDOW 許可權並且嘗試使用以下視窗型別之一來在其他應用和系統視窗上方顯示提醒視窗:

TYPE_PHONE 
TYPE_PRIORITY_PHONE 
TYPE_SYSTEM_ALERT 
TYPE_SYSTEM_OVERLAY 
TYPE_SYSTEM_ERROR 
…那麼,這些視窗將始終顯示在使用 TYPE_APPLICATION_OVERLAY 視窗型別的視窗下方。如果應用針對的是 Android O,則應用會使用 TYPE_APPLICATION_OVERLAY 視窗型別來顯示提醒視窗。

如需瞭解詳細資訊,請參閱針對 Android O 的應用的行為變更內的提醒視窗的常用視窗型別部分。

企業中的 Android 
Android O 包含會影響企業應用的變更。如果您正在為企業構建應用,包括 DPC(裝置規範控制器),您應查閱企業中的 Android 頁面中介紹的變更,並相應修改您的應用。

針對 Android O 的應用 
        這些行為變更專門應用於針對 O 平臺或更高平臺版本的應用。針對 Android O 或更高平臺版本進行編譯,或將 targetSdkVersion 設為 Android O 或更高版本的應用開發者必須修改其應用以正確支援這些行為(如果適用)。

後臺執行限制 
為提高裝置效能,系統會限制未在前臺執行的應用的某些行為。具體而言:

現在,在後臺執行的應用對後臺服務的訪問受到限制。 
應用無法使用其清單註冊大部分隱式廣播(即,並非專門針對此應用的廣播)。 
如需瞭解詳細資訊,請參閱後臺執行限制。

安全性 
        如果您的應用的網路安全性配置選擇退出對明文流量的支援,那麼,您的應用的 WebView 物件無法通過 HTTP 訪問網站。每個 WebView 物件必須轉而使用 HTTPS。

有關提升應用安全性的其他準則,請參閱面向 Android 開發者的安全性。

隱私性 
以下變更影響 Android O 的隱私性。

        系統屬性 net.dns1、net.dns2、net.dns3 和 net.dns4 不再可用,此項變更可加強平臺的隱私性。 
要獲取 DNS 伺服器之類的網路連線資訊,具有 ACCESS_NETWORK_STATE 許可權的應用可以註冊 NetworkRequest 或 NetworkCallback 物件。這些類在 Android 5.0(API 級別 21)及更高版本中提供。 
從 Android O 開始,不再支援 Build.SERIAL,此欄位將返回一個未定義的值。需要知道硬體序列號的應用應改為使用新的 Build.getSerial() 方法,該方法要求具有 READ_PHONE_STATE 許可權。 
        LauncherApps API 不再允許託管配置檔案應用獲取有關主配置檔案的資訊。當某個使用者在託管配置檔案中時,LauncherApps API 的行為就像同一配置檔案組的其他配置檔案中未安裝任何應用一樣。和之前一樣,嘗試訪問無關聯的配置檔案會引發 SecurityExceptions。 
許可權 
        在 Android O 之前,如果應用在執行時請求許可權並且被授予該許可權,系統會錯誤地將屬於同一許可權組並且在清單中註冊的其他許可權也一起授予應用。

        對於針對 Android O 的應用,此行為已被糾正。系統只會授予應用明確請求的許可權。然而,一旦使用者為應用授予某個許可權,則所有後續對該許可權組中許可權的請求都將被自動批准。

        例如,假設某個應用在其清單中列出 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE。應用請求 READ_EXTERNAL_STORAGE,並且使用者授予了該許可權。如果該應用針對的是 API 級別 24 或更低級別,系統還會同時授予 WRITE_EXTERNAL_STORAGE,因為該許可權也屬於同一 STORAGE 許可權組並且也在清單中註冊過。如果該應用針對的是 Android O,則系統此時僅會授予 READ_EXTERNAL_STORAGE;不過,如果該應用後來又請求 WRITE_EXTERNAL_STORAGE,則系統會立即授予該許可權,而不會提示使用者。

媒體 
        框架會執行音訊閃避。進行 AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK 時,應用不會失去焦點。新的 API 適用於需要暫停而不是閃避的應用。不過,Android O 中未提供此行為。 
當用戶打電話時,活動的媒體流將在通話期間靜音。 
音訊流型別應僅用於音量控制;所有其他流型別的使用(例如 AudioTrack 建構函式)仍有效,但系統會將其作為錯誤記錄下來。 
        所有與音訊相關的 API 均使用 AudioAttributes 來描述音訊播放用例。 
        使用 AudioTrack 時,如果應用請求了足夠大的音訊緩衝區,則框架將嘗試使用深度緩衝區輸出(如果可用)。 
原生庫 
        在針對 Android O 的應用中,如果原生庫包含任何可寫且可執行的載入程式碼段,則不會再載入原生庫。倘若某些應用的原生庫包含不正確的載入程式碼段,則此變更可能會導致這些應用停止工作。這是一種安全加強措施。

如需瞭解詳細資訊,請參閱可寫且可執行的程式碼段。

        與早期的開發者預覽版相同,Android O 還有助於更輕鬆地發現所有與連結器有關的問題。連結器的變更繫結到應用的目標 API 級別。如果應用的目標 API 級別發生連結器變更,則該應用無法載入該庫。如果您的目標 API 級別低於發生連結器變更的 API 級別,則 logcat 會顯示一條警告訊息。在預覽版期間,與連結器有關的問題不僅會顯示在 logcat 中,也會以 toast 的形式顯示。對於特定的 API 級別,警告可能會變成錯誤,此變更有助於提前發現此類問題。

集合的處理 
        在 Android O 中,Collections.sort() 是在 List.sort() 的基礎上實現的。在 Android 7.x(API 級別 24 和 25)中,則恰恰相反。在過去,List.sort() 的預設實現會呼叫 Collections.sort()。

此項變更使 Collections.sort() 可以利用優化的 List.sort() 實現,但具有以下限制:

        List.sort() 的實現不能呼叫 Collections.sort(),因為這會導致堆疊因無限遞迴而溢位。相反,如果您需要 List 實現的預設行為,應避免重寫 sort()。 
如果父類以不適當的方法實現 sort() ,通常最好使用在 List.toArray()、Arrays.sort() 和 ListIterator.set() 的基礎上構建的實現重寫 List.sort()。例如:

@Override
public void sort(Comparator<? super E> c) {
  Object[] elements = toArray();
  Arrays.sort(elements, c);
  ListIterator<E> iterator = (ListIterator<Object>) listIterator();
  for (Object element : elements) {
    iterator.next();
    iterator.set((E) element);
  }
}

在大多數情況下,您也可以使用根據 API 級別委託給其他預設實現的實現重寫 List.sort()。例如:

@Override
public void sort(Comparator<? super E> comparator) {
  if (Build.VERSION.SDK_INT <= 25) {
    Collections.sort(this);
  } else {
    super.sort(comparator);
  }
}

        如果您選擇後者只是因為您希望開發一種適用於所有 API 級別的 sort() 方法,可以考慮賦予其一個唯一的名稱,例如 sortCompat(),而不是重寫 sort()。 
        現在,Collections.sort() 只是對呼叫 sort() 的 List 實現進行的一項結構性修改。例如,在 Android O 之前的平臺版本中,如果通過呼叫 List.sort() 進行排序,則當迭代處理 ArrayList 以及在迭代過程中呼叫 sort() 時,會引發 ConcurrentModificationException。而 Collections.sort() 則不會引發異常。 
此項變更使平臺行為更加一致:現在,兩種方法都會引發 ConcurrentModificationException。 
帳號訪問和可檢測性 
        除非身份驗證器擁有使用者帳號或使用者授予訪問許可權,否則,應用將無法再訪問使用者帳號。僅擁有 GET_ACCOUNTS 許可權尚不足以訪問使用者帳號。要獲得帳號訪問許可權,應用應使用 AccountManager.newChooseAccountIntent() 或特定於身份驗證器的方法。獲得帳號訪問許可權後,應用可以呼叫 AccountManager.getAccounts() 來訪問帳號。

        Android O 已棄用 LOGIN_ACCOUNTS_CHANGED_ACTION。相反,應用在執行時應使用 addOnAccountsUpdatedListener() 獲取帳號更新資訊。

        有關新增 API 和增加的帳號訪問和可檢測性方法的資訊,請參閱此文件的“新增 API”部分中的帳號訪問和可檢測性。

提醒視窗 
        使用 SYSTEM_ALERT_WINDOW 許可權的應用無法再使用以下視窗型別來在其他應用和系統視窗上方顯示提醒視窗:

TYPE_PHONE
TYPE_PRIORITY_PHONE
TYPE_SYSTEM_ALERT
TYPE_SYSTEM_OVERLAY
TYPE_SYSTEM_ERROR

相反,應用必須使用名為 TYPE_APPLICATION_OVERLAY 的新視窗型別。

使用 TYPE_APPLICATION_OVERLAY 視窗型別顯示應用的提醒視窗時,請記住新視窗型別的以下特性:

        應用的提醒視窗始終顯示在狀態列和輸入法等關鍵系統視窗的下面。 
        系統可以移動使用 TYPE_APPLICATION_OVERLAY 視窗型別的視窗或調整其大小,以改善螢幕顯示效果。 
通過開啟通知欄,使用者可以訪問設定來阻止應用顯示使用 TYPE_APPLICATION_OVERLAY 視窗型別顯示的提醒視窗。 
內容變更通知 
Android O 更改了 ContentResolver.notifyChange() 和 registerContentObserver(Uri, boolean, ContentObserver) 在面向針對 Android O 的應用中的行為方式。

現在,這些 API 需要在所有 URI 中為頒發機構定義一個有效的 ContentProvider。使用相關許可權定義一個有效的 ContentProvider 可幫助您的應用防範來自惡意應用的內容變更,並防止將可能的私密資料洩露給惡意應用。
 

Android 6.0 變更

執行時許可權
低電耗模式和應用待機模式
取消支援 Apache HTTP 客戶端
BoringSSL
硬體識別符號訪問權
通知
音訊管理器變更
文字選擇
瀏覽器書籤變更
Android 金鑰庫變更
WLAN 和網路連線變更
相機服務變更
執行時
APK 驗證
USB 連線
Android for Work 變更
API 差異
API 級別 22 至 23 »

        Android 6.0(API 級別 23)除了提供諸多新特性和功能外,還對系統和 API 行為做出了各種變更。本文重點介紹您應該瞭解並在開發應用時加以考慮的一些主要變更。

如果您之前釋出過 Android 應用,請注意您的應用可能受到這些平臺變更的影響。

執行時許可權
        此版本引入了一種新的許可權模式,如今,使用者可直接在執行時管理應用許可權。這種模式讓使用者能夠更好地瞭解和控制權限,同時為應用開發者精簡了安裝和自動更新過程。使用者可為所安裝的各個應用分別授予或撤銷許可權。

        對於以 Android 6.0(API 級別 23)或更高版本為目標平臺的應用,請務必在執行時檢查和請求許可權。要確定您的應用是否已被授予許可權,請呼叫新增的 checkSelfPermission() 方法。要請求許可權,請呼叫新增的 requestPermissions() 方法。即使您的應用並不以 Android 6.0(API 級別 23)為目標平臺,您也應該在新許可權模式下測試您的應用。

        如需瞭解有關在您的應用中支援新許可權模式的詳情,請參閱使用系統許可權。如需瞭解有關如何評估新模式對應用的影響的提示,請參閱許可權最佳做法。

低電耗模式和應用待機模式
        此版本引入了針對空閒裝置和應用的最新節能優化技術。這些功能會影響所有應用,因此請務必在這些新模式下測試您的應用。

        低電耗模式:如果使用者拔下裝置的電源插頭,並在螢幕關閉後的一段時間內使其保持不活動狀態,裝置會進入低電耗模式,在該模式下裝置會嘗試讓系統保持休眠狀態。在該模式下,裝置會定期短時間恢復正常工作,以便進行應用同步,還可讓系統執行任何掛起的操作。
        應用待機模式:應用待機模式允許系統判定應用在使用者未主動使用它時處於空閒狀態。當用戶有一段時間未觸控應用時,系統便會作出此判定。如果拔下了裝置電源插頭,系統會為其視為空閒的應用停用網路訪問以及暫停同步和作業。
要詳細瞭解這些節能變更,請參閱對低電耗模式和應用待機模式進行鍼對性優化。

取消支援 Apache HTTP 客戶端
        Android 6.0 版移除了對 Apache HTTP 客戶端的支援。如果您的應用使用該客戶端,並以 Android 2.3(API 級別 9)或更高版本為目標平臺,請改用 HttpURLConnection 類。此 API 效率更高,因為它可以通過透明壓縮和響應快取減少網路使用,並可最大限度降低耗電量。要繼續使用 Apache HTTP API,您必須先在 build.gradle 檔案中宣告以下編譯時依賴項:

android {
    useLibrary 'org.apache.http.legacy'
}
BoringSSL
        Android 正在從使用 OpenSSL 庫轉向使用 BoringSSL 庫。如果您要在應用中使用 Android NDK,請勿連結到並非 NDK API 組成部分的加密庫,如 libcrypto.so 和 libssl.so。這些庫並非公共 API,可能會在不同版本和裝置上毫無徵兆地發生變化或出現故障。此外,您還可能讓自己暴露在安全漏洞的風險之下。請改為修改原生程式碼,以通過 JNI 呼叫 Java 加密 API,或靜態連結到您選擇的加密庫。

硬體識別符號訪問權
        為給使用者提供更嚴格的資料保護,從此版本開始,對於使用 WLAN API 和 Bluetooth API 的應用,Android 移除了對裝置本地硬體識別符號的程式設計訪問權。WifiInfo.getMacAddress() 方法和 BluetoothAdapter.getAddress() 方法現在會返回常量值 02:00:00:00:00:00。

現在,要通過藍芽和 WLAN 掃描訪問附近外部裝置的硬體識別符號,您的應用必須擁有 ACCESS_FINE_LOCATION 或 ACCESS_COARSE_LOCATION 許可權。

WifiManager.getScanResults()
BluetoothDevice.ACTION_FOUND
BluetoothLeScanner.startScan()
注:當執行 Android 6.0(API 級別 23)的裝置發起後臺 WLAN 或藍芽掃描時,在外部裝置看來,該操作的發起來源是一個隨機化 MAC 地址。

通知
        此版本移除了 Notification.setLatestEventInfo() 方法。請改用 Notification.Builder 類來構建通知。要重複更新通知,請重複使用 Notification.Builder 例項。呼叫 build() 方法可獲取更新後的 Notification 例項。

adb shell dumpsys notification 命令不再列印輸出您的通知文字。請改用 adb shell dumpsys notification --noredact 命令列印輸出 notification 物件中的文字。

音訊管理器變更
        不再支援通過 AudioManager 類直接設定音量或將特定音訊流靜音。setStreamSolo() 方法已棄用,您應該改為呼叫 requestAudioFocus() 方法。類似地,setStreamMute() 方法也已棄用,請改為呼叫 adjustStreamVolume() 方法並傳入方向值 ADJUST_MUTE 或 ADJUST_UNMUTE。

文字選擇

        現在,當用戶在您的應用中選擇文字時,您可以在一個浮動工具欄中顯示“剪下”、“複製”和“貼上”等文字選擇操作。其在使用者互動實現上與為單個檢視啟用上下文操作模式中所述的上下文操作欄類似。

要實現可用於文字選擇的浮動工具欄,請在您的現有應用中做出以下更改:

        在 View 物件或 Activity 物件中,將 ActionMode 呼叫從 startActionMode(Callback)更改為 startActionMode(Callback, ActionMode.TYPE_FLOATING)。改為使用 ActionMode.Callback 的現有實現擴充套件 ActionMode.Callback2。
替代 onGetContentRect() 方法,用於提供 Rect 內容物件(如文字選擇矩形)在檢視中的座標。
如果矩形的定位不再有效,並且這是唯一需要宣告為無效的元素,請呼叫 invalidateContentRect() 方法。
        請注意,如果您使用 Android 支援庫 22.2 修訂版,浮動工具欄不向後相容,預設情況下 appcompat 會獲得對 ActionMode 物件的控制權。這會禁止顯示浮動工具欄。要在 ActionMode 中啟用 AppCompatActivity 支援,請呼叫 getDelegate(),然後對返回的 setHandleNativeActionModesEnabled() 物件呼叫 AppCompatDelegate,並將輸入引數設定為 false。此呼叫會將 ActionMode 物件的控制權交還給框架。在執行 Android 6.0(API 級別 23)的裝置上,框架可以支援 ActionBar 模式或浮動工具欄模式;而在執行 Android 5.1(API 級別 22)或之前版本的裝置上,框架僅支援 ActionBar 模式。

瀏覽器書籤變更
        此版本移除了對全域性書籤的支援。android.provider.Browser.getAllBookmarks() 和 android.provider.Browser.saveBookmark() 方法現已移除。同樣,READ_HISTORY_BOOKMARKS 許可權和 WRITE_HISTORY_BOOKMARKS 許可權也已移除。如果您的應用以 Android 6.0(API 級別 23)或更高版本為目標平臺,請勿從全域性提供程式訪問書籤或使用書籤許可權。您的應用應改為在內部儲存書籤資料。

Android 金鑰庫變更
        從此版本開始,Android 金鑰庫提供程式不再支援 DSA。但仍支援 ECDSA。

        停用或重置安全鎖定螢幕時(例如,由使用者或裝置管理員執行此類操作時),系統將不再刪除需要閒時加密的金鑰,但在上述事件期間會刪除需要閒時加密的金鑰。

WLAN 和網路連線變更
此版本對 WLAN API 和 Networking API 引入了以下行為變更。

        現在,您的應用只能更改由您建立的 WifiConfiguration 物件的狀態。系統不允許您修改或刪除由使用者或其他應用建立的 WifiConfiguration 物件。
        在之前的版本中,如果應用利用帶有 disableAllOthers=true 設定的 enableNetwork() 強制裝置連線特定 WLAN 網路,裝置將會斷開與移動資料網路等其他網路的連線。在此版本中,裝置不再斷開與上述其他網路的連線。如果您的應用的 targetSdkVersion 為 “20” 或更低,則會固定連線所選 WLAN 網路。如果您的應用的 targetSdkVersion 為 “21” 或更高,請使用多網路 API(如 openConnection()、bindSocket() 和新增的 bindProcessToNetwork() 方法)來確保通過所選網路傳送網路流量。
相機服務變更
        在此版本中,相機服務中共享資源的訪問模式已從之前的“先到先得”訪問模式更改為高優先順序程序優先的訪問模式。對服務行為的變更包括:

        根據客戶端應用程序的“優先順序”授予對相機子系統資源的訪問權,包括開啟和配置相機裝置。帶有對使用者可見 Activity 或前臺 Activity 的應用程序一般會被授予較高的優先順序,從而使相機資源的獲取和使用更加可靠;
        當高優先順序的應用嘗試使用相機時,系統可能會“驅逐”正在使用相機客戶端的低優先順序應用。在已棄用的 Camera API 中,這會導致系統為被驅逐的客戶端呼叫 onError()。在 Camera2 API 中,這會導致系統為被驅逐的客戶端呼叫 onDisconnected();
在配備相應相機硬體的裝置上,不同的應用程序可同時獨立開啟和使用不同的相機裝置。但現在,如果在多程序用例中同時訪問相機會造成任何開啟的相機裝置的效能或能力嚴重下降,相機服務會檢測到這種情況並禁止同時訪問。即使並沒有其他應用直接嘗試訪問同一相機裝置,此變更也可能導致低優先順序客戶端被“驅逐”。
        更改當前使用者會導致之前使用者帳戶擁有的應用內活動相機客戶端被驅逐。對相機的訪問僅限於訪問當前裝置使用者擁有的使用者個人資料。舉例來說,這意味著,當用戶切換到其他帳戶後,“來賓”帳戶實際上無法讓使用相機子系統的程序保持執行狀態。
執行時
        ART 執行時環境現在可正確實現 newInstance() 方法的訪問規則。此變更修正了之前版本中 Dalvik 無法正確檢查訪問規則的問題。如果您的應用使用 newInstance() 方法,並且您想重寫訪問檢查,請呼叫 setAccessible() 方法(將輸入引數設定為 true)。如果您的應用使用 v7 appcompat 庫或 v7 recyclerview 庫,則您必須更新應用以使用這些庫的最新版本。否則,請務必更新從 XML 引用的任何自定義類,以便能夠訪問它們的類建構函式。

        此版本更新了動態連結程式的行為。動態連結程式現在可以識別庫的 soname 與其路徑之間的差異(公開錯誤 6670),並且現在已實現了按 soname 搜尋。之前包含錯誤的 DT_NEEDED 條目(通常是開發計算機檔案系統上的絕對路徑)卻仍工作正常的應用,如今可能會出現載入失敗。

        現已正確實現 dlopen(3) RTLD_LOCAL 標記。請注意,RTLD_LOCAL 是預設值,因此不顯式使用 RTLD_LOCAL 的 dlopen(3) 呼叫將受到影響(除非您的應用顯式使用 RTLD_GLOBAL)。使用 RTLD_LOCAL 時,在隨後通過呼叫 dlopen(3) 載入的庫中並不能使用這些符號(這與由 DT_NEEDED 條目引用的情況截然不同)。

        在之前版本的 Android 上,如果您的應用請求系統載入包含文字重定位資訊的共享庫,系統會顯示警告,但仍允許載入共享庫。從此版本開始,如果您的應用的目標 SDK 版本為 23 或更高,則系統會拒絕載入該庫。為幫助您檢測庫是否載入失敗,您的應用應該記錄 dlopen(3) 失敗日誌,並在日誌中加入 dlerror(3) 呼叫返回的問題描述文字。要詳細瞭解如何處理文字重定位,請參閱此指南。

APK 驗證
        該平臺現在執行的 APK 驗證更為嚴格。如果在清單中宣告的檔案在 APK 中並不存在,該 APK 將被視為已損壞。移除任何內容後必須重新簽署 APK。

USB 連線
        預設情況下,現在通過 USB 埠進行的裝置連線設定為僅充電模式。要通過 USB 連線訪問裝置及其內容,使用者必須明確地為此類互動授予許可權。如果您的應用支援使用者通過 USB 埠與裝置進行互動,請將必須顯式啟用互動考慮在內。

Android for Work 變更
此版本包含下列針對 Android for Work 的行為變更:

個人上下文中的工作聯絡人。Google 撥號器通話記錄現在會在使用者檢視通話記錄時顯示工作聯絡人。將 setCrossProfileCallerIdDisabled() 設定為 true 可在 Google 撥號器通話記錄中隱藏託管配置檔案聯絡人。僅當您將 setBluetoothContactSharingDisabled() 設定為 false 時,才可以通過藍芽將工作聯絡人隨個人聯絡人一起顯示給裝置。預設情況下,它設定為 true。
        WLAN 配置刪除:現在,當刪除某個託管配置檔案時,將會移除由配置檔案所有者新增的 WLAN 配置(例如,通過呼叫 addNetwork() 方法新增的配置)。
        WLAN 配置鎖定:如果 WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN 不為零,則使用者無法再修改或刪除任何由活動裝置所有者建立的 WLAN 配置。使用者仍可建立和修改其自己的 WLAN 配置。活動裝置所有者擁有編輯或刪除任何 WLAN 配置(包括並非由其建立的配置)的許可權。
        通過新增 Google 帳戶下載裝置規範控制器:向託管環境以外的裝置新增需要通過裝置規範控制器 (DPC) 應用管理的 Google 帳戶時,帳戶新增流程現在會提示使用者安裝相應的 WPC。在裝置初始設定嚮導中通過 Settings > Accounts 新增帳戶時,也會出現此行為。
對特定 DevicePolicyManager API 行為的變更:
        呼叫 setCameraDisabled() 方法只會影響呼叫該方法的使用者的相機;從託管配置檔案呼叫它不會影響主使用者執行的相機應用。此外,setKeyguardDisabledFeatures() 方法現在除了可供裝置所有者使用外,還可供配置檔案所有者使用。
配置檔案所有者可設定以下鍵盤鎖限制:
KEYGUARD_DISABLE_TRUST_AGENTS 和 KEYGUARD_DISABLE_FINGERPRINT,它們影響配置檔案上級使用者的鍵盤鎖設定。
KEYGUARD_DISABLE_UNREDACTED_NOTIFICATIONS,它隻影響應用在託管配置檔案中生成的通知。
DevicePolicyManager.createAndInitializeUser() 方法和 DevicePolicyManager.createUser() 方法已棄用。
當給定使用者的應用在前臺執行時,setScreenCaptureDisabled() 方法現在也會遮蔽輔助結構。
EXTRA_PROVISIONING_DEVICE_ADMIN_PACKAGE_CHECKSUM 現在預設為 SHA-256。出於向後相容性考慮,仍然支援 SHA-1,但未來將會取消該支援。EXTRA_PROVISIONING_DEVICE_ADMIN_SIGNATURE_CHECKSUM 現在只接受 SHA-256。
Android 6.0(API 級別 23)中曾經存在的 Device initializer API 現已刪除
EXTRA_PROVISIONING_RESET_PROTECTION_PARAMETERS 已刪除,因此 NFC 佔位配置無法通過程式設計解鎖受恢復出廠設定保護的裝置
您現在可以使用 EXTRA_PROVISIONING_ADMIN_EXTRAS_BUNDLE extra 在對託管裝置進行 NFC 配置期間向裝置所有者應用傳遞資料。
Android for Work API 針對 M 執行時許可權(包括 Work 配置檔案、輔助層及其他內容)進行了優化。新增的 DevicePolicyManager 許可權 API 不會影響 M 之前版本的應用。
當用戶退出通過 ACTION_PROVISION_MANAGED_PROFILE 或 ACTION_PROVISION_MANAGED_DEVICE intent 發起的設定流程的同步部分時,系統現在會返回 RESULT_CANCELED 結果程式碼。
對其他 API 的變更:
流量消耗:android.app.usage.NetworkUsageStats 類已重新命名為 NetworkStats。
對全域性設定的變更:
這些設定不再通過 setGlobalSettings() 進行設定:
BLUETOOTH_ON
DEVELOPMENT_SETTINGS_ENABLED
MODE_RINGER
NETWORK_PREFERENCE
WIFI_ON
這些全域性設定現在可通過 setGlobalSettings() 進行設定:
WIFI_DEVICE_OWNER_CONFIGS_LOCKDOWN