Android O (8.0) 新特性介紹

Android O 功能和 API

(文章內容均來Google開發者官網,有需要可自行翻牆查看更多資料)

Android O 爲用戶和開發者引入多種新功能。本文重點介紹面向開發者的新功能。請務必查閱 Android O 行爲變更以瞭解平臺變更可能影響您的應用的領域。

通知

在 Android O 中,我們已重新設計通知,以便爲管理通知行爲和設置提供更輕鬆和更統一的方式。這些變更包括:
  通知渠道:Android O 引入了通知渠道,其允許您爲要顯示的每種通知類型創建用戶可自定義的渠道。用戶界面將通知渠道稱之爲通知類別。要了解如何實現通知渠道的信息,請參閱通知渠道指南。
  休眠:用戶可以將通知置於休眠狀態,以便稍後重新顯示它。重新顯示時通知的重要程度與首次顯示時相同。應用可以移除或更新已休眠的通知,但更新休眠的通知並不會使其重新顯示。
  通知超時:現在,使用 Notification.Builder.setTimeout() 創建通知時您可以設置超時。您可以使用此方法指定一個持續時間,過了該持續時間後取消通知。如果需要,您可以在指定的超時持續時間之前取消通知。
  通知清除:系統現在可區分通知是由用戶清除,還是由應用移除。要查看清除通知的方式,您應實現 NotificationListenerService 類的新 onNotificationRemoved() 方法。
  背景顏色:您現在可以設置和啓用通知的背景顏色。只能在用戶必須一眼就能看到的持續任務的通知中使用此功能。例如,您可以爲與駕車路線或正在進行的通話有關的通知設置背景顏色。您還可以使用 Notification.Builder.setColor() 設置所需的背景顏色。這樣做將允許您使用 Notification.Builder.setColorized() 啓用通知的背景顏色設置。
  消息樣式:現在,使用 MessagingStyle 類的通知可在其摺疊形式中顯示更多內容。對於與消息有關的通知,您應使用 MessagingStyle 類。您還可以使用新的 addHistoricMessage() 方法,通過向與消息相關的通知添加歷史消息爲會話提供上下文。

Android N 中的通知欄
            圖 1. Android N(5.0) 中的通知欄。
Android O 中通知的嵌入式控件
           圖 2. Android O(8.0) 中通知欄的嵌入式控件。

自動填充框架

帳號創建、登錄和信用卡交易需要時間並且容易出錯。在使用要求執行此類重複性任務的應用時,用戶很容易遭受挫折。

Android O 通過引入自動填充框架,簡化了登錄和信用卡表單之類表單的填寫工作。在用戶選擇接受自動填充之後,新老應用都可使用自動填充框架。

您可以採取某些措施,優化您的應用使用此框架的方式。如需瞭解詳細信息,請參閱自動填充框架概覽。

畫中畫模式

Android O 允許以畫中畫 (PIP) 模式啓動 Activity。PIP 是一種特殊的多窗口模式,最常用於視頻播放。目前,PIP 模式可用於 Android TV,而 Android O 則讓該功能可進一步用於其他 Android 設備。

當某個 Activity 處於 PIP 模式時,它會處於暫停狀態,但仍應繼續顯示內容。因此,您應確保您的應用在 onPause() 處理程序中進行處理時不會暫停播放。相反,您應在 onStop() 中暫停播放視頻,並在 onStart() 中繼續播放。如需瞭解詳細信息,請參閱多窗口生命週期。

要指定您的 Activity 可以使用 PIP 模式,請在清單中將 android:supportsPictureInPicture 設置爲 true。(從 Android O 開始,如果您打算在 Android TV 或其他 Android 設備上支持 PIP 模式,則無需將 android:resizeableActivity 設置爲 true;只有在您的 Activity 支持其他多窗口模式時,才需要設置 android:resizeableActivity。)
API 變更

Android O 引入一種新的對象 android.app.PictureInPictureArgs,您可以將該對象傳遞給 PIP 方法來指定某個 Activity 在其處於 PIP 模式時的行爲。此對象還指定了各種屬性,例如 Activity 的首選縱橫比。

現在,在添加畫中畫中介紹的現有 PIP 方法可用於所有 Android 設備,而不僅限於 Android TV。此外,Android O 還提供以下方法來支持 PIP 模式:

Activity.enterPictureInPictureMode(PictureInPictureArgs args):將 Activity 置於畫中畫模式。Activity 的縱橫比和其他配置設置均由 args 指定。如果 args 中的任何字段爲空,系統將使用您上次調用 Activity.setPictureInPictureArgs() 時所設置的值。

指定的 Activity 被置於屏幕的一角,屏幕剩餘部分則被屏幕之前顯示的上一 Activity 所填滿。進入 PIP 模式的 Activity 將進入暫停狀態,但仍保持已啓動狀態。如果用戶點按此 PIP Activity,系統將顯示一個菜單供用戶操作,而在 Activity 處於 PIP 狀態期間,不會理會任何觸摸事件。
Activity.setPictureInPictureArgs() 更新 Activity 的 PIP 配置設置。如果 Activity 目前處於 PIP 模式,則會更新此設置;如果 Activity 的縱橫比發生變化,這非常有用。如果 Activity 不處於 PIP 模式,則會使用這些配置設置,而不會考慮您調用的 enterPictureInPictureMode() 方法。

處理字體

Android O 推出一項新功能,即 XML 中的字體,允許您使用字體作爲資源。這意味着,不再需要以資產的形式捆綁字體。字體在 R 文件中編譯,並且作爲一種資源,可自動用於系統。然後,您可以利用一種新的資源類型 font 來訪問這些字體。Android O 還提供了一種機制,可用來檢索與系統字體有關的信息並提供文件描述符。如需瞭解有關以資源形式使用字體以及檢索系統字體有關的詳細信息,請參閱處理字體。
自適應圖標

Android O 引入自適應啓動器圖標。自適應圖標支持視覺效果,可在不同設備型號上顯示爲各種不同的形狀。要了解如何創建自適應圖標,請參閱自適應圖標預覽功能指南。
顏色管理

圖像應用的 Android 開發者現在可以利用支持廣色域彩色顯示的新設備。要顯示廣色域圖像,應用需要在其清單(每個 Activity)中啓用一個標誌,並加載具有嵌入的廣域彩色配置文件(AdobeRGB、Pro Photo RGB、DCI-P3 等)的位圖。

WLAN 感知

Android O 新增了對 WLAN 感知的支持,此技術基於周邊感知聯網 (NAN) 規範。在具有相應 WLAN 感知硬件的設備上,應用和附近設備可以通過 WLAN 進行搜索和通信,無需依賴互聯網接入點。我們正在與硬件合作伙伴合作,以儘快將 WLAN 感知技術應用於設備。有關如何將 WLAN 感知集成到您的應用中的詳細信息,請參閱 WLAN 感知。
配套設備配對

在嘗試通過藍牙、BLE 和 WLAN 與配套設備配對時,Android O 提供的 API 允許您自定義配對請求對話框。如需瞭解詳細信息,請參閱配套設備配對。

如需瞭解有關在 Android 上使用藍牙的詳細信息,請參閱藍牙指南。有關對藍牙所作的特定於 Android O 的變更,請參閱 Android O 行爲變更頁面的藍牙部分。
WebView API

Android O 提供多種 API,幫助您管理在應用中顯示網頁內容的 WebView 對象。這些 API 可增強應用的穩定性和安全性,它們包括:

Version API
Google SafeBrowsing API
Termination Handle API
Renderer Importance API

如需瞭解有關這些 API 用法的更多信息,請參閱管理 WebView。
固定快捷方式和小部件

Android O 引入了快捷方式和小部件的應用內固定功能。在您的應用中,您可以根據用戶權限爲支持的啓動器創建固定的快捷方式和小部件。

如需瞭解詳細信息,請參閱固定快捷方式和小部件預覽功能指南。
無障礙功能

Android O 支持開發者使用以下無障礙功能創建自己的無障礙服務:

語言檢測

要識別“文本到語音轉換 (TTS)”工具已在某個文本範圍內識別的語言,請使用 TextClassificationManager.detectLanguages()。此方法出現在 Android O 中引入的TextClassificationManager 類中。您可以使用生成的 android.view.textclassifier.TextLanguage 對象列表來確定哪些文本區域已被指定爲某種特定的語言以及 TTS 有多大把握爲某個特定的文本子集指定語言。

無障礙功能按鈕

通過在 android:accessibilityFlags 屬性中設置 FLAG_REQUEST_ACCESSIBILITY_BUTTON 標誌,您的服務可以請求在系統的導航區域顯示無障礙功能按鈕。此按鈕爲用戶從設備上的任何屏幕啓動服務功能提供了一種快速的方式。您的服務可以使用 registerAccessibilityButtonCallback() 註冊按鈕交互回調。

注:此功能僅適用於提供軟件渲染導航區域的設備。使用 isAccessibilityButtonAvailable() 方法和 onAvailabilityChanged() 回調可跟蹤無障礙功能按鈕的可用性。請確保您的服務的用戶在無障礙功能按鈕不可用時可以通過其他方式訪問相關功能。

指紋手勢

您的無障礙服務也可以響應替代的輸入機制,即沿設備的指紋傳感器按特定方向滑動(上、下、左和右)。要獲取有關這些交互的回調,請完成以下順序步驟:

    聲明 USE_FINGERPRINT 權限和 AccessibilityServiceInfo.CAPABILITY_CAN_CAPTURE_FINGERPRINT_GESTURES 功能。
    在 android:accessibilityFlags 屬性中設置 AccessibilityServiceInfo.FLAG_CAPTURE_FINGERPRINT_GESTURES 標誌。
    使用 registerFingerprintGestureCallback() 註冊回調。

請記住,並非所有設備都包含指紋傳感器。您可以使用 isHardwareDetected() 方法識別設備是否支持此傳感器。即使對於包含指紋傳感器的設備,您的服務也只有在指紋傳感器不用於身份驗證目的時纔可使用它。要識別此傳感器何時可用,請調用 isGestureDetectionAvailable() 方法並實現 onGestureDetectionAvailabilityChanged() 回調。

字詞級突出顯示

要確定 TextView 對象中可見字符的位置,您可以在 EXTRA_DATA_TEXT_CHARACTER_LOCATION_KEY 中將其作爲第一個參數傳遞到 refreshWithExtraData() 中。隨後會更新您爲 refreshWithExtraData() 提供的作爲第二個參數的 Bundle 對象,使之包含一個可打包的 Rect 對象數組。每個 Rect 對象代表某個特定字符的邊界框。

如果您的服務使用 TextToSpeech 對象朗讀屏幕上出現的內容,您可以獲取文本到語音轉換引擎開始朗讀單個合成字詞時的準確時間信息。當引擎即將開始播放特定範圍文本的音頻時,Text-to-Speech API 會通知您的服務,將使用 UtteranceProgressListener.onUtteranceRangeStart() 回調開始朗讀此範圍的文本。

如果您創建自己的 TextToSpeechService 實現,您可以使用 rangeStart() 方法支持這一新功能。

提示文本

您的服務可以使用 AccessibilityNodeInfo 類中的 getHintText() 方法,獲取 EditText 對象的提示文本。即使某個特定的 EditText 對象當前未顯示提示文本,getHintText() 方法仍將爲您的服務提供提示文本。

連續的手勢分派
您的服務現在可以使用 GestureDescription.StrokeDescription 構造函數中的最後一個參數 isContinued,指定屬於同一設定手勢的筆劃的順序。

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

引入新權限

Android O 中引入了一項新權限android.permission.ANSWER_PHONE_CALLS,使用此權限,應用可按設定的方式接聽撥入的電話。此權限被劃分爲危險類別,屬於 PHONE 權限組。

要在應用中處理撥入的電話,您可以使用 TelecomManager 類中的 acceptRingingCall() 方法。
內容提供程序分頁

我們已更新內容提供程序以支持加載大型數據集,每次加載一頁。例如,一個具有大量圖像的照片應用可查詢要在頁面中顯示的數據的子集。內容提供程序返回的每個結果頁面由一個 Cursor 對象表示。客戶端和提供程序必須實現分頁才能利用此功能。

如需瞭解有關內容提供程序變更的詳細信息,請參閱 ContentProvider 和 ContentProviderClient。
媒體增強功能
媒體指標

新的 getMetrics() 方法將返回一個包含配置和性能信息的 Bundle 對象,用一個包含屬性和值的地圖表示。爲以下媒體類定義 getMetrics() 方法:

MediaPlayer.getMetrics()
MediaRecorder.getMetrics()
MediaCodec.getMetrics()
MediaExtractor.getMetrics()

爲每個實例單獨收集指標,並持續到實例的生命週期結束爲止。如果沒有可用的指標,則此方法將返回 null。返回的實際指標取決於類。

MediaPlayer

Android O 爲 MediaPlayer 類添加了多種新方法。這些方法可以從多個方面增強您的應用處理媒體播放的能力:

通過控制緩衝行爲改進性能的功能。
在搜索幀時進行精細控制。
播放受數字版權管理保護的材料的功能。

音頻錄製器

音頻錄製器現在支持對流式傳輸有用的 MPEG2_TS 格式:

mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_2_TS);

請參閱 MediaRecorder.OutputFormat
MediaMuxer 現在可以處理任意數量的音頻和視頻流,而不再僅限於一個音頻曲目和/或一個視頻曲目。使用 addTrack() 可混錄所需的任意數量的曲目。
MediaMuxer 還可以添加一個或多個包含用戶定義的每幀信息的元數據曲目。元數據的格式由您的應用定義。僅對 MP4 容器支持元數據曲目。

元數據可以用於離線處理。例如,傳感器的陀螺儀信號可以用於執行視頻穩定操作。

在添加元數據曲目時,曲目的 MIME 格式必須以前綴“application/”開頭。除了數據不是來源於 MediaCodec 以外,寫入元數據的操作與寫入視頻/音頻數據相同。相反,應用將包含相關時間戳的 ByteBuffer 傳遞給 writeSampleData() 方法。時間戳必須和視頻及音頻曲目處於相同的時基。

生成的 MP4 文件使用 ISOBMFF 的 12.3.3.2 部分定義的 TextMetaDataSampleEntry,指示元數據的 MIME 格式。在使用 MediaExtractor 提取包含元數據曲目的文件時,元數據的 MIME 格式將提取到 MediaFormat 中。

多顯示器支持

從 Android O 開始,此平臺爲多顯示器提供增強的支持。如果 Activity 支持多窗口模式,並且在具有多顯示器的設備上運行,則用戶可以將 Activity 從一個顯示器移動到另一個顯示器。當應用啓動 Activity 時,此應用可指定 Activity 應在哪個顯示器上運行。

注:如果 Activity 支持多窗口模式,則 Android O 將爲該 Activity 自動啓用多顯示器支持。您應測試您的應用,確保它在多顯示器環境下可正常運行。

每次只有一個 Activity 可以處於繼續狀態,即使此應用具有多個顯示器。具有焦點的 Activity 將處於繼續狀態,所有其他可見的 Activity 均暫停,但不會停止。如需瞭解有關當多個 Activity 可見時活動生命週期的詳細信息,請參閱多窗口生命週期。

當用戶將 Activity 從一個顯示器移動到另一個顯示器時,系統將調整 Activity 大小,並根據需要發起運行時變更。您的 Activity 可以自行處理配置變更,或允許系統銷燬包含該 Activity 的進程,並以新的尺寸重新創建它。如需瞭解詳細信息,請參閱處理配置變更。

API 變更

ActivityOptions 提供兩個新方法以支持多個顯示器:

setLaunchDisplayId()
指定 Activity 在啓動後應顯示在哪個顯示器上。
getLaunchDisplayId()
返回 Activity 的當前啓動顯示器。

工具更新

對 adb shell 進行了擴展,以支持多個顯示器。shell start 命令現在可用於啓動 Activity,並指定 Activity 的目標顯示器:

adb shell start –display

新的帳號訪問和 Discovery API

Android O 對應用訪問用戶帳號的方式引入多項改進。對於由身份驗證器管理的帳號,身份驗證器在決定對應用隱藏帳號還是顯示帳號時可以使用自己的政策。Android 系統跟蹤可以訪問特定帳號的應用。

在以前的 Android 版本中,想要跟蹤用戶帳號列表的應用必須獲取有關所有帳號的更新,包括具有不相關類型的帳號。Android O 添加了 addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]) 方法,其允許應用指定應接收帳號變更的帳號類型列表。

AccountManager 提供六個新方法以幫助身份驗證器管理哪些應用可以查看帳號:

setAccountVisibility(android.accounts.Account, java.lang.String, int):針對特定用戶帳號和軟件包組合設置可見性級別。
getAccountVisibility(android.accounts.Account, java.lang.String):獲取特定用戶帳號和軟件包組合的可見性級別。
getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String):允許身份驗證器獲取帳號和給定軟件包的可見性級別。
getPackagesAndVisibilityForAccount(android.accounts.Account):允許身份驗證器獲取存儲的給定帳號的可見性值。
addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.String, java.lang.Integer>):允許身份驗證器初始化帳號的可見性值。
addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]):將 OnAccountsUpdateListener 偵聽器添加到 AccountManager 對象。無論設備上的帳號列表何時發生變化,系統都將調用此偵聽器。

Android O 引入兩個特殊的軟件包名稱值,以使用 setAccountVisibility(android.accounts.Account, java.lang.String, int) 方法指定未設置的應用的可見性級別。PACKAGE_NAME_KEY_LEGACY_VISIBLE 可見性值應用於具有 GET_ACCOUNTS 權限的應用,並且其目標 Android 版本低於 Android O,或其簽名與針對任意 Android 版本的身份驗證器匹配。PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE 爲之前未設置的應用提供默認的可見性值,對於此類應用,PACKAGE_NAME_KEY_LEGACY_VISIBLE 不適用。

如需瞭解有關新的帳號訪問和 Discovery API 的詳細信息,請參閱對 AccountManager 和 OnAccountsUpdateListener 的參考。
AnimatorSet

從 Android O 開始,AnimatorSet API 現在支持尋道和倒播功能。尋道功能允許您將動畫的位置設置爲指定的時間點處。如果您的應用包含可撤消的動作的動畫,倒播功能會很有用。現在,您不必定義兩組獨立的動畫,而只需反向播放同一組動畫。
自動調整 TextView 的大小

Android O 允許您根據 TextView 的大小自動設置文本展開或收縮的大小。這意味着,在不同屏幕上優化文本大小或者優化包含動態內容的文本大小比以往簡單多了。如需瞭解有關如何在 Android O 中自動調整 TextView 的大小的詳細信息,請參閱自動調整 TextView 的大小。

應用類別

在適當的情況下,Android O 允許每個應用聲明它們所屬的類別。這些類別用於將應用呈現給用戶的用途或功能相同的應用歸類在一起,例如按流量消耗、電池消耗和存儲消耗將應用歸類。您可以在 清單標記中設置 android:appCategory 屬性,定義應用的類別。
新的 StrictMode 檢測程序

Android O 添加了三個新的 StrictMode 檢測程序,幫助識別應用可能出現的錯誤:

detectUnbufferedIo() 將檢測您的應用何時讀取或寫入未緩衝的數據,這可能極大影響性能。
detectContentUriWithoutPermission() 將檢測您的應用在其外部啓動 Activity 時何時意外忘記向其他應用授予權限。
detectUntaggedSockets() 將檢測您的應用何時使用網絡流量,而不使用 setThreadStatsTag(int) 將流量標記用於調試目的。

緩存數據

Android O 圍繞緩存數據提供更加出色的導航和性能。現在,每個應用均獲得一定的磁盤空間配額,用於存儲 getCacheQuotaBytes(UUID) 返回的緩存數據。

當系統需要釋放磁盤空間時,將開始從超過配額最多的應用中刪除緩存文件。因此,如果將您的緩存數據量始終保持低於配額的水平,則在必須清除系統中的某些文件時,您的緩存文件將能堅持到最後。系統在決定刪除您的應用中的哪些緩存文件時,將首先考慮刪除最舊的文件(由修改時間決定)。

您還可以針對每個目錄啓用兩種新行爲,以控制系統如何釋放緩存數據:

StorageManager.setCacheBehaviorAtomic() 可用於指示某個目錄及其所有內容應作爲一個不可分割的整體進行刪除。
setCacheBehaviorTombstone(File, boolean) 可用於指示不應刪除某個目錄內的文件,而應將它們截斷到 0 字節長度,使空文件保持完好。

最後,在需要爲大文件分配磁盤空間時,可考慮使用新的 allocateBytes(FileDescriptor, long) API,它將自動清除屬於其他應用的緩存文件(根據需要),以滿足您的請求。在確定設備是否有足夠的磁盤空間保存您的新數據時,請調用 getAllocatableBytes(UUID) 而不要使用 getUsableSpace(),因爲前者會考慮系統要爲您清除的任何緩存數據。
增強的媒體文件訪問功能

存儲訪問框架 (SAF) 允許應用顯示自定義 DocumentsProvider,後者可以爲其他應用提供訪問數據源中的文件的權限。事實上,文檔提供程序甚至可以提供駐留在網絡存儲區或使用媒體傳輸協議 (MTP) 等協議的文件的訪問權限。

但是,訪問遠程數據源中的大媒體文件面臨一些挑戰。媒體播放器需要以尋址方式訪問來自文檔提供程序的文件。當大媒體文件駐留在遠程數據源上時,文檔提供程序必須事先提取所有數據,並創建快照文件描述符。媒體播放器無法播放沒有文件描述符的文件,因此在文檔提供程序完成文件下載前,無法開始播放。

從 Android O 開始,存儲訪問框架允許自定義文檔提供程序爲駐留在遠程數據源中的文件創建可尋址的文件描述符。SAF 可打開文件,獲取原生可尋址的文件描述符。然後 SAF 向文檔提供程序提交離散字節請求。此功能使文檔提供程序可以返回媒體播放器應用請求的準確字節範圍,而不必事先緩存整個文件。

要使用此功能,您需要調用新的 StorageManager.openProxyFileDescriptor() 方法。openProxyFileDescriptor() 方法可接受 ProxyFileDescriptorCallback 對象作爲回調。任何時候,當客戶端應用對文檔提供程序返回的文件描述符執行文件操作時,SAF 都會調用回調。

企業中的 Android

Android 企業版爲運行 Android O 的設備引入多種新功能和 API。我們改進了個人資料所有者和設備所有者管理模式,使其比以往任何時候都更強大、高效,也更容易設置。我們還啓用了全新的部署方案。

一些值得關注的突出功能包括:

在企業擁有的設備上使用託管個人資料的功能。
大刀闊斧地改進了工作資料,採用易於使用的設置流程,顯著縮短設置時間。
基於文件的企業級加密管理。
應用管理 API 委派。

如需瞭解有關 Android O 中面向 Android 企業版的新 API 和新功能的更多信息,請參閱企業中的 Android 頁面。
Java 編程語言更新

在 Android O 中,我們將爲 Android 添加 OpenJDK Java 語言功能。我們將添加來自 OpenJDK 8 的 java.time 以及 java.nio.file 和 java.lang.invoke,包括來自 OpenJDK 7 的 MethodHandle。請查閱新程序包中的 API 差異報告。

Android O 行爲變更

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 可幫助您的應用防範來自惡意應用的內容變更,並防止將可能的私密數據泄露給惡意應用。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章