Android11及以上文件讀寫(xiě)權(quán)限申請(qǐng)?jiān)敿?xì)介紹
Android11 讀寫(xiě)權(quán)限申請(qǐng)
Android11系統(tǒng)對(duì)應(yīng)用寫(xiě)入權(quán)限做了嚴(yán)格的限制。本文介紹如何獲取文件讀寫(xiě)權(quán)限。項(xiàng)目中 build.gradle 的targetSdkVersion >= 29 ,會(huì)出現(xiàn)讀寫(xiě)問(wèn)題。
當(dāng)targetSdkVersion = 29,通過(guò)設(shè)置requestLegacyExternalStorage=“true”,還能解決。
當(dāng)targetSdkVersion = 30后,需要申請(qǐng)所有文件權(quán)限才能獲取到寫(xiě)入權(quán)限。
AndroidManifest添加權(quán)限設(shè)置
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" /><!--add 2022-2-11 Android11-->
<application
...
android:requestLegacyExternalStorage="true"
...
>代碼申請(qǐng)動(dòng)態(tài)權(quán)限
1.Android 6.0之上Android11以下申請(qǐng)權(quán)限
if (Build.VERSION.SDK_INT >= 23) {// 6.0
String[] perms = {
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_PHONE_STATE};
for (String p : perms) {
int f = ContextCompat.checkSelfPermission(SafeKeyToolActivity.this, p);
Log.d("---", String.format("%s - %d", p, f));
if (f != PackageManager.PERMISSION_GRANTED) {
requestPermissions(perms, 0XCF);
break;
}
}
}Android11申請(qǐng)權(quán)限
跳轉(zhuǎn)系統(tǒng)設(shè)置界面,用戶授權(quán)獲取權(quán)限。
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R && !isRefuse) {// android 11 且 不是已經(jīng)被拒絕
// 先判斷有沒(méi)有權(quán)限
if (!Environment.isExternalStorageManager()) {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:" + getPackageName()));
startActivityForResult(intent, 1024);
}
}
// 帶回授權(quán)結(jié)果
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 1024 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// 檢查是否有權(quán)限
if (Environment.isExternalStorageManager()) {
isRefuse = false;
// 授權(quán)成功
} else {
isRefuse = true;
// 授權(quán)失敗
}
}
}
對(duì)于部分手機(jī)如小米手機(jī),即使獲取了所有文件的管理權(quán)限,依舊訪問(wèn)不到Android/data目錄,如圖:

嘗試解決辦法:
只在外部存儲(chǔ)的應(yīng)用私有目錄下,用直接路徑讀寫(xiě)文件。
訪問(wèn)或者共享媒體文件,使用MediaStore在公共目錄下讀寫(xiě)文件
訪問(wèn)或者共享非媒體文件,使用系統(tǒng)的文件選擇器SAF在公共目錄Download下讀寫(xiě)文件。
根目錄下可以創(chuàng)建自定義文件夾、文件。
補(bǔ)充:Android 11 及以上申請(qǐng)外部存儲(chǔ)權(quán)限
升級(jí) targetSdkVersion
android
defaultConfig {
targetSdkVersion 30
}
}
添加清單權(quán)限
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" />
代碼動(dòng)態(tài)申請(qǐng)
public final class PermissionActivity extends AppCompatActivity {
private static final int REQUEST_CODE = 1024;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestPermission();
}
private void requestPermission() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// 先判斷有沒(méi)有權(quán)限
if (Environment.isExternalStorageManager()) {
writeFile();
} else {
Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
intent.setData(Uri.parse("package:" + context.getPackageName()));
startActivityForResult(intent, REQUEST_CODE);
}
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// 先判斷有沒(méi)有權(quán)限
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
writeFile();
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE}, REQUEST_CODE);
}
} else {
writeFile();
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == REQUEST_CODE) {
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
writeFile();
} else {
ToastUtils.show("存儲(chǔ)權(quán)限獲取失敗");
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE && Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
if (Environment.isExternalStorageManager()) {
writeFile();
} else {
ToastUtils.show("存儲(chǔ)權(quán)限獲取失敗");
}
}
}
/**
* 模擬文件寫(xiě)入
*/
private void writeFile() {
ToastUtils.show("寫(xiě)入文件成功");
}
}總結(jié)
到此這篇關(guān)于Android11及以上文件讀寫(xiě)權(quán)限申請(qǐng)的文章就介紹到這了,更多相關(guān)Android11文件讀寫(xiě)權(quán)限申請(qǐng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Android進(jìn)階CameraX與Camera2使用比對(duì)詳解
這篇文章主要為大家介紹了Android進(jìn)階CameraX與Camera2使用比示例對(duì)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-01-01
Android LaunchMode四種啟動(dòng)模式詳細(xì)介紹
這篇文章主要介紹了Android LaunchMode四種啟動(dòng)模式詳細(xì)介紹的相關(guān)資料,這里對(duì)launchmode的使用方法進(jìn)行了詳解及啟動(dòng)模式的比較,需要的朋友可以參考下2016-12-12
Android之ArcSlidingHelper制作圓弧滑動(dòng)效果
這篇文章主要介紹了Android之ArcSlidingHelper制作圓弧滑動(dòng)效果,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-08-08
Android中利用NetworkInfo判斷網(wǎng)絡(luò)狀態(tài)時(shí)出現(xiàn)空指針(NullPointerException)問(wèn)題的解決
這篇文章主要介紹了Android中利用NetworkInfo判斷網(wǎng)絡(luò)狀態(tài)時(shí)出現(xiàn)空指針(NullPointerException)問(wèn)題的解決方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2016-11-11
Android 項(xiàng)目實(shí)戰(zhàn)之頭像選擇功能
這篇文章主要介紹了Android 項(xiàng)目實(shí)戰(zhàn)頭像選擇功能實(shí)戰(zhàn),需要的朋友可以參考下2018-01-01
Android?RecyclerBarChart繪制使用教程
這篇文章主要為大家介紹了Android?RecyclerBarChart繪制使用教程,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-12-12

