字節跳動:Android R如何訪問文件,修改文件,你們對R適配了嗎

Android R如何訪問文件,修改文件,你們對R適配了嗎
心理分析:新Android特性一直都是面試官重點中的重點接下來,會問你他的原理 你是怎麼看。 它的優缺點。爲什麼比其他的好。從原理層來解析。這纔是最難的。

這篇文章 從原理層說明他們的區別

更多面試內容,面試專題,flutter視頻 全套,音視頻從0到高手開發。
關注GitHub:https://github.com/xiangjiana/Android-MS
免費獲取面試PDF合集

Android R 越來越近了,最近 Google 又發佈了 Android R Beta 的第五個版本,眼瞅着這進度,在今年 R3 季度,Android R 就正式和用戶見面了,在此之前,開發者必然又是面臨的一波讓人頭疼的適配。

 

瞭解新特性,首推應該去看官方文檔,官方已經給出了一份完整的新特性文檔,在發佈的這段時間,也一直在保持同步的更新。而作爲開發者,我們更關心的是如何解決在我們現有的 App 上,保證 Android R 的兼容性問題。

今天就給推薦給大家一份適配文檔,以開發者的角度列一份適配清單,在 Android R 還沒來之前,先了解需要做什麼,以及怎麼做,到時候纔不至於措手不及。

這份文檔的出自 OPPO 開放平臺,可能有人會覺得是 KPI 工程,但是你想想這些廠商每年耗巨資研發的旗艦機,用着最新的硬件,當然要搭配最新的系統,而用戶在旗艦機上的體驗,也是他們最關心的,所以每次 Android 發佈新系統,這些廠商也在推進自己應用市場上 App 的適配工作。

你只需要想想他們做這件事的動機,就能知道這份文檔肯定是花了心思的。文檔我看過一遍,從場景出發來分析原因,並附上解決方案,很有參考意義。

文檔比較長,大家可以先收藏,再跳躍閱讀看自己關注的點

一. 背景說明

本文檔是基於谷歌安卓R 的 beta1 版本的變更輸出的兼容性整改指導,如果後續 beta 版本有新的變更和新的特性,我們也會刷新文檔的相關章節內容,請開發者持續關注。

二. 存儲空間限制

2.1 背景

爲了讓用戶更好地控制自己的文件,並限制文件混亂的情況,Android R 修改了 APP 訪問外部存儲中文件的方法。外部存儲的新特性被稱爲 Scoped Storage。

Android R 仍然使用 READ_EXTERNAL_STORAGE 和 WRITE_EXTERNAL_STORAGE 作爲面向用戶的存儲相關運行時權限,但現在即使獲取了這些權限,訪問外部存儲也受到了限制。APP 需要這些運行時權限的情景發生了變化,且各種情況下外部存儲對 APP 的可見性也發生了變化。

在 Scoped Storage 新特性中,外部存儲空間被分爲兩部分:
● 公共目錄 :Downloads、Documents、Pictures 、DCIM、Movies、Music、Ringtones 等

  • 公共目錄下的文件在 APP 卸載後,不會刪除。
  • APP 可以通過 SAF(System Access Framework)、MediaStore 接口訪問其中的文件。

● App-specific 目錄

  • APP 卸載後,數據會清除。
  • APP 的私密目錄,APP 訪問自己的 App-specific 目錄時無需任何權限

     

Android R 規定了 APP 有兩種外部存儲空間視圖模式:Legacy View、Filtered View。

● Filtered View

  • App 可以直接訪問 App-specific 目錄,但不能直接訪問 App-specific 外的文件。訪問公共目錄或其他 APP 的 App-specific 目錄,只能通過 MediaStore、SAF、或者其他 APP 提供的 ContentProvider、FileProvider 等訪問。

● Legacy View

  • 兼容模式。與 Android R 以前一樣,申請權限後 App 可訪問外部存儲,擁有完整的訪問權限。

在 Android R 上,target SDK 大於或等於 29 的 APP 默認被賦予 Filtered View,反之則默認被賦予 Legacy View。APP 可以在 AndroidManifest.xml 中設置新屬性 requestLegacyExternalStorage 來修改外部存儲空間視圖模式,true 爲 Legacy View,false 爲 Filtered View。可以使用 Environment.isExternalStorageLegacy() 這個 API 來檢查 APP 的運行模式。APP 開啓 Filtered View 後,Scoped Storage 新特性對 APP 生效。

Android R 除了劃分外部存儲和定義 Filtered View,還在查詢、讀寫文件的一些細節上做了改進或限制,例如圖片文件中的地理位置信息將不再默認提供、查詢 MediaProvider 獲得的 DATA 字段不再可靠、新增了文件的 Pending 狀態等等。這些細節的具體內容請參考適配方案章節。

2.2 兼容性影響

Scoped Storage 對於 APP 訪問外部存儲方式、APP 數據存放以及 APP 間數據共享,都產生很大影響。請開發者注意以下的兼容性影響事項。

2.2.1 無法新建文件

問題原因: 直接使用自身 App-specific 目錄以外的路徑新建文件。

問題分析: 在 Android R 上,APP 只允許在自身 App-specific 目錄以內通過路徑生成的文件。

解決方案: APP 自身 App-specific 目錄下新建文件的方法與文件路徑,請參見 2.3.1;如果要在公共目錄下新建文件,使用 MediaStore 接口,請參見 2.3.2;如果要在任意目錄下新建文件,需要使用 SAF,請參見 2.3.3。

2.2.2 無法訪問存儲設備上的文件

問題原因 1: 直接使用路徑訪問公共目錄文件。

問題分析 1: 在 Android R 上,APP 默認只能訪問外部存儲設備上的 App-specific 目錄。

解決方法 1: 參見 2.3.2 和 2.3.3,使用 MediaStore 接口訪問公共目錄中的多媒體文件,或者使用 SAF 訪問公共目錄中的任意文件。注意:從 MediaStore 接口中查詢到的 DATA 字段將在 Android R 開始廢棄,不應該利用它來訪問文件或者判斷文件是否存在;從 MediaStore 接口或者 SAF 獲取到文件 Uri 後,請利用 Uri 打開 FD 或者輸入輸出流,而不要轉換成文件路徑去訪問。

問題原因 2: 使用 MediaStore 接口訪問非多媒體文件。

問題分析 2: 在 Android R 上,使用 MediaStore 接口只能訪問公共目錄中的多媒體文件。

解決方法 2: 使用 SAF 向用戶申請文件或目錄的讀寫權限,請參見 2.3.3。

2.2.3 無法正確分享文件

問題原因: APP 將 App-specific 目錄中的私有文件分享給其他 APP 時,使用了 file:// 類型的 Uri。

問題分析: 在 Android R 上,由於 App-specific 目錄中的文件是私有受保護的,其他 APP 無法通過文件路徑訪問。

解決方案: 參見 2.3.4,使用 FileProvider,將 content:// 類型的 Uri 分享給其他 APP。

2.2.4 無法修改存儲設備上的文件

問題原因 1: 直接使用路徑訪問公共目錄文件。

問題分析 1: 同 2.2.2。

解決方案 1: 同 2.2.2,請使用正確的公共目錄文件訪問方式。

問題原因 2: 使用 MediaStore 接口獲取公共目錄多媒體文件的 Uri 後,直接使用該 Uri 打開 OutputStream 或文件描述符。

問題分析 2: 在 Android R 上,修改公共目錄文件,需要用戶授權。

解決方案 2: 從 MediaStore 接口獲取公共目錄多媒體文件 Uri 後,打開 OutputStream 或 FD 時,注意 catch RecoverableSecurityException,然後向用戶申請該多媒體文件的刪改權限,請參見 2.3.2.6;使用 SAF 獲取到文件或目錄的 Uri 時,用戶已經授權讀寫,可以直接使用,但要注意 Uri 權限的時效,請參見 2.3.3.6。

2.2.5 應用卸載後文件意外刪除

問題原因: 將想要保留的文件保存在外部存儲的 App-specific 目錄下。

問題分析:在 Android R 上,卸載 APP 默認刪除 App-specific 目錄下的數據。

解決方案: APP 應該將想要保留的文件通過 MediaStore 接口保存到公共目錄下,請參見 2.3.2。默認情況下,MediaStore 接口會將非媒體類文件保存到 Downloads 目錄下,推薦 APP 指定一級目錄爲 Documents。如果 APP 想要在卸載時保留 App-specific 目錄下的數據,要在 AndroidManifest.xml 中聲明 android:hasFragileUserData="true",這樣在 APP 卸載時就會有彈出框提示用戶是否保留應用數據。

2.2.6 無法訪問圖片文件中的地理位置數據

問題原因: 直接從圖片文件輸入流中解析地理位置數據。

問題分析: 由於圖片的地理位置信息涉及用戶隱私,Android R 上默認不向 APP 提供該數據。

解決方案: 申請 ACCESS_MEDIA_LOCATION 權限,並使用 MediaStore.setRequireOriginal() 接口更新文件 Uri,請參見 2.3.5.1 。

2.2.7 Fota 升級問題

問題原因: Fota 升級後,APP 被卸載,重新安裝後無法訪問到 APP 數據。

問題分析: Scoped Storage 新特性只對 Android R 上新安裝的 APP 生效。設備從 Android R 之前的版本升級到 Android R,已安裝的 APP 獲得 Legacy View 視圖。這些 APP 如果直接通過路徑的方式將文件保存到了外部存儲上,例如外部存儲的根目錄,那麼 APP 被卸載後重新安裝,新的 APP 獲得 Filtered View 視圖,無法直接通過路徑訪問到舊數據,導致數據丟失。

解決方案: APP 應該修改保存文件的方式,不再使用路徑的方式直接保存,而是採用 MediaStore 接口將文件保存到對應的公共目錄下。在 Fota 升級前,可以將 APP 的用戶歷史數據通過 MediaStore 接口遷移到公共目錄下。此外,APP 應當改變訪問 App-specific 目錄以外的文件的方式,請使用 MediaStore 接口或者 SAF。

2.3 適配指導

Android R Scoped Storage 新特性谷歌官方適配文檔:

https://developer.android.google.cn/preview/privacy/scoped-storage

OPPO 適配指導如下,分爲:訪問 APP 自身 App-specific 目錄文件、使用 MediaStore 訪問公共目錄、使用 SAF 訪問指定文件和目錄、分享 App-specific 目錄下文件和其他細節適配。

2.3.1 訪問 APP 自身 App-specific 目錄文件

無需任何權限,APP 即可直接使用文件路徑來讀寫自身 App-specific 目錄下的文件。獲取 App-specific 目錄路徑的接口如下表所示。

 

如下,以新建並寫入文件爲例。

 

  final File[] dirs = getExternalFilesDirs("Documents");
  File primaryDir = null;
  if (dirs != null && dirs.length > 0) {
      primaryDir = dirs[0];
  }
  if (primaryDir == null) {
      return;
  }
  File newFile = new File(primaryDir.getAbsolutePath(), "MyTestDocument");
  OutputStream fileOS = null;
  try {
      fileOS = new FileOutputStream(newFile);
      if (fileOS != null) {
          fileOS.write("file is  created".getBytes(StandardCharsets.UTF_8));
          fileOS.flush();
      }
  } catch (IOException e) {
      LogUtil.log("create file fail");
  } finally {
      try {
          if (fileOS != null) {
              fileOS.close();
          }
      } catch (IOException e1) {
          LogUtil.log("close stream fail");
      }
  }

2.3.2 使用 MediaStore 訪問公共目錄

APP 無法直接訪問公共目錄下的文件。MediaStore 爲 APP 提供了訪問公共目錄下媒體文件的接口。APP 在有適當權限時,可以通過 MediaStore 查詢到公共目錄文件的 Uri,然後通過 Uri 讀寫文件。

MediaStore 相關的 Google 官方文檔:

https://developer.android.google.cn/reference/android/provider/MediaStore

2.3.3 APP 通過 MediaStore 訪問文件所需要的權限

通過 MediaStore 提供的 Uri,使用 ContentResolver 的 insert 接口,將文件保存到公共目錄下。不同的 Uri,可以保存到不同的公共目錄中

更多面試內容,面試專題,flutter視頻 全套,音視頻從0到高手開發。
關注GitHub:https://github.com/xiangjiana/Android-MS
免費獲取面試PDF合集

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