在前幾天的Google I/O 2019大會上,發佈了Android Q版本(Android 10)。Android Q帶來了許多新特性,也增強安全隱私保護,包括支持摺疊屏、非SDK接口限制、共享內存、分區存儲、系統二進制文件映射到只執行內存、WLAN直連廣播、全屏Intent的權限變更、夜間主題模式等等。
1、非SDK接口限制
爲了確保應用穩定性與兼容性,Android平臺開始限制我們的應用可在Android 9以上使用哪些非 SDK 接口。Android Q包含更新後的受限非SDK接口列表。目前我們還可以使用灰名單來訪問非SDK接口,但如果使用任何非SDK方法或字段,可能會導致應用程序無法運行(通過反射機制來訪問SDK方法或字段將會失效)。
2、共享內存
Ashmem修改了/proc/<pid>/maps中Dalvik的映射格式,這會影響到那些直接解析映射文件的應用。如果應用需要依賴Dalvik映射格式,我們應該在設備上測試新的/proc/<pid>/maps格式並進行相應解析。以Android Q爲目標平臺的應用無法直接使用Ashmen,必須通過NDK的 ASharedMemory
類來訪問共享內存。另外,應用無法對現有的Ashmem文件描述符進行IOCTL,必須改爲NDK的ASharedMemory類或者Android Java API來創建共享內存區域。這個變更可以提高訪問共享內存的安全性與穩定性。
3、支持摺疊屏
Android Q包含可摺疊屏和大屏設備。當應用在Android Q平臺運行時,onResume()和onPause()方法的工作原理是不同的。當多個應用同時在多窗口或多顯示屏模式下顯示時,可見堆棧中所有可設置爲焦點的頂層Activity都處於“已恢復”狀態,但實際上焦點僅位於其中一個Activity。在Android Q之前版本運行時,一次只能恢復系統中的一個Activity,而所有其他可見Activity都處於暫停狀態。
在Android Q中,我們可以訂閱onTopResumedActivityChanged()回調,以便在Activity獲取或失去最頂層處於恢復狀態的位置後收到通知。
resizeableActivity
清單屬性的行爲也發生了變化。如果設置了resizeableActivity=false,但沒有設置固定屏幕方向或者寬高比,則屏幕尺寸、屏幕方向變化會導致應用調整大小以佔滿整個屏幕。如果設置了resizeableActivity=false,也設置固定屏幕方向或寬高比,那麼屏幕發生變化後,應用會顯示黑邊並調整大小以保持相應的寬高比。如果設置爲resizeableActivity=true,應用會保持原樣,並調整大小。
應用可以聲明 1:1 的寬高比,並且可以使用新屬性 android:minAspectRatio
4、系統二進制文件映射到只執行內存
從Android Q開始,系統二進制文件和庫會映射到只執行(不可讀取)內存中,作爲應對代碼重用攻擊的安全強化技術。如果讀入已標記爲只執行的內存段會拋出SIGSEGV異常,無論此讀入行爲來自錯誤、漏洞或內存自省都不例外。我們可以通過檢查/data/tombstones/的tombstones文件來確定崩潰是否由更改所導致。崩潰消息:
Cause: execute-only (no-read) memory access error; likely due to data in .text.
要解決此問題,我們可以調用mprotect()將只執行內存段標記爲“讀取+執行”,例如用於內存執行檢查。但是,Google官方建議我們,保留爲只執行屬性。
5、SYSTEM_ALERT_WINDOW彈窗
在Android Q設備上運行的應用無法獲取SYSTEM_ALERT_WINDOW
權限。這是因爲繪製疊加層窗口使用過多內存,這對於低內存設備十分不利。如果應用發送具有ACTION_MANAGE_OVERLAY_PERMISSION的Intent請求,則系統默認拒絕此請求,並將用戶轉到設置屏幕,顯示不允許授予此權限,因爲它降低設備速度。
6、全局夜間主題模式(Dark Theme)
從Android Q開始,用戶可通過以下三種途徑激活新的全局夜間模式:
(1)點擊設置,進入顯示;
(2)新的快捷設置;
(3)啓動省電模式;
在夜間模式下,系統界面會變暗,而提供支持的應用也會同時啓用夜間模式。我們可爲應用開發專屬的夜間主題,或者開啓"強制變暗"(Force Dark)功能,讓操作系統爲現有主題重新創建一個夜間版本。我們只需要在應用的當前主題內設置android:forceDarkAllowed="true"即可。
7、WLAN直連廣播
在Android Q中,與 WLAN 直連相關的廣播不再具有粘性:
如果需要用到這些廣播,請在初始化時用get()方法獲取。
8、全屏Intent的權限變更
使用全屏Intent的應用,必須在其應用的清單文件中請求 USE_FULL_SCREEN_INTENT
權限。如果沒聲明USE_FULL_SCREEN_INTENT
,則系統會忽略此全屏 Intent 並輸出以下日誌消息:Package [pkg]: Use of fullScreenIntent requires the USE_FULL_SCREEN_INTENT permission。
9、分區存儲
爲了讓用戶更好地控制自己的文件,並限制文件出現混亂,Android更改了應用訪問設備外部存儲空間中文件的方式。Android Q用更精細的媒體特定權限來代替READ_EXTERNAL_STORAGE
和 WRITE_EXTERNAL_STORAGE權限,並且無需特定權限,應用即可訪問自己在外部存儲設備的文件。
對於每個應用,Android Q會創建一個"隔離存儲沙盒"。應用可以將文件存儲於自己沙盒中,也可以存儲於媒體和下載內容的通用集合中。
10、Location位置權限
Android Q可讓用戶更好控制應用何時能夠訪問設備位置信息。當在Android Q上運行的應用請求位置訪問權限時,會彈出圖1對話框。此對話框可讓用戶將位置信息訪問權限授予到兩個不同的範圍:在使用中(僅限前臺)或始終(前臺和後臺)。
Android Q引入新的位置權限:ACCESS_BACKGROUND_LOCATION。與現有ACCESS_FINE_LOCATION和ACCESS_COARSE_LOCATION權限不同的是,新權限僅會影響應用在後臺運行時對位置信息的訪問權。除非應用的某個 Activity 可見或應用正在運行前臺服務,否則應用將被視爲在後臺運行。可用如下代碼來檢測位置權限:
boolean permissionAccessCoarseLocationApproved =
ActivityCompat.checkSelfPermission(this, permission.ACCESS_COARSE_LOCATION)
== PackageManager.PERMISSION_GRANTED;
if (permissionAccessCoarseLocationApproved) {
boolean backgroundLocationPermissionApproved =
ActivityCompat.checkSelfPermission(this,
permission.ACCESS_BACKGROUND_LOCATION)
== PackageManager.PERMISSION_GRANTED;
if (backgroundLocationPermissionApproved) {
// 可在前臺和後臺訪問位置信息
} else {
// 只能在前臺訪問位置信息
ActivityCompat.requestPermissions(this, new String[] {
Manifest.permission.ACCESS_BACKGROUND_LOCATION},
your-permission-request-code);
}
} else {
// 沒有訪問位置信息的權限,需要申請
ActivityCompat.requestPermissions(this, new String[] {
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_BACKGROUND_LOCATION
},
your-permission-request-code);
}
11、後臺Activity啓動
Android Q對應用可啓動Activity的事件作了限制。此變更能最大限度減少對用戶的中斷,並且可以讓用戶更好地控制屏幕顯示的內容。在Android Q運行的應用,只有滿足以下一個或多個條件纔可以啓動Activity:
- 該應用具有可見窗口,例如在前臺運行的 Activity。
- 在前臺運行的另一個應用會發送屬於該應用的
PendingIntent
。示例包括髮送菜單項待定 intent 的自定義標籤頁提供程序。 - 系統發送屬於該應用的
PendingIntent
,例如點按通知。只有應用應啓動界面的待定 intent 纔可以免除。 - 系統嚮應用發送廣播,例如
SECRET_CODE_ACTION
。只有應用應啓動界面的特定廣播纔可以免除。
幾乎所有情況下,後臺都應該創建通知以便向用戶提供信息,而不是直接啓動Activity。
12、數據和標識符變更
在Android Q中,對訪問數據和系統標識符作了限制,包括:聯繫人親密程度、隨機選擇MAC地址、訪問/proc/net文件系統、訪問USB串行設備需要用戶授權等。
①聯繫人親密程度
從Android Q開始,平臺不再跟蹤聯繫人的互動親密程度。因此,我們的應用對用戶的聯繫人進行搜索,系統不再按互動頻率對搜索結果排序。
②隨機選擇MAC地址
默認情況下,Android Q設備會傳輸隨機選擇的MAC地址。新增了兩個API:
- 獲取隨機選擇的 MAC 地址:設備所有者應用和個人資料所有者應用可以通過調用
getRandomizedMacAddress()
檢索分配給特定網絡的隨機選擇 MAC 地址。 - 獲取實際的出廠 MAC 地址:設備所有者應用可以通過調用
getWifiMacAddress()
檢索設備的實際硬件 MAC 地址。此方法對於跟蹤設備隊列非常有用。
③訪問/proc/net文件系統
Android Q 撤消了 /proc/net
訪問權限,其中包含有關設備網絡狀態的信息。需要訪問此信息的應用(如 VPN)應引用 NetworkStatsManager
和 ConnectivityManager
類。
④訪問USB串行設備需要用戶授權
以 Android Q 爲目標的平臺,我們的應用只能在用戶授予其訪問 USB 設備或配件的權限後才能讀取序列號。
13、網絡權限變更
①訪問所有相機信息都需要權限
Android Q 更改了 getCameraCharacteristics()
方法默認返回的信息的廣度。具體而言就是,您的應用必須具有 CAMERA
權限才能訪問此方法的返回值中可能包含的設備特定元數據。
②啓動與停用WLAN的限制
在Android Q上運行的應用無法啓用或停用WLAN。WifiManager.setWifiEnabled()方法始終會返回false。如果需要啓用或停用WLAN,需要使用設置面板提示用戶啓用和停用 WLAN。
③WLAN網絡配置限制
爲了保護用戶隱私,現在只能對手動配置系統的 WLAN 網絡列表。如果您的應用以 Android Q 爲目標平臺,則下列方法將不再返回有用數據:
getConfiguredNetworks()
方法始終返回空列表。- 每個返回整數值的網絡操作方法(
addNetwork()
和updateNetwork()
)始終返回 -1。 - 每個返回布爾值的網絡操作(
removeNetwork()
、reassociate()
、enableNetwork()
、disableNetwork()
、reconnect()
和disconnect()
)始終返回false
。
如果應用程序需要連接到 WLAN 網絡,請使用以下備用方法:
- 要觸發與 WLAN 網絡的即時本地連接,請在標準
NetworkRequest
對象中使用WifiNetworkSpecifier
。 - 要添加 WLAN 網絡以便考慮爲用戶提供互聯網訪問權限,請使用 WifiNetworkSuggestion 對象。您可以通過分別調用
WifiManager.addNetworkSuggestions()
和WifiManager.removeNetworkSuggestions()
添加和移除顯示在自動連接網絡選擇對話框中的網絡。這些方法不需要任何位置權限。