Android 11存储权限申请失败问题排查及解决方法咨询
Android 11存储权限申请失效问题排查与修复方案
问题背景
开发Android应用时,存储权限申请逻辑在Android 11以下版本正常运行,但在Android 11(API 30)版本中无法生效,以下是现有代码及问题修复方案。
现有代码问题分析
1. AndroidManifest配置无效
android:requestLegacyExternalStorage="true"仅对Android 10(API 29)生效,Android 11及以上版本会忽略该属性,无法通过它绕过Android 11的存储权限限制。
2. ActivityResult判断逻辑错误
在onActivityResult中通过_resultCode == RESULT_OK判断授权结果是错误的:跳转到系统设置页面授权后,返回的resultCode始终为RESULT_CANCELED,导致即使授权成功也无法触发后续页面跳转。
3. 版本判断不严谨
使用Build.VERSION.SDK_INT == Build.VERSION_CODES.R仅匹配Android 11,未覆盖Android 12及以上版本——这些版本的全文件访问权限逻辑与Android 11一致,应使用>=判断。
4. 未初始化Intent变量
代码中直接调用i.setClass(...),但变量i未初始化,会触发空指针异常。
5. 权限申请无退出逻辑
用户拒绝权限后直接重复调用_takePermission()会导致无限循环申请,影响用户体验。
正确实现方案
1. AndroidManifest.xml配置
添加MANAGE_EXTERNAL_STORAGE权限,同时保留requestLegacyExternalStorage兼容Android 10:
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /> <!-- Android 11+ 全文件访问权限 --> <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" tools:ignore="ScopedStorage" /> <application ... android:requestLegacyExternalStorage="true"> ... </application>
2. Java代码修复
import android.content.Intent; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Environment; import android.provider.Settings; 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 PermissionActivity extends AppCompatActivity { private static final int REQUEST_CODE_STORAGE = 100; private static final int REQUEST_CODE_LEGACY_STORAGE = 101; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // 启动时主动检查权限 if (!_isPermissionGranted()) { _takePermission(); } else { navigateToMain2Activity(); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); // Android 11+ 跳转设置后直接检查权限状态,无需判断resultCode if (requestCode == REQUEST_CODE_STORAGE) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (Environment.isExternalStorageManager()) { Toast.makeText(this, "权限已授予", Toast.LENGTH_SHORT).show(); navigateToMain2Activity(); } else { Toast.makeText(this, "请授予全文件访问权限以继续", Toast.LENGTH_SHORT).show(); // 可添加弹窗引导用户前往设置,避免无限循环申请 } } } } public boolean _isPermissionGranted() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { return Environment.isExternalStorageManager(); } else { int readPermission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.READ_EXTERNAL_STORAGE); return readPermission == android.content.pm.PackageManager.PERMISSION_GRANTED; } } public void _takePermission() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { try { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); intent.setData(Uri.parse("package:" + getPackageName())); startActivityForResult(intent, REQUEST_CODE_STORAGE); } catch (Exception e) { Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION); startActivityForResult(intent, REQUEST_CODE_STORAGE); } } else { ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_LEGACY_STORAGE); } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if (requestCode == REQUEST_CODE_LEGACY_STORAGE) { if (grantResults.length > 0 && grantResults[0] == android.content.pm.PackageManager.PERMISSION_GRANTED) { Toast.makeText(this, "权限已授予", Toast.LENGTH_SHORT).show(); navigateToMain2Activity(); } else { Toast.makeText(this, "请授予存储权限以继续", Toast.LENGTH_SHORT).show(); // 引导用户前往设置开启权限,避免无限循环 } } } // 封装页面跳转逻辑,避免重复代码 private void navigateToMain2Activity() { Intent i = new Intent(this, Main2Activity.class); startActivity(i); finish(); // 可选,关闭当前权限页面 } }
关键修复点说明
- 移除
onActivityResult中RESULT_OK的判断,直接检查权限状态 - 版本判断改为
Build.VERSION.SDK_INT >= Build.VERSION_CODES.R,覆盖所有Android 11+版本 - 初始化Intent变量并封装页面跳转逻辑,避免空指针异常
- 添加权限拒绝后的友好提示,避免无限循环申请
- 在
onCreate中启动时主动检查权限,确保进入主页面的前提是权限已授予
内容的提问来源于stack exchange,提问作者Ayan Mishra
相关产品推荐
相关产品推荐

