Android O要來了,大家准備好了嗎? -开发者知识库

Android O要來了,大家准備好了嗎? -开发者知识库,第1张

Android O 要來了,大家准備好了嗎?

本文繼續擔當一下搬運工,能爬牆的,直接去這里

Android O 行為變更

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

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

針對所有 API 級別的應用

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

后台執行限制

Android O 為提高電池壽命而引入的變更之一是,當您的應用進入已緩存狀態時,如果沒有活動的組件,系統將解除應用具有的所有喚醒鎖。

leobert注:這意味着曾經的一些長時間后台service,自喚醒廣播等實現方案將不再可靠。

Android 后台位置限制

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

此類變更會影響以下 API:

  • Fused Location Provider (FLP)
  • Geofencing
  • GNSS Measurements
  • Location Manager

Android O 還對特定方法做出了以下變更:

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

  • 查看您的應用的邏輯,並確保您使用的是最新的位置 API。
  • 測試您的應用是否在每個用例中都表現出預期行為。
  • 考慮使用 Fused Location Provider (FLP) 或地理圍欄來處理依賴於用戶當前位置的用例。(注,這個自動翻譯不咋地)

詳細信息,請參閱后台位置限制(注:這個去爬牆看吧)。

藍牙

Android O 對 ScanRecord.getBytes() 函數檢索的數據長度做出了以下變更:

  • getBytes() 方法對於所接收的字節數不作任何假定。因此,應用不應受所返回的任何最小或最大字節數的影響。相反,應用應當計算所返回數組的長度。
  • 兼容藍牙 5 的設備返回的數據長度可能會超出之前最大 60 個字節的限制。
  • 如果遠程設備未提供掃描響應,則也可能返回少於 60 個字節的數據。

leobert注:按照字節數的判斷將不再可靠

輸入和導航

隨着 Android 應用出現在 Chrome 操作系統和平板電腦等其他大尺寸設備上,我們看到,用戶在 Android 應用中又重新開始使用鍵盤導航。在 Android O 中,我們又再次使用鍵盤作為導航輸入設備,從而為基於箭頭和標簽的導航構建了一種更可靠並且可預測的模型。

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

leobert注:鍵盤導航並不是一個新的概念,如果對這個不熟悉,可以看一下這里,大體上來說,是連接鍵盤使用tab和方向鍵切換焦點。

無障礙功能

現在,無障礙服務可識別應用的 TextView 對象內部的所有 ClickableSpan 實例。

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

leobert注:這似乎又可以搞事情?

安全性

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

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

leobert注:
SSLv3 不安全,早就說要丟掉了,比如看這里
現在大家應該用的是或者基於okhttp或者Apache的httpclient(一些遺留的)
WebView這個可能會帶來一些影響(未測試驗證):JS調用native代碼,JS通過內核訪問數據

隱私性

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。此項變更使行為符合文檔要求。

摘抄一段Collection接口的doc:
@throws NullPointerException if this collection contains one or more null elements and the specified collection does not support null elements (optional), or if the specified collection is null

語言區域和國際化

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。

權限

leobert注: 該部分很重要,之前的單權限獲取將會獲取整個權限組權限將不再可靠。使用一些

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

寫在最后

扒了一大堆東西,排版的時候順便再細看了一遍,感覺越來越“正規”,但國產rom讓人很擔心,國內的普及速度讓人絕望,適配到Android4.4讓人很心塞

最佳答案:

本文经用户投稿或网站收集转载,如有侵权请联系本站。

发表评论

0条回复