Android存儲權(quán)限兼容問題解析
一、引言
在 Android 開發(fā)中,存儲權(quán)限是一個常見且重要的權(quán)限。不同版本的 Android 系統(tǒng)對于存儲權(quán)限的管理和處理方式存在差異,這就導致了開發(fā)者在處理存儲權(quán)限時會遇到各種兼容問題。本文將詳細介紹 Android 各版本存儲權(quán)限的變化,以及如何進行兼容處理,并給出具體的代碼示例。
二、Android 各版本存儲權(quán)限變化
2.1 Android 6.0(API 級別 23)之前
在 Android 6.0 之前,應(yīng)用的權(quán)限在安裝時一次性授予。只要用戶安裝了應(yīng)用,應(yīng)用就擁有了在 AndroidManifest.xml 中聲明的所有權(quán)限,無需在運行時再次請求。例如,要使用存儲權(quán)限,只需在 AndroidManifest.xml 中添加如下代碼:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
2.2 Android 10(API 級別 29)及之后
Android 10 引入了分區(qū)存儲(Scoped Storage)機制,對應(yīng)用訪問外部存儲的方式進行了重大改變。應(yīng)用默認只能訪問自己的專屬目錄(如 Context.getExternalFilesDir() 返回的目錄)和媒體文件,訪問其他應(yīng)用的文件需要特殊處理。同時,WRITE_EXTERNAL_STORAGE 權(quán)限不再授予普通應(yīng)用,除非應(yīng)用在 AndroidManifest.xml 中聲明 android:requestLegacyExternalStorage="true" 以使用舊的存儲模式。
2.3 Android 11(API 級別 30)及之后
Android 11 進一步加強了分區(qū)存儲的限制,android:requestLegacyExternalStorage 屬性不再起作用,應(yīng)用必須適應(yīng)分區(qū)存儲。不過,Android 11 提供了一些新的 API 來處理文件訪問,如 MediaStore API 用于訪問媒體文件。
三、兼容處理方案及代碼示例
3.1 權(quán)限檢查與請求
以下是一個在 Android 6.0 及以上版本中請求存儲權(quán)限的代碼示
import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
public class MainActivity extends AppCompatActivity {
private static final int PERMISSION_REQUEST_CODE = 1;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// 檢查是否已經(jīng)授予存儲權(quán)限
if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
// 如果沒有授予權(quán)限,則請求權(quán)限
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
PERMISSION_REQUEST_CODE);
} else {
// 已經(jīng)授予權(quán)限,執(zhí)行相關(guān)操作
performStorageOperation();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSION_REQUEST_CODE) {
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// 用戶授予了權(quán)限,執(zhí)行相關(guān)操作
performStorageOperation();
} else {
// 用戶拒絕了權(quán)限,給出提示
Toast.makeText(this, "存儲權(quán)限被拒絕,無法執(zhí)行操作", Toast.LENGTH_SHORT).show();
}
}
}
private void performStorageOperation() {
// 執(zhí)行存儲相關(guān)操作
Toast.makeText(this, "開始執(zhí)行存儲操作", Toast.LENGTH_SHORT).show();
}
}
3.2 Android 10 及以上版本的分區(qū)存儲處理
在 Android 10 及以上版本中,使用分區(qū)存儲可以通過 Context.getExternalFilesDir() 訪問應(yīng)用的專屬目錄。以下是一個簡單的文件讀寫示例:
import android.content.Context;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
public class StorageActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_storage);
// 獲取應(yīng)用的外部存儲專屬目錄
File externalFilesDir = getExternalFilesDir(null);
if (externalFilesDir != null) {
// 創(chuàng)建一個文件
File file = new File(externalFilesDir, "test.txt");
try {
// 寫入文件
FileOutputStream fos = new FileOutputStream(file);
String content = "Hello, World!";
fos.write(content.getBytes());
fos.close();
Toast.makeText(this, "文件寫入成功", Toast.LENGTH_SHORT).show();
} catch (IOException e) {
e.printStackTrace();
Toast.makeText(this, "文件寫入失敗", Toast.LENGTH_SHORT).show();
}
}
}
}
3.3 Android 11 及以上版本的媒體文件訪問
import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.provider.MediaStore;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
public class MediaAccessActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_media_access);
// 獲取 ContentResolver
ContentResolver contentResolver = getContentResolver();
// 定義查詢的 URI
Uri uri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
// 定義查詢的列
String[] projection = {MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME};
// 執(zhí)行查詢
Cursor cursor = contentResolver.query(uri, projection, null, null, null);
if (cursor != null) {
while (cursor.moveToNext()) {
// 獲取圖片的 ID 和文件名
long id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID));
String displayName = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DISPLAY_NAME));
Toast.makeText(this, "圖片 ID: " + id + ", 文件名: " + displayName, Toast.LENGTH_SHORT).show();
}
cursor.close();
}
}
}
四、總結(jié)
在 Android 開發(fā)中,處理存儲權(quán)限兼容問題需要根據(jù)不同版本的系統(tǒng)特點進行相應(yīng)的處理。在 Android 6.0 及以上版本中,要使用運行時權(quán)限機制;在 Android 10 及以上版本中,要適應(yīng)分區(qū)存儲;在 Android 11 及以上版本中,要使用新的 API 進行文件訪問。通過合理的權(quán)限管理和文件操作,可以確保應(yīng)用在不同版本的 Android 系統(tǒng)上都能正常運行。
以上就是Android存儲權(quán)限兼容問題解析的詳細內(nèi)容,更多關(guān)于Android存儲權(quán)限兼容的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Android網(wǎng)絡(luò)請求-sign參數(shù)的設(shè)置方式
這篇文章主要介紹了Android網(wǎng)絡(luò)請求-sign參數(shù)的設(shè)置方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-03-03
Android自定義ViewGroup之WaterfallLayout(二)
這篇文章主要為大家詳細介紹了Android自定義ViewGroup之WaterfallLayout,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-09-09
6步輕松實現(xiàn)兩個listView聯(lián)動效果
這篇文章主要為大家詳細介紹了教大家通過6步輕松實現(xiàn)兩個listView聯(lián)動效果,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-04-04
Flutter?DateTime獲取本月的開始時間與結(jié)束時間方法
這篇文章主要為大家介紹了Flutter?DateTime獲取本月的開始時間與結(jié)束時間方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪2023-05-05
Android自定義布局實現(xiàn)仿qq側(cè)滑部分代碼
這篇文章主要為大家詳細介紹了自定義布局實現(xiàn)仿qq側(cè)滑Android部分代碼,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03
Android中AnimationDrawable使用的簡單實例
這篇文章介紹了Android中AnimationDrawable使用的簡單實例,有需要的朋友可以參考一下2013-10-10
Android百度地圖定位后獲取周邊位置的實現(xiàn)代碼
這篇文章主要為大家詳細介紹了Android百度地圖定位后獲取周邊位置的實現(xiàn)代碼,準確獲取周邊地理位置,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2016-01-01
Android Java調(diào)用自己C++類庫的實例講解
今天小編就為大家分享一篇關(guān)于Android Java調(diào)用自己C++類庫的實例講解,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-02-02

