https://developer.android.com/training/data-storage
如果你APP會讀寫內部空間或者是記憶卡上的資料,對於Android 11在儲存空間中可能會有一些問題
目前在App中存取檔案資料的方始有這幾種
也就是可以在in-app中使用data/data/{packageName}/files/ 去存取資料,但這個缺點就是app資料就不見了
可分享的多媒體資料存取,也就是你如果想把一些auidio/video等等存入或讀取在手機中,就可以透過這個 MediaStore API來取用
可以讀取其它類型的分享型內容或是下載的資料等等,透過storage access framework來讀取,這種方式就是透過系統檔案總管讓使用者允許你要存取的資料位置,你就可以讀取這的資料
就是shared Preference 或是data store的方式
Database
Android 10 之前
而在Android 10 之前你可以透過
READ_EXTERNAL_STORAGE
, WRITE_EXTERNAL_STORAGE
去對整個空間獲取存取權限
Android 10
然後再Android 10的時候,如果你的APP在 android 10想要讀寫記憶卡位置,你可以透過上面兩個權限,然後加上Manifest 定義
https://developer.android.com/training/data-storage/use-cases#opt-out-scoped-storage
android:requestLegacyExternalStorage="true"
就可以正常的跟10之前一樣取得權限,或是你也可以使用
preserverLegacyExternalStorage 的定義
https://developer.android.com/reference/android/R.attr#preserveLegacyExternalStorage
這個定義的目的是,如果是更新升級,他一樣可以獲得原本的使用權限,但如果當你的這個app是新安裝的話,就無法取得Write權限
這時候就必須使用scoped storage 去存取資料,這個之後會談到
Android 11的時候
於是在Android 11的時候,android:requestLegacyExternalStorage將會被忽略,等於你只能拿到 read file的permission,另外WRITE_EXTERNAL_STORAG
也是一樣,官方文件這樣寫著,也就是你宣告了他也不會理你
https://developer.android.com/training/data-storage#permissions
if your app targets Android 11 (API level 30) or higher, the
WRITE_EXTERNAL_STORAGE
permission doesn't have any effect on your app's access to storage.
那怎麼辦
11卻增加了一個拿取全部空間的宣告權限
可以拿到整個儲存空間read/write的權限,不過使用這個權限的APP必須是合理的使用才能上架到google
如果你的APP沒有在合理使用的狀況下,譬如應該是一個檔案總管軟體,掃毒軟體,或是檔案轉移軟體等等,上架到Google必須經過審核才能通過,否則你就不能使用該權限,或是你沒有要上架到Google,就可以使用在Menifest宣告
然後執行request
ActivityCompat.requestPermissions(
this, arrayOf(
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.MANAGE_EXTERNAL_STORAGE
),
1
)
然後透過判斷去開啟使用者同意開啟你的權限
if (!Environment.isExternalStorageManager()) {
val intent = Intent(ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION)
intent.data = Uri.fromParts("package", packageName, null)
startActivity(intent)
}
譬如這個畫面,同意之後你就可以跟以前一樣開心的使用讀取權限了
正常使用下建議
建議使用scoped storage 去讓使用者同意與取得
但Android 11對於使用有一些新限制
- 不能存取Root權限
- 不能存取/android/data/跟 /android/obb/的路徑
其他
github sample
而使用方法可以參考google在github的sample