Android 9 Pie
Android 9 Pie
Android 9 利用人工智能技術,讓手機可以為您提供更多幫助。現在,手機變得更智能、更快,并且還可以隨著您的使用進行調整。
查看新功能
確保您的應用兼容
測試您的應用與 Android 9 是否兼容。只需下載設備系統鏡像,安裝您的當前應用,并針對行為變更可能對應用產生影響的各個方面進行測試。更新您的代碼,并使用應用當前指定的平臺進行發布。
下載系統鏡像
如何為 Pixel 設備獲取 Android?9
了解詳情
行為變更
影響所有 Android?9 應用的系統變更
了解詳情
兼容性測試
實現兼容性的簡單步驟
了解詳情
Android?9 中提供哪些功能?
更簡約,更快捷,更多擴展應用的新方式。
-
?
通知更新和智能回復
?
-
?
適用于位圖和可繪制對象的 ImageDecoder
?
-
?
JobScheduler 中的流量費用敏感度
?
-
?
顯示屏凹口 API
?
-
?
多攝像頭 API
?
-
?
更多…
?
開始使用 Android?9!
請先以 Android?9 作為目標版本,并支持其行為變更。當您準備就緒后,便可使用新功能和 API 來擴展您的應用。
以 Android?9 作為目標版本
Studio 設置以及如何以 Android?9 作為目標版本
了解詳情
以 API 28+ 為目標的應用的行為變更
以 Android?9 為目標的應用的系統變更
了解詳情
Android?9 功能
使用 Android?9 擴展您的應用
了解詳情
最新資訊和視頻
BLOG
Wrapping up for 2018 with Google Play and Android
Earlier this year we highlighted some of Google Play's milestones and commitments in supporting the 1M+ developers on the Play Store, as well as those of you working on Android apps and games and looking to launch and grow your business on our
Android Developers
2018年12月19日
BLOG
Effective foreground services on Android
This is the fourth in a series of blog posts in which outline strategies and guidance in Android with regard to power. Android is a mobile operating system designed to work with constrained memory and battery. For this reason, a typical Android
Android Developers
2018年12月12日
YOUTUBE
Android Developer Story: QQMusic delivers great experiences with Android 9
Discover how the team at QQMusic adapted their app to Android 9, and find out how they used Android Studio and Kotlin. Watch more developer stories → http://bit.ly/2JNZeW0 Subscribe to the channel → http://bit.ly/AndroidDevs1
Android Developers
2018年12月1日
YOUTUBE
Android Developer Story: Chinese developer CamScanner builds a business platform with Android
Find out how Chinese app CamScanner, part of CC Intelligence Technology, has built a trusted business platform with Android. CamScanner is unicorn enterprise specialized in AI and big data focusing on text recognition and interpretation, learn how
Android Developers
2018年12月1日
MORE
Android 9 功能和 API
Android 9(API 級別 28)為用戶和開發者引入了眾多新特性和新功能。 本文重點介紹面向開發者的新功能。
要了解新 API,請閱讀?API 差異報告或訪問?Android API 參考。 請務必查閱?Android 9 行為變更以了解平臺變更可能對應用產生影響的各個方面。
利用 Wi-Fi RTT 進行室內定位
Android 9 添加了對 IEEE 802.11mc Wi-Fi 協議(也稱為?Wi-Fi Round-Trip-Time?(RTT))的平臺支持,從而讓您的應用可以利用室內定位功能。
在運行 Android 9 且具有硬件支持的設備上,應用可以使用?RTT API?來測量與附近支持 RTT 的 Wi-Fi?接入點?(AP) 的距離。 設備必須已啟用位置服務并開啟 Wi-Fi 掃描(在?Settings > Location?下),同時您的應用必須具有?ACCESS_FINE_LOCATION?權限。
設備無需連接到接入點即可使用 RTT。 為了保護隱私,只有手機可以確定與接入點的距離;接入點無此信息。
如果您的設備測量與 3 個或更多接入點的距離,您可以使用一個多點定位算法來預估與這些測量值最相符的設備位置。 結果通常精準至 1 至 2 米。
通過這種精確性,您可以打造新的體驗,例如樓內導航、基于精細位置的服務,如無歧義語音控制(例如,“打開這盞燈”),以及基于位置的信息(如?“此產品是否有特別優惠?”)。
顯示屏缺口支持
通過使用模擬器測試屏幕缺口。
Android 9 支持最新的全面屏,其中包含為攝像頭和揚聲器預留空間的屏幕缺口。 通過?DisplayCutout?類可確定非功能區域的位置和形狀,這些區域不應顯示內容。 要確定這些屏幕缺口區域是否存在及其位置,請使用?getDisplayCutout()?函數。
全新的窗口布局屬性?layoutInDisplayCutoutMode?讓您的應用可以為設備屏幕缺口周圍的內容進行布局。 您可以將此屬性設為下列值之一:
- LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT
- LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES
- LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER
可以按以下方法在任何運行 Android 9 的設備或模擬器上模擬屏幕缺口:
注:我們建議您通過使用運行 Android 9 的設備或模擬器測試屏幕缺口周圍的內容顯示。
通知
Android 9 引入了多個通知增強功能,可供以 API 級別 28 及以上版本作為目標平臺的開發者使用。
附帶了照片的 MessagingStyle。
含回復和對話的 MessagingStyle。
提升短信體驗
從 Android 7.0(API 級別 24)開始,您可以添加一個操作以回復短信或直接從通知中輸入其他文本。 Android 9 通過下列增強提升了該功能:
-
簡化了針對對話參與者的支持:Person?類可用于識別參與對話的人員,包括他們的頭像和 URI。 現在,許多其他 API(如?addMessage())均可利用 [Person] 類而不是?CharSequence。?Person?類也支持構建器設計模式。
-
支持圖像:現在,Android 9 可在手機的“短信通知”中顯示圖像。 您可以使用對短信使用?setData()來顯示圖像。 以下代碼段演示了如何創建?Person?和包含圖像的短信。
?
KOTLINJAVA
// Create new Person. Person sender = new Person().setName(name).setUri(uri).setIcon(null).build(); // Create image message. Message message = new Message("Picture", time, sender).setData("image/", imageUri); Notification.MessagingStyle style = new Notification.MessagingStyle(getUser()).addMessage("Check this out!", 0, sender).addMessage(message);?
?
-
將回復另存為草稿:當用戶無意中關閉一個短信通知時,您的應用可以檢索系統發送的?EXTRA_REMOTE_INPUT_DRAFT。 您可以使用此 extra 預填充應用中的文本字段,以便用戶可以完成他們的回復。
-
確定對話是否為群組對話。您可以使用?setGroupConversation()?以明確確定對話是否為群組對話。
-
為 Intent 設置語義操作:setSemanticAction()?函數允許您為操作提供語義含義,如“標記為已讀”、“刪除”和“回復”等。
-
SmartReply:Android 9 支持在您的短信應用中提供相同的建議回復。 使用?RemoteInput.setChoices()?為用戶提供一組標準回復。
渠道設置、廣播和請勿打擾
Android 8.0 引入了通知渠道,允許您為要顯示的每種通知類型創建可由用戶自定義的渠道。 Android 9 通過下列變更簡化通知渠道設置:
-
屏蔽渠道組:現在,用戶可以針對某個應用在通知設置中屏蔽整個渠道組。 您可以使用?isBlocked()?函數確定何時屏蔽一個渠道組,從而不會向該組中的渠道發送任何通知。
此外,您的應用可以使用全新的?getNotificationChannelGroup()?函數查詢當前渠道組設置。
-
全新的廣播 Intent 類型:現在,當通知渠道和渠道組的屏蔽狀態發生變更時,Android 系統將發送廣播 Intent。 擁有已屏蔽的渠道或渠道組的應用可以偵聽這些 Intent 并做出相應的回應。 有關這些 Intent 操作和 extra 的更多信息,請參閱?NotificationManager?參考中更新的常量列表。 有關響應廣播 Intent 的信息,請參閱廣播。
-
NotificationManager.Policy?有 3 種新的“請勿打擾”優先級類別:
- PRIORITY_CATEGORY_ALARMS?優先處理警報。
- PRIORITY_CATEGORY_MEDIA?優先處理媒體源的聲音,如媒體和語音導航。
- PRIORITY_CATEGORY_SYSTEM?優先處理系統聲音。
-
NotificationManager.Policy?還有 7 種新的“請勿打擾”常量,可以用來抑制視覺中斷:
- SUPPRESSED_EFFECT_FULL_SCREEN_INTENT?防止通知啟動全屏 Activity。
- SUPPRESSED_EFFECT_LIGHTS?屏蔽通知燈。
- SUPPRESSED_EFFECT_PEEK?防止通知短暫進入視圖(“滑出”)。
- SUPPRESSED_EFFECT_STATUS_BAR?防止通知顯示在支持狀態欄的設備的狀態欄中。
- SUPPRESSED_EFFECT_BADGE?在支持標志的設備上屏蔽標志。 如需了解詳細信息,請參閱修改通知標志。
- SUPPRESSED_EFFECT_AMBIENT?在支持微光顯示的設備上屏蔽通知。
- SUPPRESSED_EFFECT_NOTIFICATION_LIST?防止通知顯示在支持列表視圖(如通知欄或鎖屏)的設備的列表視圖中。
多攝像頭支持和攝像頭更新
在運行 Android 9 的設備上,您可以通過兩個或更多物理攝像頭來同時訪問多個視頻流。] 在配備雙前置攝像頭或雙后置攝像頭的設備上,您可以創建只配備單攝像頭的設備所不可能實現的創新功能,例如無縫縮放、背景虛化和立體成像。 通過該 API,您還可以調用邏輯或融合的攝像頭視頻流,該視頻流可在兩個或更多攝像頭之間自動切換。
攝像頭方面的其他改進還包括附加會話參數和 Surface 共享,前者有助于降低首次拍照期間的延遲,而后者則讓攝像頭客戶端能夠處理各種用例,而無需停止并啟動攝像頭視頻流。 我們還針對基于顯示屏的?flash 支持和?OIS 時間戳訪問新增了一些 API,用以實現應用級的圖像穩定化和特效。
在 Android 9 中,多攝像頭 API支持單色攝像頭,適用于具有?FULL?或?LIMITED?功能的設備。 單色輸出通過?YUV_420_888?格式實現,Y 為灰度,U (Cb) 為 128,V (Cr) 為 128。
在受支持的設備上,Android 9 還支持外置 USB/UVC 攝像頭。
適用于可繪制對象和位圖的 ImageDecoder
Android 9 引入了?ImageDecoder?類,可提供現代化的圖像解碼方法。 使用該類取代?BitmapFactory?和?BitmapFactory.Options?API。
ImageDecoder?讓您可通過字節緩沖區、文件或 URI 來創建?Drawable?或?Bitmap。 要解碼圖像,請首先以編碼圖像的來源為參數,調用?createSource()。 然后,通過傳遞?ImageDecoder.Source?對象來調用?decodeDrawable()?或?decodeBitmap(),從而創建?Drawable] 或?Bitmap。 要更改默認設置,請將?OnHeaderDecodedListener?傳遞給?decodeDrawable()?或?decodeBitmap()。?ImageDecoder?調用?onHeaderDecoded(),以圖像的默認寬度和高度(若已知)為參數。 如果編碼圖像是動畫 GIF 或 WebP,decodeDrawable()?將返回?Drawable,它是?AnimatedImageDrawable?類的一個實例。
您可以使用不同的方法來設置圖像屬性:
- 要將解碼的圖像縮放到精確尺寸,請將目標尺寸傳遞給?setTargetSize()。 您也可以使用樣圖尺寸來縮放圖像。 將樣圖尺寸直接傳遞給?setTargetSampleSize()。
- 要在縮放圖像的范圍內裁剪圖像,請調用?setCrop()。
- 要創建可變位圖,請將?true?傳遞給?setMutableRequired()。
通過?ImageDecoder?還可以為圓角或圓形遮罩之類的圖像添加復雜的定制效果。 以?PostProcessor?類的一個實例作為參數使用?setPostProcessor(),執行您所需的任何繪圖命令。
注:對?AnimatedImageDrawable進行后處理時,效果會出現在動畫的所有幀中。
動畫
Android 9 引入了?AnimatedImageDrawable?類,用于繪制和顯示 GIF 和 WebP 動畫圖像。?AnimatedImageDrawable?的工作方式與?AnimatedVectorDrawable?的相似之處在于,都是渲染線程驅動?AnimatedImageDrawable?的動畫。 渲染線程還使用工作線程進行解碼,因此,解碼不會干擾渲染線程的其他操作。 這種實現機制允許您的應用在顯示動畫圖像時,無需管理其更新,也不會干擾應用界面線程上的其他事件。
可使用?ImageDecoder?的實例對?AnimatedImageDrawable?進行解碼。 以下代碼段演示如何使用?ImageDecoder?來解碼?AnimatedImageDrawable:
KOTLINJAVA
private void decodeImage() throws IOException {Drawable decodedAnimation = ImageDecoder.decodeDrawable(ImageDecoder.createSource(getResources(), R.drawable.my_drawable));if (decodedAnimation instanceof AnimatedImageDrawable) {// Prior to start(), the first frame is displayed.((AnimatedImageDrawable) decodedAnimation).start();} }?
ImageDecoder?有幾個允許您進一步修改圖像的函數。 例如,可使用?setPostProcessor()?函數來修改圖像的外觀,如應用圓形遮罩或圓角。
HDR VP9 視頻、HEIF 圖像壓縮和 Media API
Android 9 新增了對 High Dynamic Range (HDR) VP9 Profile 2 的內置支持,因此,現在您可以在支持 HDR 的設備上為用戶提供來自 YouTube、Play Movies 和其他來源的采用 HDR 的影片。
Android 9 為平臺增加了對?HEIF?(heic) 圖像編碼的支持。?MediaMuxer?和?MediaExtractor?類中可支持 HEIF 靜態圖像示例 HEIF 改進了壓縮,可節省存儲空間和網絡數據流量。 借助 Android 9 設備上的平臺支持,從后端服務器發送和使用 HEIF 圖像輕而易舉。 確保應用兼容這種便于共享和顯示的數據格式后,嘗試在應用中使用 HEIF 作為圖像存儲格式。 您可以使用?ImageDecoder?或?BitmapFactory?進行 jpeg 到 heicto 的轉換,以通過 jpeg 獲取位圖,并且可以使用?HeifWriter?寫入來自 YUV 字節緩沖區、Surface 或 Bitmap 的 HEIF 靜態圖像。
還可通過?AudioTrack、AudioRecord?和?MediaDrm?類獲取媒體指標。
Android 9 向?MediaDRM?類添加了函數以獲取指標、高帶寬數字內容保護 (HDCP) 級別、安全級別和會話數,并對安全性級別和安全停止進行更多控制。 如需了解更多詳情,請參閱?API 差異報告。
在 Android 9 中,AAudio?API 包含 AAudioStream 屬性,用于?usage、content type?和?input preset。 使用這些屬性可以創建針對 VoIP 或攝像機應用調整的流。 您還可以設置?SessionID將 AAudio 流與可包含音效的子混音相關聯。 使用?AudioEffect API?來控制音效。
Android 9 包含一個用于?DynamicsProcessing?的?AudioEffect?API。 借助該類,可以構建基于通道的音效,由各種類型(包括均衡、多頻帶壓縮和限幅器)的多個階段組成。 頻帶和活動階段的數量可配置,而且大多數參數可實時控制。
JobScheduler 中的流量費用敏感度
從 Android 9 開始,JobScheduler?可以使用運營商提供的網絡狀態信號來改善與網絡有關的作業處理。
作業可以聲明其預估的數據大小、信號預提取,并指定具體的網絡要求。?JobScheduler?然后根據網絡狀態管理工作。 例如,當網絡顯示擁塞時,JobScheduler?可能會延遲較大的網絡請求。 如果使用的是不按流量計費的網絡,則?JobScheduler?可運行預提取作業以提升用戶體驗(例如預提取標題)。
添加作業時,確保使用?setEstimatedNetworkBytes()、setPrefetch()?和?setRequiredNetwork()(如果適用),以幫助?JobScheduler?正確處理工作。 在執行作業時,請確保使用?JobParameters.getNetwork()?返回的?Network對象。 否則,您將隱式使用設備的默認網絡,其可能不符合您的要求,從而導致意外的流量消耗。
Neural Networks API 1.1
Android 8.1(API 級別 27)中引入了?Neural Networks API?以加快 Android 設備上機器學習的速度。 Android 9 擴展和改進了該 API,增加了對九種新運算的支持:
- 元素級數學運算:
- ANEURALNETWORKS_DIV
- ANEURALNETWORKS_SUB
- 數組運算:
- ANEURALNETWORKS_BATCH_TO_SPACE_ND
- ANEURALNETWORKS_SPACE_TO_BATCH_ND
- ANEURALNETWORKS_SQUEEZE
- ANEURALNETWORKS_STRIDED_SLICE
- ANEURALNETWORKS_TRANSPOSE
- ANEURALNETWORKS_PAD
- ANEURALNETWORKS_MEAN
已知問題:?將?ANEURALNETWORKS_TENSOR_QUANT8_ASYMM?張量傳遞到?ANEURALNETWORKS_PAD?運算(在 Android 9 及更高版本中提供)時,NNAPI 的輸出可能與較高級別機器學習框架(如?TensorFlow Lite)的輸出不匹配。 應只傳遞ANEURALNETWORKS_TENSOR_FLOAT32?直到問題得到解決。
此外,API 還引入了一個新函數,即?ANeuralNetworksModel_relaxComputationFloat32toFloat16(),允許您指定是否計算范圍和精度低至 IEEE 754 16 位浮點格式的?ANEURALNETWORKS_TENSOR_FLOAT32。
自動填充框架
Android 9 引入了多項改進,自動填充服務可以利用這些改進進一步增強用戶填寫表單時的體驗。 如需詳細了解如何在您的應用中使用自動填充功能,請參閱自動填充框架指南。
安全增強功能
Android 9 引入了若干安全功能,詳見以下各節摘要說明:
Android Protected Confirmation
運行 Android 9 或更高版本的受支持設備賦予您使用 Android Protected Confirmation 的能力。 使用該工作流時,您的應用會向用戶顯示提示,請他們批準一個簡短的聲明。 應用可以通過這個聲明再次確認,用戶確實想完成一項敏感事務,例如付款。
如果用戶接受該聲明,Android 密鑰庫會收到并存儲由密鑰哈希消息身份驗證代碼 (HMAC) 保護的加密簽名。 Android 密鑰庫確認消息的有效性之后,您的應用可以使用在可信執行環境 (TEE) 下通過?trustedConfirmationRequired?生成的密鑰來簽署用戶已接受的消息。 該簽名具有很高的可信度,它表示用戶已看過聲明并同意其內容。
注意:Android Protected Confirmation 不會為用戶提供安全信息通道。 應用無法承擔 Android 平臺所提供機密性保證之外的任何其他保證。 尤其是,請勿使用該工作流顯示您通常不會顯示在用戶設備上的敏感信息。
如需獲得 Android Protected Confirmation 新增支持方面的指導,請參閱?Android Protected Confirmation?指南。
統一生物識別身份驗證對話框
在 Android 9 中,系統代表您的應用提供生物識別身份驗證對話框。 該功能可創建標準化的對話框外觀、風格和位置,讓用戶更加確信,他們在使用可信的生物識別憑據檢查程序進行身份驗證。
如果您的應用使用?FingerprintManager?向用戶顯示指紋身份驗證對話框,請切換到改用?BiometricPrompt。BiometricPrompt?依賴系統來顯示身份驗證對話框。 它還會改變其行為,以適應用戶所選擇的生物識別身份驗證類型。
注:在應用中使用?BiometricPrompt?之前,應該先使用?hasSystemFeature()函數以確保設備支持?FEATURE_FINGERPRINT、FEATURE_IRIS?或?FEATURE_FACE。
如果設備不支持生物識別身份驗證,可以回退為使用?createConfirmDeviceCredentialIntent()?函數驗證用戶的 PIN 碼、圖案或密碼。
硬件安全性模塊
運行 Android 9 或更高版本的受支持設備可擁有?StrongBox Keymaster,它是位于硬件安全性模塊中的 Keymaster HAL 的一種實現。 該模塊包含以下組成部分:
- 自己的 CPU。
- 安全存儲空間。
- 真實隨機數生成器。
- 可抵御軟件包篡改和未經授權線刷應用的附加機制。
檢查存儲在 StrongBox Keymaster 中的密鑰時,系統會通過可信執行環境 (TEE) 證實密鑰的完整性。
如需了解有關使用 Strongbox Keymaster 的更多信息,請參閱硬件安全性模塊。
保護對密鑰庫進行的密鑰導入
Android 9 通過利用 ASN.1?編碼密鑰格式將已加密密鑰安全導入密鑰庫的功能,提高了密鑰解密的安全性。 Keymaster 隨后會在密鑰庫中將密鑰解密,因此密鑰的內容永遠不會以明文形式出現在設備的主機內存中。
注:只有附帶 Keymaster 4 或更高版本的設備才支持該功能。
詳細了解如何更安全地導入已加密密鑰。
具有密鑰輪轉的 APK 簽名方案
Android 9 新增了對 APK Signature Scheme v3 的支持。該架構提供的選擇可以在其簽名塊中為每個簽名證書加入一條輪轉證據記錄。 利用此功能,應用可以通過將 APK 文件過去的簽名證書鏈接到現在簽署應用時使用的證書,從而使用新簽名證書來簽署應用。
注:運行 Android 8.1(API 級別 27)或更低版本的設備不支持更改簽名證書。 如果應用的?minSdkVersion?為?27?或更低,除了新簽名之外,可使用舊簽名證書來簽署應用。
詳細了解如何使用?apksigner?輪轉密鑰。
只允許在未鎖定設備上進行密鑰解密的選項
Android 9 引入了?unlockedDeviceRequired?標志。 此選項確定在允許使用指定密鑰對任何正在傳輸或存儲的數據進行解密之前,密鑰庫是否要求屏幕解鎖。 這些類型的密鑰非常適合用于加密要存儲在磁盤上的敏感數據,例如健康或企業數據。 該標志為用戶提供了更高的保證,即使手機丟失或被盜,在設備鎖定的情況下,無法對數據進行解密。
注:unlockedDeviceRequired?標志啟用之后,仍然可以隨時進行加密和簽名驗證。 該標志可防止在設備解鎖時“僅解密”數據。
在設備鎖定時要確保密鑰安全不被解密,可通過將?true?傳遞給?setUnlockedDeviceRequired()?函數啟用該標志。 完成該步驟之后,當用戶的屏幕被鎖定時,使用該密鑰進行解密或簽署數據的任何嘗試都會失敗。 鎖定設備在可以訪問之前,需要 PIN 碼、密碼、指紋或者一些其他可信因素。
舊版加密支持
附帶 Keymaster 4 的 Android 9 設備支持三重數據加密算法(簡稱三重 DES)。 如果您的應用與需要三重 DES 的舊版系統進行互操作,請使用這種加密來加密敏感憑據。
如需詳細了解如何讓您的應用更加安全,請參閱?Android 開發者的安全性。
Android 備份
?
Android 9 新增了與備份和還原有關的功能和開發者選項。 這些更改的詳細信息如以部分下所示。
客戶端加密備份
?
Android 9 新增了對使用客戶端密鑰加密 Android 備份的支持。 滿足下列條件時會自動啟用該支持功能:
- 用戶已使用 Android 9 或更高版本啟用備份。
- 用戶已為其設備設置屏幕鎖定,需要 PIN 碼、圖案或密碼才能解鎖。
該隱私措施啟用之后,從用戶設備制作的備份還原數據時,會要求提供設備的 PIN 碼、圖案或密碼。 如需詳細了解該項功能背后的技術,請參閱?Google 云密鑰保險柜服務白皮書。
定義備份所需的設備條件
如果您的應用數據包含敏感信息或偏好,Android 9 可讓您定義設備條件(例如在客戶端加密已啟用或者正在進行本地設備到設備傳輸時),數據將依據該條件包括在用戶的備份中。
如需了解有關在 Android 設備上備份數據的詳細信息,請參閱數據備份概覽。
無障礙功能
Android 9 引入了針對無障礙功能框架的增強功能,讓您能夠更輕松地為應用的用戶提供更好的體驗。
導航語義
Android 9 中的新增屬性讓您可以更輕松地定義無障礙服務(尤其是屏幕閱讀器)如何從屏幕的某個部分導航到另一個部分。 這些屬性可幫助視力受損用戶在應用界面的文本之間快速移動,并允許他們進行選擇。
例如,在購物應用中,屏幕閱讀器可以幫助用戶從某個交易類別直接導航至下一個交易類別,在轉到下一個類別之前,屏幕閱讀器無需讀取當前類別中的所有交易。
無障礙功能窗格標題
在 Android 8.1(API 級別 27)和更低版本中,無障礙服務有時無法確定屏幕的某個窗格是何時更新的,例如某個 Activity 將一個 Fragment 替換為另一個 Fragment 的時候。 窗格由按照邏輯關系分組、視覺上相關的界面元素組成,其中通常包含一個 Fragment。
在 Android 9 中,可為這些窗格提供?無障礙功能窗格標題,即可單獨識別的標題。 如果某個窗格具有無障礙功能窗格標題,當窗格改變時,無障礙服務可接收更詳細的信息。 依靠這種功能,服務可以為用戶提供有關界面變化的更精細信息。
要指定某個窗格的標題,請使用?android:accessibilityPaneTitle?屬性。 您也可以更新在運行時使用?setAccessibilityPaneTitle()?替換的某個界面窗格的標題。 例如,您可以為某個?Fragment?對象的內容區域提供標題。
基于標題的導航
如果您的應用顯示的文本內容包含邏輯標題,則對于表示這些標題的?View?實例,請將android:accessibilityHeading?屬性設置為?true。 通過添加這些標題,無障礙服務可幫助用戶直接從一個標題導航至下一個標題。 任何無障礙服務都可以使用這種功能,以改善用戶界面的導航體驗。
群組導航和輸出
傳統上,屏幕閱讀器一直使用?android:focusable?屬性來確定何時應該將?ViewGroup?或一系列?View?對象作為一個整體進行讀取。 這樣,用戶就可以了解,這些視圖在邏輯上彼此相關。
在 Android 8.1 和更低版本中,您需要將?ViewGroup?中的每個?View?對象標記為不可聚焦,并將?ViewGroup?本身標記為可聚焦。 這種安排導致?View?的某些實例被標記為可聚焦,從而使得鍵盤導航變得更為繁瑣。
從 Android 9 開始,如果將?View?對象標記為可聚焦會產生不良后果,則可以使用?android:screenReaderFocusable屬性代替?android:focusable?屬性。 屏幕閱讀器聚焦在所有將?android:screenReaderFocusable?或?android:focusable?設置為?true?的元素上。
便捷操作
Android 9 新增了一些方便用戶執行操作的支持功能:
訪問提示: 無障礙功能框架中的新增功能可讓您在應用界面中訪問提示。 使用?getTooltipText()?讀取提示文本,使用?ACTION_SHOW_TOOLTIP?和?ACTION_HIDE_TOOLTIP?來指示?View?的實例顯示或隱藏提示。
新增全局操作: Android 9 在?AccessibilityService?類中引入了對兩個額外設備操作的支持。 您的 Service 可以幫助用戶分別使用?GLOBAL_ACTION_LOCK_SCREEN?和?GLOBAL_ACTION_TAKE_SCREENSHOT?操作鎖定其設備并進行屏幕截圖。
窗口變更詳情
Android 9 讓您可以在應用同時重繪多個窗口時,更輕松地跟蹤應用窗口的更新。 當發生?TYPE_WINDOWS_CHANGED?事件時,可使用?getWindowChanges()?API 來確定窗口發生的變更。 在多窗口更新期間,每個窗口都會生成自己的一組事件。?getSource()?函數返回與每個事件相關聯的窗口的根視圖。
如果應用已為其?View?對象定義無障礙功能窗格標題,您的 Service 將可以識別應用界面何時進行更新。TYPE_WINDOW_STATE_CHANGED?事件發生時,可使用?getContentChangeTypes()?所返回的類型來確定窗口發生的變更。 例如,框架可以檢測窗格何時有新標題或者窗格何時消失。
Google 致力于為所有 Android 用戶改善無障礙功能,提供增強功能以便讓您構建 Service,如話語提示?屏幕閱讀器,供需要無障礙功能的用戶使用。 如需了解有關如何讓您的應用更便于訪問以及如何構建無障礙 Service 的更多信息,請參閱無障礙功能。
旋轉
為避免無意的旋轉,我們新增了一種模式,哪怕設備位置發生變化,也會固定在當前屏幕方向上。 必要時用戶可以通過按系統欄上的一個按鈕手動觸發旋轉。
大多數情況下,對應用的兼容性影響微不足道。 不過,如果您的應用有任何自定義旋轉行為,或使用了任何非常規的屏幕方向設置,則可能會遇到以前用戶旋轉首選項始終設置為縱向時被忽視的問題。 我們鼓勵您審視一下您的應用所有關鍵 Activity 中的旋轉行為,并確保您的所有屏幕方向設置仍可提供最佳體驗。
如需了解更多詳情,請參閱相關的行為變更。
一個新的旋轉模式允許用戶在必要時利用系統欄上的一個按鈕手動觸發旋轉。
文本
Android 9 為平臺提供了以下與文本相關的功能:
-
文本預先計算:PrecomputedText?類使您能提前計算和緩存所需信息,改善了文本渲染性能。 它還使您的應用可以在主線程之外執行文本布局。
-
放大器:Magnifier?類是一種可提供放大器 API 的微件,可在所有應用中實現一致的放大器功能體驗。
-
Smart Linkify:Android 9 增強了?TextClassifier?類,該類可利用機器學習在選定文本中識別一些實體并建議采取相應的操作。 例如,TextClassifier?可以讓您的應用檢測到用戶選擇了電話號碼。 然后,您的應用可以建議用戶使用該號碼撥打電話。?TextClassifier?中的功能取代了?Linkify?類的功能。
-
文本布局:借助幾種便捷函數和屬性,可以更輕松地實現界面設計。 如需了解詳細信息,請參閱?TextView?參考文檔。
DEX 文件的 ART 提前轉換
在運行 Android 9 或更高版本的設備上,Android 運行時 (ART) 提前編譯器通過將應用軟件包中的 DEX 文件轉換為更緊湊的表示形式,進一步優化了壓縮的 Dalvik Executable 格式 (DEX) 文件。 此項變更可讓您的應用啟動更快并消耗更少的磁盤空間和內存。
這種改進特別有利于磁盤 I/O 速度較慢的低端設備。
設備端系統跟蹤
Android 9 允許您通過設備記錄系統跟蹤記錄,然后與您的開發團隊分享這些記錄的報告。 該報告支持多種格式,包括 HTML。
通過收集這些跟蹤記錄,您可以獲取與應用進程和線程相關的計時數據,并查看其他類型的具有全局意義的設備狀態。
注:您無需設置您的代碼來記錄跟蹤記錄,但這樣做可以幫助您查看應用代碼的哪些部分可能會導致線程掛起或界面卡頓。
如需詳細了解該工具,請參閱執行設備內置系統跟蹤。
?
行為變更:所有應用
Android 9(API 級別 28)向 Android 系統引入了多項變更。 當應用在 Android 9 平臺上運行時,以下行為變更將影響所有應用,無論這些應用以哪個 API 級別為目標。 所有開發者都應查看這些變更,并修改其應用以正確支持這些變更(如果適用)。
如需了解僅影響以 API 28 或更高級別為目標的應用的變更,請參閱行為變更:以 API 級別 28+ 為目標的應用。
電源管理
Android 9 引入了新功能以改善設備電源管理。 這些變更連同 Android 9 之前已存在的功能可幫助確保系統資源被提供給最需要它們的應用。
詳情請參閱電源管理。
隱私權變更
為了增強用戶隱私,Android 9 引入了若干行為變更,如限制后臺應用訪問設備傳感器、限制通過 Wi-Fi 掃描檢索到的信息,以及與通話、手機狀態和 Wi-Fi 掃描相關的新權限規則和權限組。
無論采用哪一種目標 SDK 版本,這些變更都會影響運行于 Android 9 上的所有應用。
后臺對傳感器的訪問受限
Android 9 限制后臺應用訪問用戶輸入和傳感器數據的能力。 如果您的應用在運行 Android 9 設備的后臺運行,系統將對您的應用采取以下限制:
- 您的應用不能訪問麥克風或攝像頭。
- 使用連續報告模式的傳感器(例如加速度計和陀螺儀)不會接收事件。
- 使用變化或一次性報告模式的傳感器不會接收事件。
如果您的應用需要在運行 Android 9 的設備上檢測傳感器事件,請使用前臺服務。
限制訪問通話記錄
Android 9 引入?CALL_LOG?權限組并將?READ_CALL_LOG、WRITE_CALL_LOG?和?PROCESS_OUTGOING_CALLS?權限移入該組。 在之前的 Android 版本中,這些權限位于?PHONE?權限組。
對于需要訪問通話敏感信息(如讀取通話記錄和識別電話號碼)的應用,該?CALL_LOG?權限組為用戶提供了更好的控制和可見性。
如果您的應用需要訪問通話記錄或者需要處理去電,則您必須向?CALL_LOG?權限組明確請求這些權限。 否則會發生?SecurityException。
注:因為這些權限已變更組并在運行時授予,用戶可以拒絕您的應用訪問通話記錄信息。 在這種情況下,您的應用應該能夠妥善處理無法訪問信息的狀況。
如果您的應用已經遵循運行時權限最佳做法,則可以處理權限組的變更。
限制訪問電話號碼
在未首先獲得?READ_CALL_LOG?權限的情況下,除了應用的用例需要的其他權限之外,運行于 Android 9 上的應用無法讀取電話號碼或手機狀態。
與來電和去電關聯的電話號碼可在手機狀態廣播(比如來電和去電的手機狀態廣播)中看到,并可通過?PhoneStateListener?類訪問。 但是,如果沒有?READ_CALL_LOG?權限,則?PHONE_STATE_CHANGED?廣播和?PhoneStateListener?提供的電話號碼字段為空。
要從手機狀態中讀取電話號碼,請根據您的用例更新應用以請求必要的權限:
- 要通過?PHONE_STATE?Intent 操作讀取電話號碼,同時需要?READ_CALL_LOG?權限和?READ_PHONE_STATE?權限。
- 要從?onCallStateChanged()?中讀取電話號碼,只需要?READ_CALL_LOG?權限。 不需要?READ_PHONE_STATE?權限。
限制訪問 Wi-Fi 位置和連接信息
在 Android 9 中,應用進行 Wi-Fi 掃描的權限要求比之前的版本更嚴格。 詳情請參閱?Wi-Fi 掃描限制。
類似的限制也適用于?getConnectionInfo()?函數,該函數返回描述當前 Wi-Fi 連接的?WifiInfo?對象。 如果調用應用具有以下權限,則只能使用該對象的函數來檢索 SSID 和 BSSID 值:
- ACCESS_FINE_LOCATION?或?ACCESS_COARSE_LOCATION
- ACCESS_WIFI_STATE
檢索 SSID 或 BSSID 還需要在設備上啟用位置服務(在?Settings > Location?下)。
從 Wi-Fi 服務函數中移除的信息
在 Android 9 中,下列事件和廣播不接收用戶位置或個人可識別數據方面的信息:
- WifiManager?中的?getScanResults()?和?getConnectionInfo()?函數。
- WifiP2pManager?中的?discoverServices()?和?addServiceRequest()?函數。
- NETWORK_STATE_CHANGED_ACTION?廣播。
Wi-Fi 的?NETWORK_STATE_CHANGED_ACTION系統廣播不再包含 SSID(之前為 EXTRA_SSID)、BSSID(之前為 EXTRA_BSSID)或連接信息(之前為 EXTRA_NETWORK_INFO)。 如果應用需要此信息,請改為調用getConnectionInfo()。
電話信息現在依賴設備位置設置
如果用戶在運行 Android 9 的設備上停用設備定位,則以下函數不提供結果:
- getAllCellInfo()
- listen()
- getCellLocation()
- getNeighboringCellInfo()
對使用非 SDK 接口的限制
為幫助確保應用穩定性和兼容性,此平臺對某些非 SDK 函數和字段的使用進行了限制;無論您是直接訪問這些函數和字段,還是通過反射或 JNI 訪問,這些限制均適用。 在 Android 9 中,您的應用可以繼續訪問這些受限的接口;該平臺通過 toast 和日志條目提醒您注意這些接口。 如果您的應用顯示這樣的 toast,則必須尋求受限接口之外的其他實現策略。 如果您認為沒有可行的替代策略,您可以提交錯誤以請求重新考慮此限制。
對非 SDK 接口的限制包含了更多重要信息。 您應查閱該信息以確保您的應用繼續正常工作。
安全行為變更
設備安全性變更
無論應用的目標平臺版本如何,Android 9 添加的若干功能均可令應用的安全性得到改善。
傳輸層安全協議 (TLS) 實現變更
系統的傳輸層安全協議 (TLS) 實現在 Android 9 中經歷了若干次變更:
- 如果?SSLSocket?的實例在創建時連接失敗,系統會引發?IOException?而非?NullPointerException。
- SSLEngine?類可正常處理出現的任何?close_notify?提醒。
如需了解有關在 Android 應用中進行安全網絡請求的更多信息,請參閱一個 HTTPS 示例。
更嚴格的 SECCOMP 過濾器
Android 9 對可供應用使用的系統調用做了進一步限制。 此行為是?Android 8.0(API 級別 26)包含的 SECCOMP 過濾器的擴展。
注:此更改僅影響使用授權的系統調用的應用。
加密變更
Android 9 針對加密算法的實現和處理引入了幾項變更。
參數和算法的 Conscrypt 實現
Android 9 在?Conscrypt?中實現了更多的算法參數。 這些參數包括: AES、DESEDE、OAEP 和 EC。 這些參數和許多算法的?Bouncy Castle?版本自 Android 9 起已被棄用。
注:EC 參數的 Conscrypt 實現僅支持已命名的曲線。
如果您的應用以 Android 8.1(API 級別 27)或更低版本為目標,則在請求這些已棄用算法之一的 Bouncy Castle 實現時,您將收到一條警告消息。 然而,如果您以 Android 9 為目標平臺,則這些請求會各自引發?NoSuchAlgorithmException。
其他變更
Android 9 引入了多項與加密有關的其他變更:
- 使用 PBE 密鑰時,如果 Bouncy Castle 需要初始化矢量 (IV),而您的應用未提供 IV,則會收到一條警告消息。
- ARC4 加密的 Conscrypt 實現允許您指定?ARC4/ECB/NoPadding?或?ARC4/NONE/NoPadding。
- Crypto Java 加密架構 (JCA) 提供程序現已被移除。 因此,如果您的應用調用?SecureRandom.getInstance("SHA1PRNG", "Crypto"),將會發生?NoSuchProviderException。
- 如果您的應用從大于密鑰結構的緩沖區中解析 RSA 密鑰,將不會再發生異常。
如需了解有關使用 Android 的加密功能的更多信息,請參閱加密。
不再支持 Android 安全加密文件
Android 9 完全取消了對 Android 安全加密文件 (ASEC) 的支持。
在 Android 2.2(API 級別 8)中,Android 引入了 ASEC 以支持 SD 卡加載應用功能。 在 Android 6.0(API 級別 23)上,平臺引入了一個可采用的存儲設備?技術,開發者可用它來代替 ASEC。
ICU 庫更新
Android 9 使用 ICU 庫版本 60。 Android 8.0(API 級別 26)和 Android 8.1(API 級別 27)使用 ICU 58。
ICU 用于提供?android.icu package?下的公開 API, 供 Android 平臺內部用來提供國際化支持。 例如,它用于實現?java.util、java.text?和?android.text.format?格式的 Android 類。
對 ICU 60 進行的更新包含許多細微但很有用的變更,這包括 Emoji 5.0 數據支持,改進了日期/時間格式,詳見 ICU 59 和 ICU 60 版本說明中的介紹。
本次更新中的顯著變更:
- 平臺處理時區的方式已發生更改。
- 平臺能夠更好地處理 GMT 和 UTC,不再將 UTC 與 GMT 混為一談。
ICU 現在提供 GMT 和 UTC 的翻譯版時區名稱。 此變更會影響“GMT”、“Etc/GMT”、“Etc/UTC”、“UTC”和“Zulu”之類時區的?android.icu?格式和解析行為。
- java.text.SimpleDateFormat?現在使用 ICU 提供 UTC /GMT 的顯示名稱,這意味著:
- 對于許多語言區域而言,設置?zzzz?的格式將會生成很長的本地化字符串。之前,對于 UTC 時區,它會生成“UTC”,而對于 GMT,則會生成“GMT+00:00”之類的字符串。
- 解析?zzzz?可識別“Universal Coordinated Time”和“Greenwich Mean Time”之類的字符串。
- 在所有語言里,如果應用接受“UTC”或“GMT+00:00”作為?zzzz?的輸出,則可能會遇到兼容性問題。
- java.text.DateFormatSymbols.getZoneStrings()?的行為已變更:
- 與?SimpleDateFormat?類似,現在,UTC 和 GMT 也有長名稱。對于 UTC 時區,DST 類型的時區名稱(例如“UTC”、“Etc/UTC”和“Zulu”)變為 GMT+00:00(而不是硬編碼字符串?UTC),這是在沒有其他名稱可用時的標準回退。
- 某些時區 ID 被正確地識別為其他地區的同義詞,因此,Android 能夠查找過時時區 ID(例如?Eire)對應的字符串,而之前無法解決此問題。
- 亞洲/河內不再是可識別的時區。 因此,java.util.TimeZones.getAvailableIds()?不再返回此值,java.util.TimeZone.getTimeZone()?也不再識別它。此行為與現有的?android.icu?行為相符。
- 平臺能夠更好地處理 GMT 和 UTC,不再將 UTC 與 GMT 混為一談。
- android.icu.text.NumberFormat.getInstance(ULocale, PLURALCURRENCYSTYLE).parse(String)?函數甚至在解析合法相應幣種文本時也會引發?ParseException。 通過對?PLURALCURRENCYSTYLE?類型的相應幣種文本使用自 Android 7.0(API 級別 24)以來所提供的NumberFormat.parseCurrency,可避免此問題。
Android Test 變更
Android 9 引入了多項針對 Android Test 框架庫和類結構的更改。 這些變更可幫助開發者使用支持框架的公共 API,此外,在使用第三方庫或自定義邏輯構建和運行測試時,這些變更還可提供更大的靈活性。
從框架移除的內容庫
Android 9 將基于 JUnit 的類重新整理成三個內容庫:?android.test.base、android.test.runner?和?android.test.mock。 此變更允許您針對與您的項目依賴項搭配效果最好的 JUnit 版本運行測試。 此版本的 JUnit 可能不同于?android.jar?提供的版本。
如需了解有關如何將基于 JUnit 的類組織到這些內容庫中,以及如何準備您的應用項目以編寫和運行測試,請參閱針對 Android 測試設置項目。
測試套件版本號變更
移除了?TestSuiteBuilder?類中的?addRequirements()?函數,TestSuiteBuilder?類本身也已棄用。addRequirements()?函數要求開發者提供類型為隱藏 API 的參數,結果令 API 失效。
Java UTF 解碼器
UTF-8 是 Android 中的默認字符集。 UTF-8 字節序列可由?String(byte[] bytes)?之類的?String?構造函數解碼。
Android 9 中的 UTF-8 解碼器遵循比以前版本中更嚴格的 Unicode 標準: 這些變更包括:
- 非最短形式的 UTF-8(例如?<C0, AF>)被視為格式不正確。
- 替代形式的 UTF-8(例如?U+D800..U+DFFF)被視為格式不正確。
- 最大的子部分被單個?U+FFFD?取代。 例如,在字節序列“41 C0 AF 41 F4 80 80 41”中,最大子部分為“C0”、“AF”和“F4 80 80”。其中“F4 80 80”可以是“F4 80 80 80”的初始子序列,但“C0”不能是任何形式正確的代碼單位序列的初始子序列。 因此,輸出應為“A\ufffd\ufffdA\ufffdA”。
- 要在 Android 9 或更高版本中解碼修改后的 UTF-8/CESU-8 序列,請使用?DataInputStream.readUTF()?函數或?NewStringUTF()?JNI 函數。
使用證書的主機名驗證
RFC 2818中介紹了兩種對照證書匹配域名的方法—使用?subjectAltName?(SAN) 擴展程序中的可用名稱,或者在沒有SAN?擴展程序的情況下,回退到?commonName?(CN)。
然而,在 RFC 2818 中,回退到?CN?已被棄用。因此,Android 不再回退到使用?CN。 要驗證主機名,服務器必須出示具有匹配?SAN?的證書。 不包含與主機名匹配的?SAN?的證書不再被信任。
網絡地址查詢可能會導致網絡違規
要求名稱解析的網絡地址查詢可能會涉及網絡 I/O,因此會被視為阻塞性操作。 對于主線程的阻塞性操作可能會導致停頓或卡頓。
StrictMode?類是一個有助于開發者檢測代碼問題的開發工具。
在 Android 9 及更高版本中,StrictMode?可以檢測需要名稱解析的網絡地址查詢所導致的網絡違規。
您在交付應用時不應啟用?StrictMode。 否則,您的應用可能會遭遇異常,例如,在使用?detectNetwork()?或?detectAll()?函數獲取用于檢測網絡違規的政策時,會出現NetworkOnMainThreadException。
解析數字 IP 地址不被視為阻塞性操作。 數字 IP 地址解析的工作方式與 Android 9 以前的版本中所采用的方式相同。
套接字標記
在低于 Android 9 的平臺版本上,如果使用?setThreadStatsTag()?函數標記某個套接字,則當使用帶?ParcelFileDescriptor?容器的?binder 進程間通信將其發送給其他進程時,套接字會被取消標記。
在 Android 9 及更高版本中,利用 binder 進程間通信將套接字發送至其他進程時,其標記將得到保留。 此變更可能影響網絡流量統計,例如,使用?queryDetailsForUidTag()?函數時。
如果您要保留以前版本的行為,即取消已發送至其他進程的套接字的標記,您可以在發送此套接字之前調用?untagSocket()。
報告的套接字中可用字節數
在調用?shutdownInput()?函數后,available()?函數會在調用時返回?0。
更詳盡的 VPN 網絡功能報告
在 Android 8.1(API 級別 28)及更低版本中,NetworkCapabilities?類僅報告 VPN 的有限信息,例如?TRANSPORT_VPN,但會省略?NET_CAPABILITY_NOT_VPN。 信息有限導致難以確定使用 VPN 是否會導致對應用的用戶收費。 例如,檢查?NET_CAPABILITY_NOT_METERED?并不能確定底層網絡是否按流量計費。
從 Android 9 及更高版本開始,當 VPN 調用?setUnderlyingNetworks()?函數時,Android 系統將會合并任何底層網絡的傳輸和能力并返回 VPN 網絡的有效網絡能力作為結果。
在 Android 9 及更高版本中,已經檢查NET_CAPABILITY_NOT_METERED?的應用將收到關于 VPN 網絡能力和底層網絡的信息。
應用不再能訪問 xt_qtaguid 文件夾中的文件
從 Android 9 開始,不再允許應用直接讀取?/proc/net/xt_qtaguid?文件夾中的文件。 這樣做是為了確保與某些根本不提供這些文件的設備保持一致。
依賴這些文件的公開 API?TrafficStats?和?NetworkStatsManager?繼續按照預期方式運行。 然而,不受支持的?cutils函數(例如?qtaguid_tagSocket())在不同設備上可能不會按照預期方式運行 — 甚至根本不運行。
現在強制執行 FLAG_ACTIVITY_NEW_TASK 要求
在 Android 9 中,您不能從非 Activity 環境中啟動 Activity,除非您傳遞 Intent 標志?FLAG_ACTIVITY_NEW_TASK。 如果您嘗試在不傳遞此標志的情況下啟動 Activity,則該 Activity 不會啟動,系統會在日志中輸出一則消息。
注:在 Android 7.0(API 級別 24)之前,標志要求一直是期望的行為并被強制執行。 Android 7.0 中的一個錯誤會臨時阻止實施標志要求。
屏幕旋轉變更
從 Android 9 開始,對縱向旋轉模式做出了重大變更。 在 Android 8.0(API 級別 26)中,用戶可以使用 Quicksettings 圖塊或 Display 設置在自動屏幕旋轉和縱向旋轉模式之間切換。 縱向模式已重命名為旋轉鎖定,它會在自動屏幕旋轉關閉時啟用。 自動屏幕旋轉模式沒有任何變更。
當設備處于旋轉鎖定模式時,用戶可將其屏幕鎖定到頂層可見 Activity 所支持的任何旋轉。 Activity 不應假定它將始終以縱向呈現。 如果頂層 Activity 可在自動屏幕旋轉模式下以多種旋轉呈現,則應在旋轉鎖定模式下提供相同的選項,根據 Activity 的?screenOrientation?設置,允許存在一些例外情況(見下表)。
請求特定屏幕方向(例如,screenOrientation=landscape)的 Activity 會忽略用戶鎖定首選項,并且行為與 Android 8.0 中的行為相同。
可在?Android Manifest?中,或以編程方式通過?setRequestedOrientation()?在 Activity 級別設置屏幕方向首選項。
旋轉鎖定模式通過設置 WindowManager 在處理 Activity 旋轉時使用的用戶旋轉首選項來發揮作用。 用戶旋轉首選項可能在下列情況下發生變更。 請注意,恢復設備的自然旋轉存在偏差,對于外形與手機類似的設備通常設置為縱向:
- 當用戶接受旋轉建議時,旋轉首選項變為建議方向。
- 當用戶切換到強制縱向應用(包括鎖定屏幕或啟動器)時,旋轉首選項變為縱向。
下表總結了常見屏幕方向的旋轉行為:
| 未指定、user | 在自動屏幕旋轉和旋轉鎖定下,Activity 可以縱向或橫向(以及顛倒縱向或橫向)呈現。 預期同時支持縱向和橫向布局。 |
| userLandscape | 在自動屏幕旋轉和旋轉鎖定下,Activity 可以橫向或顛倒橫向呈現。 預期只支持橫向布局。 |
| userPortrait | 在自動屏幕旋轉和旋轉鎖定下,Activity 可以縱向或顛倒縱向呈現。 預期只支持縱向布局。 |
| fullUser | 在自動屏幕旋轉和旋轉鎖定下,Activity 可以縱向或橫向(以及顛倒縱向或橫向)呈現。 預期同時支持縱向和橫向布局。 旋轉鎖定用戶將可選擇鎖定到顛倒縱向,通常為 180o。 |
| sensor、fullSensor、sensorPortrait、sensorLandscape | 忽略旋轉鎖定模式首選項,視為自動屏幕旋轉已啟用。 請僅在例外情況下并經過仔細的用戶體驗考量后再使用此項。 |
Apache HTTP 客戶端棄用影響采用非標準 ClassLoader 的應用
在 Android 6.0 中,我們取消了對 Apache HTTP 客戶端的支持。
此變更對大多數不以 Android 9 或更高版本為目標的應用沒有任何影響。 不過,此變更會影響使用非標準?ClassLoader結構的某些應用,即使這些應用不以 Android 9 或更高版本為目標平臺。
如果應用使用顯式委托到系統?ClassLoader?的非標準?ClassLoader,則應用會受到影響。 在?org.apache.http.*?中查找類時,這些應用需要委托給應用?ClassLoader。 如果它們委托給系統?ClassLoader,則應用在 Android 9 或更高版本上將失敗并顯示?NoClassDefFoundError,因為系統?ClassLoader?不再識別這些類。 為防止將來出現類似問題,一般情況下,應用應通過應用?ClassLoader?加載類,而不是直接訪問系統?ClassLoader。
枚舉相機
在 Android 9 設備上運行的應用可以通過調用?getCameraIdList()?發現每個可用的攝像頭。 應用不應假定設備只有一個后置攝像頭或只有一個前置攝像頭。
例如,如果您的應用有一個用來切換前置和后置攝像頭的按鈕,則設備可能有多個前置或后置攝像頭可供選擇。 您應瀏覽一下攝像頭列表,檢查每個攝像頭的特征,然后決定向用戶顯示哪些攝像頭。
?
行為變更:以 API 級別 28+ 為目標的應用
Android 9(API 級別 28)向 Android 系統引入了多項變更。 以下行為變更僅影響以 API 28 或更高級別為目標的應用。 將?targetSdkVersion?設為 API 28 或更高級別的應用必須進行修改,以便正確支持這些行為(如果適用)。
如需了解影響在 Android 9 上運行的所有應用的變更,則無論這些應用以哪個 API 級別為目標,都請參閱行為變更:所有應用。
前臺服務
針對 Android 9 或更高版本并使用前臺服務的應用必須請求?FOREGROUND_SERVICE?權限。 這是普通權限,因此,系統會自動為請求權限的應用授予此權限。
如果針對 Android 9 或更高版本的應用嘗試創建一個前臺服務且未請求?FOREGROUND_SERVICE,則系統會引發?SecurityException。
隱私權變更
如果您的應用以 Android 9 為目標平臺,您應牢記以下行為變更。 對設備序列信息和 DNS 信息進行的這些更新可增強用戶隱私保護。
構建序列號棄用
在 Android 9 中,Build.SERIAL?始終設置為?"UNKNOWN"?以保護用戶的隱私。
如果您的應用需要訪問設備的硬件序列號,您應改為請求?READ_PHONE_STATE?權限,然后調用?getSerial()。
DNS 隱私
以 Android 9 為目標平臺的應用應采用私有 DNS API。 具體而言,當系統解析程序正在執行 DNS-over-TLS 時,應用應確保任何內置 DNS 客戶端均使用加密的 DNS 查找與系統相同的主機名,或停用它而改用系統解析程序。
框架安全性變更
Android 9 包含可提升您的應用安全性的多個行為變更,但這些變更僅在您的應用以 API 級別 28 或更高級別為目標平臺時才會生效:
默認情況下啟用網絡傳輸層安全協議 (TLS)
如果您的應用以 Android 9 或更高版本為目標平臺,則默認情況下?isCleartextTrafficPermitted()?函數返回?false。 如果您的應用需要為特定域名啟用明文,您必須在應用的網絡安全性配置中針對這些域名將?cleartextTrafficPermitted?顯式設置為?true。
按進程分設基于網絡的數據目錄
為改善 Android 9 中的應用穩定性和數據完整性,應用無法再讓多個進程共用同一?WebView?數據目錄。 此類數據目錄一般存儲 Cookie、HTTP 緩存以及其他與網絡瀏覽有關的持久性和臨時性存儲。
在大多數情況下,您的應用只應在一個進程中使用?android.webkit?軟件包中的類,例如?WebView?和?CookieManager。 例如,您應該將所有使用?WebView?的?Activity?對象移入同一進程。 您可以通過在應用的其他進程中調用?disableWebView(),更嚴格地執行“僅限一個進程”規則。 該調用可防止?WebView?在這些其他進程中被錯誤地初始化,即使是從依賴內容庫進行的調用也能防止。
如果您的應用必須在多個進程中使用?WebView?的實例,則必須先利用?WebView.setDataDirectorySuffix()?函數為每個進程指定唯一的數據目錄后綴,然后再在該進程中使用?WebView?的給定實例。 該函數會將每個進程的網絡數據放入其在應用數據目錄內自己的目錄中。
注:即使您使用?setDataDirectorySuffix(),系統也不會跨應用的進程界限共享 Cookie 以及其他網絡數據。 如果應用中的多個進程需要訪問同一網絡數據,您需要自行在這些進程之間復制數據。 例如,您可以調用?getCookie()?和?setCookie(),在不同進程之間手動傳輸 Cookie 數據。
以應用為單位的 SELinux 域名
以 Android 9 或更高版本為目標平臺的應用無法利用可全球訪問的 Unix 權限與其他應用共享數據。 此變更可改善?Android 應用沙盒的完整性, 具體地講,就是要求應用的私有數據只能由該應用訪問。
要與其他應用共享文件,請使用?content provider。
連接變更
連接數據計數和多路徑
在以 Android 9 或更高版本為目標平臺的應用中,系統計算并非當前默認網絡的網絡流量,例如,當設備連接 WLAN 時的蜂窩流量,并在?NetworkStatsManager?類中提供函數以查詢該流量。
具體而言,getMultipathPreference()?現在將返回一個基于上述網絡流量的值。 從 Android 9 開始,此函數針對蜂窩數據返回?true,但當超過一天內累積的特定流量時,它將開始返回?false。 在 Android 9 上運行的應用必須調用此函數并采用此提示。
ConnectivityManager.NetworkCallback?類現在將有關 VPN 的信息發送到應用。 此變更讓應用偵聽連接事件變得更容易,而無需混用同步和異步調用,也無需使用有限的 API。 此外,它還意味著將設備同時連接至多個 WLAN 網絡或多個蜂窩網絡時,信息傳輸可按預期工作。
Apache HTTP 客戶端棄用
在 Android 6.0 中,我們取消了對 Apache HTTP 客戶端的支持。 從 Android 9 開始,默認情況下該內容庫已從 bootclasspath 中移除且不可用于應用。
要繼續使用 Apache HTTP 客戶端,以 Android 9 及更高版本為目標的應用可以向其?AndroidManifest.xml?添加以下內容:
<uses-library android:name="org.apache.http.legacy" android:required="false"/>?
注:擁有最低 SDK 版本 23 或更低版本的應用需要?android:required="false"?屬性,因為在 API 級別低于 24 的設備上,org.apache.http.legacy?庫不可用。 (在這些設備上,Apache HTTP 類在 bootclasspath 中提供。)
作為使用運行時 Apache 庫的替代,應用可以在其 APK 中綁定自己的?org.apache.http?庫版本。 如果進行此操作,您必須將該庫重新打包(使用一個類似?Jar Jar?的實用程序)以避免運行時中提供的類存在類兼容性問題。
界面變更
視圖焦點
0 面積的視圖(即寬度或高度為 0)再也不能被聚焦。
此外,Activity 不再隱式分配觸摸模式下的初始焦點。 而是由您顯式請求初始焦點(如若需要的話)。
CSS RGBA 十六進制值處理
以 Android 9 或更高版本為目標的應用必須支持草案版?CSS 顏色模塊級別 4?的行為,用于處理 4 和 8 個十六進制數字 CSS 顏色。
Chrome 自版本 52 以來便一直支持 CSS 顏色模塊級別 4,但?WebView?目前停用此功能,因為現有 Android 應用被發現包含 Android ordering (ARGB) 中的 32 位十六進制顏色,這會導致渲染錯誤。
例如,對于以 API 級別 27 或更低版本為目標平臺的應用,顏色?#80ff8080?目前在?WebView?中被渲染為不透明淺紅色 (#ff8080)。 先導部分(Android 會將其解讀為 Alpha 部分)目前被忽略。 如果某個應用以 API 級別 28 或更高版本為目標,則?#80ff8080?將被解讀為 50% 透明淺綠 (#80ff80)。
文檔滾動標簽
Android 9 可正確處理文檔的根標簽是滾動標簽的案例。 在之前的版本中,滾動位置在 body 標簽上設置,根標簽的滾動值為零。 Android 9 支持符合標準的行為,在這種行為中,滾動標簽是根標簽。
此外,直接訪問?document.body.scrollTop、document.body.scrollLeft、document.documentElement.scrollTop?或?document.documentElement.scrollLeft?會因目標 SDK 的不同而具有不同的行為。 要訪問視口滾動值,請使用?document.scrollingElement(若有)。
來自已暫停應用的通知
在 Android 9 之前,暫停的應用發出的通知會被取消。 從 Android 9 開始,暫停的應用發出的通知將被隱藏,直至應用繼續運行。
將應用遷移到 Android 9
Android 9(API 級別 28)引入了一些您的應用可加以利用的新功能和 API,以及新行為變更。本文概述了將應用遷移到 Android 9 的兩個關鍵階段的步驟:
驗證您的現有應用能夠在新版本平臺上全功能運行。在此階段,您不需要使用新的 API,也不需要更改應用的?targetSdkVersion,但可能需要進行一些細微的更改。
當您準備好利用平臺的新功能時,將?targetSdkVersion?更新至“28”,驗證應用是否仍可按預期方式運行,然后開始使用新的 API。
準備一臺運行 Android 9 的設備
如果您有一臺兼容設備,則從制造商那里獲取設備的 Android 9 系統鏡像;點擊此處獲取?Pixel 設備的出廠鏡像。刷寫系統鏡像的一般說明位于此處。
您還可以為 Android Emulator 下載 Android 9 系統鏡像。它列于?SDK 管理器的?Android 9?下,顯示為?Google APIs Intel x86 Atom System Image。
注:Android 9 模擬器系統鏡像可在?Android Studio 3.1?及更高版本中下載;Android Studio 3.2?提供最佳兼容性。如需了解詳細信息,請參閱獲取 Android 9 SDK。
確保與 Android 9 兼容
這一步的目標是確保您的現有應用在 Android 9 上可照常運行。由于一些平臺變更可能影響應用的行為方式,因此可能需要進行一些調整,但您不需要使用新的 API 或更改?targetSdkVersion。
執行兼容性測試
與 Android 9 的兼容性測試多半與您準備發布應用時執行的測試屬于同一類型。這時有必要回顧一下核心應用質量指南和測試最佳實踐。
不過,測試還有另一個層面:Android 9 向 Android 平臺引入了一些變化,即便不對?targetSdkVersion?做任何變動,仍可能影響應用的行為或令其根本無法運行。因此,您必須回顧表 1 中的關鍵變化,并對任何為適應這些變化而實現的修復進行測試。
表 1.?對在 Android 9 設備上運行的所有應用都有影響的關鍵變化。
| 對非 SDK 接口的限制 | 現已禁止訪問特定的非 SDK 接口,無論是直接訪問,還是通過 JNI 或反射進行間接訪問。嘗試訪問受限制的接口時,會生成?NoSuchFieldException?和?NoSuchMethodException?之類的錯誤。詳情請參閱對非 SDK 接口的限制。 |
| 移除加密提供程序 | 從 Android 9 開始,Crypto JCA 提供程序已被移除。調用?SecureRandom.getInstance("SHA1PRNG", "Crypto")?將會引發?NoSuchProviderException。 |
| 更嚴格的 UTF-8 解碼器 | 在 Android 9 中,針對 Java 語言的 UTF-8 解碼器比以往更嚴格,并且遵循 Unicode 標準。 |
| 禁止空閑應用訪問相機、麥克風和傳感器 | 在應用處于空閑狀態時,不能再訪問相機、麥克風或 SensorManager 傳感器。 |
如需查看針對在 Android 9 上運行的所有應用的更詳盡行為變更列表,請參閱行為變更文檔。
更新您的目標版本并使用 Android?P 功能
本部分解釋如何通過將您的?targetSdkVersion?更新為 28 并增加 Android 9 中提供的新功能來實現對 Android 9 的全面支持。
除提供新 API 之外,在您將?targetSdkVersion?更新為 28 時,您會注意到 Android 9 還引入了一些行為變更。由于某些行為變更可能要求更改代碼以避免沖突,因此,您應先查閱所有以 Android 9 為目標的應用的行為變更,了解在您更改?targetSdkVersion?后您的應用會受到哪些影響。
注:上述旨在確保平臺兼容性的步驟是將應用以 Android 9 為目標的先決條件,因此請您務必先完成這些步驟。
獲取 Android 9 SDK
您可以使用?Android Studio 3.1?或更高版本獲取 SDK 軟件包,以便利用 Android 9 構建應用。如果您暫時不需要 Android 9 中的新功能,只想針對該平臺版本進行編譯,您可以使用?Android Studio 3.1。Android Studio 3.2?提供了對 Android 9 功能的全面支持。
要設置任一版本的 Android Studio,請按照設置 Preview SDK?中介紹的步驟操作。
測試 Android 9 應用
完成以上準備工作后,您就可以構建應用,然后對其做進一步測試,確保以 Android 9(API 級別 28)為目標平臺時它能正常工作。這時有必要再次回顧一下核心應用質量指南和測試最佳實踐。
如果您構建應用時將?targetSdkVersion?設置為 P,應該注意特定的平臺變化。即便您不實現 Android 9 中的新功能,其中的一些變化仍可能嚴重影響應用的行為或令其根本無法運行。
表 2 列出了這些變化以及可獲得更多信息的鏈接。
表 2.?targetSdkVersion?設置為 28 時影響應用的關鍵變化。
| 前臺服務權限 | 現在,想要使用前臺服務的應用必須首先請求 FOREGROUND_SERVICE 權限。這是普通權限,因此,系統會自動為請求權限的應用授予此權限。在未獲得此權限的情況下啟動前臺服務將會引發 SecurityException。 |
| 棄用 Bouncy Castle 加密 | Android 9 棄用了幾個來自 Bouncy Castle 提供程序中的加密技術,代之以由 Conscrypt 提供程序提供的加密技術。調用請求 Bouncy Castle 提供程序的?getInstance()?時,會生成?NoSuchAlgorithmException?錯誤。要解決這些錯誤,請不要在 getInstance() 中指定提供程序(也就是請求默認實現)。 |
| 移除對?Build.serial的直接訪問 | 現在,需要 Build.serial 標識符的應用必須請求?READ_PHONE_STATE?權限,然后使用 Android 9 中新增的新?Build.getSerial()?函數。 |
| 不允許共享 WebView 數據目錄 | 現在,不允許應用在不同進程之間共享一個 WebView 數據目錄。如果您的應用有多個進程使用 WebView、CookieManager 或 android.webkit 軟件包中的任何其他 API,則在第二個進程調用 WebView 函數時,您的應用將會崩潰。 |
| SELinux 禁止訪問應用的數據目錄 | 系統強制每個應用的 SELinux 沙盒對每個應用的私有數據目錄強制執行逐個應用的 SELinux 限制。現在,不允許直接通過路徑訪問其他應用的數據目錄。應用可以繼續使用進程間通信 (IPC) 機制(包括通過傳遞 FD)共享數據。 |
如需查看針對以 Android 9 為目標的應用的更詳盡行為變更列表,請參閱行為變更文檔。
要探索 Android 9 中的新功能和 API,請參閱?Android 9 功能和 API。
?
電源管理
Android 9(API 級別 28)引入了一些新功能來改進設備電源管理。 這些變化,連同先前版本中已經存在的功能,有助于確保將系統資源提供給最需要它們的應用。
電源管理功能可以分為兩個類別:
應用待機群組
系統將根據用戶的使用模式限制應用對 CPU 或電池等設備資源的訪問。 這是 Android 9 中新增的一項功能。
省電模式改進
開啟省電模式后,系統會對所有應用施加限制。 這是一項已有的功能,但在 Android 9 中得到了改進。
注:這些變化適用于所有應用,無論它們是否以 Android 9 為目標。
應用待機群組
Android 9 引入了一項新的電池管理功能,即應用待機群組。 應用待機群組可以基于應用最近使用時間和使用頻率,幫助系統排定應用請求資源的優先級。 根據使用模式,每個應用都會歸類到五個優先級群組之一中。 系統將根據應用所屬的群組限制每個應用可以訪問的設備資源。
五個群組按照以下特性將應用分組:
活躍
如果用戶當前正在使用應用,應用將被歸到“活躍”群組中,例如:
- 應用已啟動一個 Activity
- 應用正在運行前臺服務
- 應用的同步適配器與某個前臺應用使用的 content provider 關聯
- 用戶在應用中點擊了某個通知
如果應用處于“活躍”群組,系統不會對應用的作業、報警或 FCM 消息施加任何限制。
工作集
如果應用經常運行,但當前未處于活躍狀態,它將被歸到“工作集”群組中。 例如,用戶在大部分時間都啟動的某個社交媒體應用可能就屬于“工作集”群組。 如果應用被間接使用,它們也會被升級到“工作集”群組中 。
如果應用處于“工作集”群組,系統會對它運行作業和觸發報警的能力施加輕度限制。 如需了解詳細信息,請參閱電源管理限制。
常用
如果應用會定期使用,但不是每天都必須使用,它將被歸到“常用”群組中。 例如,用戶在健身房運行的某個鍛煉跟蹤應用可能就屬于“常用”群組。
如果應用處于“常用”群組,系統將對它運行作業和觸發報警的能力施加較強的限制,也會對高優先級 FCM 消息的數量設定限制。 如需了解詳細信息,請參閱電源管理限制。
極少使用
如果應用不經常使用,那么它屬于“極少使用”群組。 例如,用戶僅在入住酒店期間運行的酒店應用就可能屬于“極少使用”群組。
如果應用處于“極少使用”群組,系統將對它運行作業、觸發警報和接收高優先級 FCM 消息的能力施加嚴格限制。系統還會限制應用連接到網絡的能力。 如需了解詳細信息,請參閱電源管理限制。
從未使用
安裝但是從未運行過的應用會被歸到“從未使用”群組中。 系統會對這些應用施加極強的限制。
系統會動態地將每個應用歸類到某個優先級群組,并根據需要重新歸類。 系統可能會依靠某個使用機器學習的預加載應用確定每個應用的使用可能性,并將應用歸類到合適的群組。 如果設備上不存在系統應用,系統默認將基于應用的最近使用時間對它們進行排序。 更為活躍的應用將被歸類到為應用提供更高優先級的群組,從而讓應用可以使用更多系統資源。 具體而言,群組決定應用運行作業的頻率,應用可以觸發報警的頻率,以及應用可以接收高優先級?Firebase 云信息傳遞?(FCM)?消息的頻率。 這些限制僅在設備使用電池電量時適用,如果設備正在充電,系統不會對應用施加這些限制。
每個制造商都可以設定自己的標準來歸類非活躍應用。 您不應當嘗試影響應用所屬的群組。 相反,您應當將精力放在確保應用在所屬的群組內良好運行上。 您的應用可以通過調用新函數?UsageStatsManager.getAppStandbyBucket()?查找當前屬于哪個群組。
注:位于?低電耗模式白名單中的應用不適用基于應用待機群組的限制。
最佳實踐
如果您的應用已遵循低電耗模式和應用待機模式的最佳實踐,那么處理新的電源管理功能不應是難事。 不過,之前正常運行的一些應用行為現在可能會引起問題。
- 不要讓系統處于一種不斷變換應用所屬群組的狀態。 系統的分組方式可以變化,每個設備制造商都可以選擇使用自己的算法編寫分組應用。 相反,請確保您的應用無論處于哪一個分組時行為都很恰當。
- 如果應用沒有啟動器 Activity,那么它可能永遠不會升級到“活躍”分組中。 您需要重新設計應用,使之具有此類 Activity。
- 如果應用的通知不可操作,用戶與通知交互將無法觸發應用向“活躍”群組的升級。 在這種情況下,您需要重新設計某些適當的通知,讓它們允許用戶響應。 如需了解一些指導原則,請參閱 Material Design?通知設計模式。
-
類似地,如果應用在收到高優先級 FCM 消息時不顯示通知,那么它不會向用戶提供與應用交互的機會,也不會借此升級到“活躍”群組中。 事實上,高優先級 FCM 消息的唯一預期目的是向用戶推送通知,因此,這種情況永遠都不應發生。 如果您在某條 FCM 消息不觸發用戶交互時將其錯誤地標記為高優先級,它可能引起其他不良后果;例如,它可能導致您的應用耗盡配額,導致真正緊急的 FCM 消息被視為一般優先級。
注:如果用戶重復忽略了某個通知,系統將向用戶提供未來阻止該通知的選項。 請不要為了讓您的應用處于“活躍”群組而向用戶濫發通知!
?
-
如果應用分為多個軟件包,那么這些軟件包可能處于不同的群組中,進而擁有不同的訪問權限級別。 請務必對軟件包被歸類到各個群組的此類應用進行測試,以便確保應用行為正常。
省電模式改進
Android 9 對省電模式進行了多處改進。 設備制造商可以決定施加的確切限制。 例如,在 AOSP 構建中,系統會應用以下限制:
- 系統會更積極地將應用置于應用待機模式,而不是等待應用空閑。
- 后臺執行限制適用于所有應用,無論它們的目標 API 級別如何。
- 當屏幕關閉時,位置服務可能會被停用。
- 后臺應用沒有網絡訪問權限。
此外,還有一些設備特定的其他電源優化。 如需了解詳細信息,請參閱附錄: 電源管理限制。
一如既往,一種比較好的做法是在省電模式激活時對您的應用進行測試。 您可以通過設備的?Settings > Battery Saver?界面手動開啟省電模式。
測試和問題排查
新的電源管理功能會影響在 Android 9 設備上運行的所有應用,無論應用是否以 Android 9 為目標。務必確保您的應用在這些設備上行為正常。
務必在各種條件下測試您的應用的主要用例,以便了解電源管理功能彼此之間的交互。 您可以使用?Android 調試橋命令開關某些功能。
Android 調試橋命令
您可以使用?Android 調試橋?shell 命令測試多個電源管理功能。
如需了解使用 ADB 將設備置于低電耗模式的信息,請參閱在低電耗模式和應用待機模式下進行測試。
應用待機群組
您可以使用 ADB 為您的應用手動指定應用待機群組。 要更改應用的群組,請使用以下命令:
$ adb shell am set-standby-bucket packagename active|working_set|frequent|rare?
您還可以使用該命令一次設置多個軟件包:
$ adb shell am set-standby-bucket package1 bucket1 package2 bucket2...?
要檢查應用處于哪一個群組,請運行以下命令:
$ adb shell am get-standby-bucket [packagename]?
如果您不傳遞?packagename?參數,命令將列出所有應用的群組。 應用還可以調用新函數?UsageStatsManager.getAppStandbyBucket(),在運行時查找所屬的群組。
省電模式
可以使用多個命令測試您的應用在低電量條件下的行為。
注:您還可以使用設備的?Settings > Battery saver?界面將設備置于省電模式。
要模擬拔下設備電源時的情形,請使用以下命令:
$ adb shell dumpsys battery unplug?
要測試設備在低電量條件下的行為,請使用以下命令:
$ adb shell settings put global low_power 1?
完成測試后,您可以使用以下命令撤消設備的手動設置:
$ adb shell dumpsys battery reset總結
以上是生活随笔為你收集整理的Android 9 Pie的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 讯时用例图
- 下一篇: 条形码控件TBarCode SDK系列教