针对 Android 13~16 的存储权限变化做专门处理
摘要:针对Android13-16存储权限变化,补充了StoragePermissionUtils工具类,与现有PermissionUtils结合使用。新工具类适配不同版本:Android16+使用MANAGE_EXTERNAL_STORAGE,Android13-15使用READ_MEDIA_*媒体权限,Android6-12保持原有读写权限。通过检查、请求权限的方法封装,并处理权限请求结果和系
·
有一个 PermissionUtils 动态权限工具类,但它只是一个通用权限请求框架,没有针对 Android 13~16 的存储权限变化做专门处理,补充一个,针对 Android 13~16 的存储权限变化做专门处理。Android 13(API 33) 开始,存储权限被拆分成了媒体类型权限(READ_MEDIA_IMAGES、READ_MEDIA_VIDEO、READ_MEDIA_AUDIO),Android 14/15/16 又进一步收紧了非媒体文件的访问。
适配 Android 16 的 StoragePermissionUtils
package com.nyw.mvvmmode.utils;
import android.app.Activity;
import android.content.Intent;
import android.os.Build;
import android.os.Environment;
import android.provider.Settings;
/**
* 存储权限工具类(适配 Android 6 ~ Android 16+)
* 功能:
* - 自动判断系统版本,使用对应权限策略
* - Android 13+ 使用新的媒体权限
* - Android 11+ 使用 MANAGE_EXTERNAL_STORAGE
* - Android 6-10 使用传统读写权限
*/
public class StoragePermissionUtils {
// 请求码
public static final int REQUEST_STORAGE_PERMISSION = 200;
/**
* 检查存储权限
*/
public static boolean checkStoragePermission(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Android 11+:检查是否有管理所有文件权限
return Environment.isExternalStorageManager();
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// Android 13-16:检查媒体权限
return PermissionUtils.checkMultiplePermissions(activity, new String[]{
android.Manifest.permission.READ_MEDIA_IMAGES,
android.Manifest.permission.READ_MEDIA_VIDEO,
android.Manifest.permission.READ_MEDIA_AUDIO
});
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Android 6-10:检查读写权限
return PermissionUtils.checkMultiplePermissions(activity, new String[]{
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
});
}
// Android 5.1 及以下默认有权限
return true;
}
/**
* 请求存储权限
*/
public static void requestStoragePermission(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// Android 11+:跳转到管理所有文件权限页面
Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
activity.startActivityForResult(intent, REQUEST_STORAGE_PERMISSION);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// Android 13-16:请求媒体权限
PermissionUtils.requestMultiplePermissions(activity, new String[]{
android.Manifest.permission.READ_MEDIA_IMAGES,
android.Manifest.permission.READ_MEDIA_VIDEO,
android.Manifest.permission.READ_MEDIA_AUDIO
});
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
// Android 6-10:请求传统读写权限
PermissionUtils.requestMultiplePermissions(activity, new String[]{
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
});
}
}
/**
* 处理权限请求结果
* 在 Activity 的 onRequestPermissionsResult 中调用
*/
public static void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
if (requestCode == PermissionUtils.REQUEST_CODE_PERMISSION) {
PermissionUtils.onRequestPermissionsResult(null, requestCode, permissions, grantResults);
}
}
/**
* 处理从设置页返回的结果
* 在 Activity 的 onActivityResult 中调用
*/
public static boolean onActivityResult(Activity activity, int requestCode) {
if (requestCode == REQUEST_STORAGE_PERMISSION) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
return Environment.isExternalStorageManager();
}
}
return false;
}
}
PermissionUtils 代码
package com.nyw.mvvmmode.utils;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.List;
/**
* Android 6.0+ 动态权限工具类
* 支持:单个/多个权限请求、权限检查、引导用户去设置页开启权限
*/
public class PermissionUtils {
// 权限请求码(自定义,确保唯一)
public static final int REQUEST_CODE_PERMISSION = 100;
// 跳转到应用设置页的请求码
public static final int REQUEST_CODE_SETTINGS = 101;
// 新增:使用弱引用持有Activity,避免内存泄漏
private static WeakReference<Activity> sActivityWeakRef;
/**
* 检查单个权限是否已授予
*/
public static boolean checkSinglePermission(Context context, @NonNull String permission) {
// Android 6.0 以下默认授予所有权限
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
return ContextCompat.checkSelfPermission(context, permission)
== PackageManager.PERMISSION_GRANTED;
}
/**
* 检查多个权限是否已全部授予
*/
public static boolean checkMultiplePermissions(Context context, @NonNull String[] permissions) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || permissions == null || permissions.length == 0) {
return true;
}
for (String permission : permissions) {
if (!checkSinglePermission(context, permission)) {
return false;
}
}
return true;
}
/**
* 筛选出未授予的权限
*/
public static List<String> getDeniedPermissions(Context context, @NonNull String[] permissions) {
List<String> deniedPermissions = new ArrayList<>();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || permissions == null || permissions.length == 0) {
return deniedPermissions;
}
for (String permission : permissions) {
if (!checkSinglePermission(context, permission)) {
deniedPermissions.add(permission);
}
}
return deniedPermissions;
}
/**
* 请求单个权限
*/
public static void requestSinglePermission(Activity activity, @NonNull String permission) {
requestMultiplePermissions(activity, new String[]{permission});
}
/**
* 请求多个权限
*/
public static void requestMultiplePermissions(Activity activity, @NonNull String[] permissions) {
if (activity == null || permissions == null || permissions.length == 0) {
return;
}
// 弱引用持有Activity
sActivityWeakRef = new WeakReference<>(activity);
// 筛选未授予的权限
List<String> deniedPermissions = getDeniedPermissions(activity, permissions);
if (deniedPermissions.isEmpty()) {
// 所有权限已授予,直接回调成功
if (sPermissionCallback != null) {
sPermissionCallback.onPermissionGranted(permissions);
}
return;
}
// 发起权限请求
ActivityCompat.requestPermissions(
activity,
deniedPermissions.toArray(new String[0]),
REQUEST_CODE_PERMISSION
);
}
/**
* 检查是否需要显示权限说明(用户之前拒绝过权限)
*/
public static boolean shouldShowPermissionRationale(Activity activity, @NonNull String permission) {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M || activity == null) {
return false;
}
return ActivityCompat.shouldShowRequestPermissionRationale(activity, permission);
}
/**
* 跳转到应用设置页(用户永久拒绝权限时调用)
*/
public static void goToAppSettings(Activity activity) {
if (activity == null) {
return;
}
Intent intent = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", activity.getPackageName(), null);
intent.setData(uri);
activity.startActivityForResult(intent, REQUEST_CODE_SETTINGS);
}
// ====================== 权限请求回调 ======================
private static PermissionCallback sPermissionCallback;
public interface PermissionCallback {
/**
* 所有请求的权限都已授予
*/
void onPermissionGranted(String[] grantedPermissions);
/**
* 部分/全部权限被拒绝
*/
void onPermissionDenied(String[] deniedPermissions, boolean isPermanentlyDenied);
}
/**
* 设置权限请求回调(需在请求权限前设置)
*/
public static void setPermissionCallback(PermissionCallback callback) {
sPermissionCallback = callback;
}
/**
* 清除权限回调(避免内存泄漏)
*/
public static void clearPermissionCallback() {
sPermissionCallback = null;
sActivityWeakRef = null; // 清除弱引用
}
/**
* 在 Activity 的 onRequestPermissionsResult 中调用,处理权限请求结果
*/
public static void onRequestPermissionsResult(Activity activity, int requestCode,
@NonNull String[] permissions, @NonNull int[] grantResults) {
// 检查Activity是否存活
if (activity == null || activity.isFinishing() || activity.isDestroyed()) {
clearPermissionCallback();
return;
}
// 检查弱引用是否有效
if (sActivityWeakRef != null && sActivityWeakRef.get() != activity) {
clearPermissionCallback();
return;
}
if (requestCode != REQUEST_CODE_PERMISSION || sPermissionCallback == null) {
return;
}
List<String> grantedPermissions = new ArrayList<>();
List<String> deniedPermissions = new ArrayList<>();
boolean isPermanentlyDenied = false;
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
grantedPermissions.add(permissions[i]);
} else {
deniedPermissions.add(permissions[i]);
// 检查是否永久拒绝(用户勾选了“不再询问”)
if (!shouldShowPermissionRationale(activity, permissions[i])) {
isPermanentlyDenied = true;
}
}
}
if (deniedPermissions.isEmpty()) {
// 所有权限都授予
sPermissionCallback.onPermissionGranted(grantedPermissions.toArray(new String[0]));
} else {
// 部分/全部权限被拒绝
sPermissionCallback.onPermissionDenied(deniedPermissions.toArray(new String[0]), isPermanentlyDenied);
}
}
}
这样做的好处
- 不重复造轮子:存储权限的具体规则在
StoragePermissionUtils中处理,底层调用你已有的PermissionUtils - 适配到 Android 16:
- Android 13-16 使用新的媒体权限
- Android 11-12 使用
MANAGE_EXTERNAL_STORAGE - Android 6-10 使用旧的读写权限
- 完整的结果处理:
- 动态权限结果 →
onRequestPermissionsResult - 从系统设置页返回 →
onActivityResult
- 动态权限结果 →
在 Activity 中调用:
// 检查并请求存储权限
if (!StoragePermissionUtils.checkStoragePermission(this)) {
StoragePermissionUtils.requestStoragePermission(this);
}
在 Activity 中处理权限回调::
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
StoragePermissionUtils.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (StoragePermissionUtils.onActivityResult(this, requestCode)) {
// 用户从设置页返回并开启了权限
Toast.makeText(this, "存储权限已开启", Toast.LENGTH_SHORT).show();
// 继续执行需要权限的操作
}
}
这样就不需要重新写一个全新的权限工具类,只需要更新 StoragePermissionUtils,就能在 Android 16 上正常使用。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)