天天看點

Android R 新特性分析及适配指南

Android R(Android 11 API 30)于2020年9月9日正式釋出,随國内各終端廠商在售Android裝置的版本更新更新,應用軟體對Android R 版本的相容适配已迫在眉睫。

對于Android R的新特性,這裡按照以下幾個方面進行了歸納:`分區存儲、權限、隐私、性能、安全`。

對于Android R的新特性,這裡按照以下幾個方面進行了歸納:<code>分區存儲、權限、隐私、性能、安全</code>。

官方文檔描述:https://developer.android.google.cn/about/versions/11

從Android 10(API 29)開始,Android<code>預設開啟分區存儲</code>功能,不過Android 10 可通過增加<code>android:requestLegacyExternalStorage="true"</code>配置<code>停用分區存儲</code>;

從Android 11(API 30)開始,<code>強制執行分區存儲</code>,對于Android 11及以上裝置,<code>android:requestLegacyExternalStorage="true"</code>配置将不再有效。

Android 11 分區存儲官方描述:

https://developer.android.google.cn/training/data-storage#scoped-storage

Android 10 預設開啟分區存儲:

https://xiaxl.blog.csdn.net/article/details/103125117

開啟分區存儲後,應用預設情況下隻能通路<code>應用專屬目錄(内部存儲、外部存儲應用專屬目錄)</code>,以及<code>本應用所建立的特定類型的媒體檔案</code>。

應用專屬目錄

包括<code>内部存儲</code>、<code>外部存儲專屬目錄</code>(若應用包名com.xiaxl.demo):

<code>/data/data/com.xiaxl.demo/files,</code>

<code>/sdcard/Android/data/com.xiaxl.demo/files</code>

分别采用以下API進行通路:

<code>File appFile = new File(context.getFilesDir(), filename);</code>

<code>File appExternalFile = new File(context.getExternalFilesDir(), filename);</code>

共享存儲目錄

包括媒體、文檔和其他檔案。例如DCIM、Pictures、Movies、Download等目錄;

注:

<code>Android 10(Android Q)中共享存儲目錄使用MediaStore API通路;</code>

<code>Android 11(Android R)中共享存儲目錄支援MediaStore API與File API通路。</code>

為保證應用在Android 10、Android 11裝置中,使用<code>File API對共享存儲目錄具有相同的檔案通路權限</code>。建議在應用 AndroidManifest配置檔案中,增加<code>requestLegacyExternalStorage="true"</code>辨別,以<code>關閉Android 10裝置上的分區存儲功能</code>,使<code>分區存儲隻對Android 11以上裝置生效</code>:

應用專屬目錄(<code>内部存儲</code>、<code>外部存儲專屬目錄</code>)的讀寫,Android 4.4以上裝置不需要任何權限;

共享存儲路徑的讀寫,需要<code>READ_EXTERNAL_STORAGE</code>與<code>WRITE_EXTERNAL_STORAGE</code> 權限;

Android R 新特性分析及适配指南

Android 11以上裝置中,如果您的應用再次請求<code>READ_EXTERNAL_STORAGE</code>權限時,動态權限申請彈窗将變化為<code>“您的應用正在請求通路照片和媒體”</code>。

Android R 新特性分析及适配指南

檔案媒體通路 官方描述:

如果需要與其他應用共享單個檔案或應用資料,可以使用API:

<code>FileProvider</code>(分享自己的一個或多個檔案)

如果應用需要将自己的一個或多個檔案提供給其他應用,安全的做法是向接收方應用發送檔案的内容 URI,并授予對該 URI 的臨時通路權限。

Android <code>FileProvider</code> 元件提供了 <code>getUriForFile()</code> 方法,用于生成檔案的内容 <code>URI</code>。

<code>ContentProvider</code>(擷取替他應用提供的資料)

如果您需要向其他應用提供資料,可以使用<code>ContentProvider</code>。

<code>ContentProvider</code>是一種标準接口,可将一個程序中的資料與另一個程序中運作的代碼進行連。

Android R 新特性分析及适配指南

Android 11 共享檔案官方描述:

有一些應用需要擷取所有檔案的通路權限,例如:檔案管理器軟體。

擷取所有檔案的通路權限,可申請<code>MANAGE_EXTERNAL_STORAGE</code>權限。

<code>MANAGE_EXTERNAL_STORAGE</code>相關官方描述:

https://developer.android.google.cn/training/data-storage/manage-all-files

Android 11 中對權限進行了如下更改:

新增 <code>READ_PHONE_NUMBERS</code>權限,擷取手機号碼;

<code>背景通路位置</code>權限調整;

使用者<code>多次針對某項特定的權限請求</code>點<code>拒絕</code>,表示使用者希望<code>不再詢問</code>;

應用<code>長時間未使用</code>,系統會<code>自動重置使用者已授予敏感權限</code>;

針對<code>位置、麥克風、攝像頭</code>授權彈窗新增<code>僅限這一次</code>授權按鈕;

<code>SYSTEM_ALERT_WINDOW</code> 權限授權方式改變為系統自動授權;

參考 Android 11 權限更新官方文檔:

https://developer.android.google.cn/about/versions/11/privacy/permissions#one-time

當應用的 <code>targetSdkVersion&gt;=30</code> 時,使用以下API<code>擷取手機号碼</code>時,需要申請<code>READ_PHONE_NUMBERS</code>權限,而不再是<code>READ_PHONE_STATE</code> 權限。

<code>TelephonyManager</code> 類和 <code>TelecomManager</code> 類中的 <code>getLine1Number()</code> 方法。

<code>TelephonyManager</code> 類中不受支援的 <code>getMsisdn()</code> 方法。

在Android 10及之前的裝置,可以繼續使用<code>READ_PHONE_STATE</code>擷取手機号;

對Android11及以上裝置,需擷取<code>READ_PHONE_NUMBERS</code>權限,才能擷取手機号;

對于<code>READ_PHONE_STATE</code>權限

Android 10 開始<code>普通應用</code>已經不能再<code>讀取裝置的硬體ID</code>資訊;

相關資訊參考 https://xiaxl.blog.csdn.net/article/details/103125117;

Android 11 開始<code>擷取手機号</code>相關API更換為<code>READ_PHONE_NUMBERS</code>權限;

<code>READ_PHONE_NUMBERS</code>權限官方API描述:

https://developer.android.google.cn/reference/android/Manifest.permission#READ_PHONE_NUMBERS

在Android10裝置上,同時<code>申請前台、背景位置權限</code>時,并在使用者選擇<code>始終允許</code>後,才能獲得背景位置權限。

在Android11裝置上,對于<code>targetSdkVersion&lt;=29(Android 10)</code>的應用,同時<code>申請前台、背景位置權限</code>時,對話框不再提示始終允許字樣,而是提供了位置權限的設定入口,需要<code>使用者在設定頁面選擇始終允許</code>才能獲得背景位置權限。

在Android11裝置上,對于<code>targetSdkVersion=30(Android 11)</code>的應用,同時<code>申請前台、背景位置權限</code>時,系統會忽略該請求,無任何響應(<code>需首先擷取前台位置權限,再次申請背景位置權限</code>)。

在Android11裝置上,對于<code>targetSdkVersion=30(Android 11)</code>的應用,<code>先申請前台位置權限,後申請背景位置權限</code>。

背景通路位置權限 官方描述:

https://developer.android.google.cn/training/location/background

Android R 新特性分析及适配指南
Android R 新特性分析及适配指南
Android R 新特性分析及适配指南

Android11裝置上,targetSdkVersion=30的應用,申請背景位置權限,直接跳轉到設定頁面。

Android R 新特性分析及适配指南

在 Android 11 中,使用者<code>多次針對某項特定的權限請求</code>點選了<code>拒絕</code>,那麼應用再次請求該項權限時,使用者将不會看到系統權限彈窗,該操作表示使用者希望<code>不再詢問</code>;

在 Android 11 中,當targetSdkVersion&gt;=30時,<code>應用在一段時間内未使用</code>,系統會通過<code>自動重置使用者已授予應用的運作時敏感權限</code>來保護使用者資料;

Android R 新特性分析及适配指南

從 Android 11(API 級别 30)開始,當應用請求與<code>位置、麥克風、攝像頭</code>相關權限時,面向使用者的授權對話框會包含<code>僅限這一次</code>選項;如果使用者在對話框中選擇<code>僅限這一次</code>,系統會向應用授予臨時的單次授權。

Android R 新特性分析及适配指南

權限申請API使用方式不變:

源碼參考:

https://github.com/android/permissions-samples/tree/main/RuntimePermissionsBasic;

在 Android 11 中,<code>SYSTEM_ALERT_WINDOW</code> 權限授權方式更改為:<code>根據請求自動向某些應用授予 SYSTEM_ALERT_WINDOW 權限</code>。

系統會自動向具有 <code>ROLE_CALL_SCREENING</code> 且請求 <code>SYSTEM_ALERT_WINDOW</code> 的所有應用授予該權限。如果應用失去 <code>ROLE_CALL_SCREENING</code>,就會失去該權限。

<code>ROLE_CALL_SCREENING</code>為<code>RoleManager</code>中的常量類,多用于通知使用者将我們的應用替換掉手機自帶的預搭載應用(短信、電話撥号);

系統會自動向通過 <code>MediaProjection</code> 截取螢幕且請求 <code>SYSTEM_ALERT_WINDOW</code> 的所有應用授予該權限,除非使用者已明确拒絕向應用授予該權限。當應用停止截取螢幕時,就會失去該權限。此用例主要用于遊戲直播應用。

SYSTEM_ALERT_WINDOW權限 官方描述:

https://developer.android.google.cn/about/versions/11/privacy/permissions#system-alert

主要更改涉及以下幾個方面:

軟體包可見性:擷取其他應用資訊需在<code>AndroidManifest</code>中增加<code>&lt;queries&gt;</code>标簽;

前台服務:通路位置資訊、攝像頭、麥克風限制;

永久 SIM 卡辨別符 ICCID 擷取受限;

新增<code>AppOpsManager.OnOpNotedCallback</code>監聽危險權限的調用,進而保護使用者的私密資料;

這樣對于第三方依賴庫的權限使用申請可以做一個監控

在 Android 11 及更高版本裝置中,當應用的 <code>targetSdkVersion&gt;=30</code> 時,如果應用希望擷取其他應用的資訊(比如:包名、軟體名稱),原有方式将無法擷取到。

如需擷取其他應用資訊,需要在<code>AndroidManifest</code>中增加<code>&lt;queries&gt;</code>元素标簽,告知系統希望擷取哪些應用的資訊或者哪一類應用的資訊。

如果需要擷取所有應用的資訊(比如:Launcher應用、裝置管理器應用):這種情況隻需要在<code>AndroidManifest</code>中添加<code>QUERY_ALL_PACKAGES</code>權限即可。

<code>QUERY_ALL_PACKAGES</code>權限為普通權限,不需要進行動态申請。但送出應用市場後,應用市場可能會進行稽核

軟體包可見性 官方描述:

https://developer.android.google.cn/about/versions/11/privacy/package-visibility

當應用的 <code>targetSdkVersion&gt;=30</code> 時,<code>前台服務</code>通路<code>位置資訊、攝像頭、麥克風</code>時,需添加<code>foregroundServiceType</code>。

前台服務 官方描述:

https://developer.android.google.cn/about/versions/11/privacy/foreground-services

在 Android 11 及更高版本中,使用 <code>SubscriptionInfo.getIccId()</code> 方法通路不可重置的 ICCID 受到限制。

<code>SubscriptionInfo.getIccId()</code> 方法會傳回一個<code>非null的空字元串</code>。

如需唯一辨別裝置上安裝的 SIM 卡,請改用 <code>getSubscriptionId()</code> 方法。<code>SubscriptionId</code>會提供一個索引值,用于唯一識别已安裝的 SIM 卡(包括實體 SIM 卡和電子 SIM 卡),除非裝置恢複出廠設定,否則此辨別符的值對于給定 SIM 卡是保持不變的。

Android 11新增<code>AppOpsManager.OnOpNotedCallback</code>為開發者提供<code>對應用危險權限的使用監聽,進而保護使用者的私密資料</code>。

當應用以及應用的依賴包中,申請某項危險權限時,<code>AppOpsManager.OnOpNotedCallback</code>的對應回調方法将會被調用,進而<code>列印申請的權限</code>與<code>對應的API調用棧</code>。

舉例:

<code>使用位置權限擷取位置資訊</code>時,将會回調<code>AppOpsManager.OnOpNotedCallback</code>中的<code>onNoted</code>方法,并列印<code>使用的權限</code>與<code>對應的API調用棧</code>。

列印日志如下:

從以上日志可以看出,當應用申請<code>ACCESS_COARSE_LOCATION</code>權限并<code>擷取位置資訊時</code>,列印了應用<code>申請的權限</code>與<code>對應的API調用棧</code>。

AppOpsManager 相關官方描述:

https://developer.android.google.cn/guide/topics/data/audit-access#audit-by-attribution-tag

JobScheduler使用頻率進行限制

Android 11 為對<code>JobScheduler</code>使用頻率進行一定限制。

對于 debuggable 清單屬性設定為 true 的應用,過多的調用 <code>JobScheduler</code> API 将傳回 <code>RESULT_FAILURE</code>。

<code>JobScheduler</code>主要用于在未來某個時間下滿足一定條件時觸發執行某項任務,例如:<code>當裝置在空閑狀态, 并且使用wifi時, 自動下載下傳Apk</code>。

<code>JobScheduler</code>典型的使用舉例如下:

官方描述參考:

https://developer.android.google.cn/about/versions/11/behavior-changes-all

官方Demo參考:

https://github.com/googlearchive/android-JobScheduler

非 SDK 接口限制

官方從 Android 9(API 級别 28)開始,對應用使用的非 SDK 接口實施了限制。

如果你的APP通過引用<code>非 SDK 接口</code>或嘗試<code>使用反射或 JNI 來擷取句柄</code>,這些限制就會起作用。官方給出的解釋是為了<code>提升使用者體驗、降低應用崩潰風險</code>。

官方給出了一個檢測工具,下載下傳位址:veridex

veridex使用方法:

Android R 新特性分析及适配指南

以上截圖中,blacklist、greylist、greylist-max-o、greylist-max-p含義如下:

blacklist 黑名單:禁止使用的非SDK接口,運作時直接Crash(是以必須解決)

greylist 灰名單:即目前版本仍能使用的非SDK接口,但在下一版本中可能變成被限制的非SDK接口

greylist-max-o: 在targetSDK&lt;=O中能使用,但是在targetSDK&gt;=P中被禁止使用的非SDK接口

greylist-max-p: 在targetSDK&lt;=P中能使用,但是在targetSDK&gt;=Q中被禁止使用的非SDK接口

非SDK接口限制 官方描述:

https://developer.android.google.cn/about/versions/11/non-sdk-11

Android R 新特性分析及适配指南