Android 14媒体权限:XXPermissions使用详解
Android 14(API 34)对媒体权限进行了精细化调整,引入部分媒体文件访问控制机制。作为Android开发者,你是否正面临权限申请逻辑复杂、版本适配混乱、用户体验不佳等问题?本文将详细介绍如何使用XXPermissions框架(已适配Android 14)简化媒体权限申请流程,解决上述痛点。通过本文,你将掌握媒体权限的分类、申请方法、版本兼容处理及最佳实践。
媒体权限概述
Android系统的媒体权限管理经历了多次演变,从早期的统一存储权限到Android 13(API 33)的媒体类型细分,再到Android 14的部分访问控制,权限管理日趋精细化。
权限分类
XXPermissions将Android 14的媒体权限分为以下三类,对应不同的媒体文件访问范围:
- 图片权限(READ_MEDIA_IMAGES):用于访问设备中的图片文件。
- 视频权限(READ_MEDIA_VIDEO):用于访问设备中的视频文件。
- 音频权限(READ_MEDIA_AUDIO):用于访问设备中的音频文件。
这些权限定义在框架的dangerous包中,分别对应ReadMediaImagesPermission.java、ReadMediaVideoPermission.java和ReadMediaAudioPermission.java类。
Android 14新特性
Android 14引入了"选择照片"功能,允许用户授予应用对部分图片/视频的访问权限。这一特性要求应用在申请READ_MEDIA_IMAGES或READ_MEDIA_VIDEO权限时,能够处理部分授权场景。
XXPermissions通过ReadMediaImagesPermission.java中的isGrantedPermissionByStandardVersion方法,自动适配这一特性:
@Override
protected boolean isGrantedPermissionByStandardVersion(@NonNull Context context, boolean skipRequest) {
if (PermissionVersion.isAndroid14() && !skipRequest) {
// 如果是在 Android 14 上面,并且是图片权限或者视频权限,则需要重新检查权限的状态
// 这是因为用户授权部分图片或者视频的时候,READ_MEDIA_VISUAL_USER_SELECTED 权限状态是授予的
// 但是 READ_MEDIA_IMAGES 和 READ_MEDIA_VIDEO 的权限状态是拒绝的
// 为了权限回调不出现失败,这里只能返回 true,这样告诉外层请求其实是成功的
return PermissionLists.getReadMediaVisualUserSelectedPermission().isGrantedPermission(context, false);
}
return super.isGrantedPermissionByStandardVersion(context, skipRequest);
}
集成XXPermissions
添加依赖
要在项目中使用XXPermissions,需要先添加相应的依赖。根据项目的Gradle版本,选择以下配置方式:
Gradle 7.0以下
在项目根目录的build.gradle文件中添加:
allprojects {
repositories {
// JitPack 远程仓库
maven { url 'https://jitpack.io' }
}
}
然后在app模块的build.gradle中添加依赖:
dependencies {
// 权限请求框架
implementation 'com.github.getActivity:XXPermissions:26.5'
}
Gradle 7.0及以上
在项目根目录的settings.gradle文件中添加:
dependencyResolutionManagement {
repositories {
// JitPack 远程仓库
maven { url 'https://jitpack.io' }
}
}
然后在app模块的build.gradle中添加相同的依赖配置。
权限声明
在AndroidManifest.xml中声明需要使用的媒体权限:
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO" />
对于Android 13以下的设备,XXPermissions会自动使用READ_EXTERNAL_STORAGE权限进行兼容,无需额外声明。
媒体权限申请实现
XXPermissions提供了简洁的API,使媒体权限申请变得简单。以下是针对不同场景的实现方法。
申请单个媒体权限
以申请图片权限为例,使用XXPermissions申请单个媒体权限的代码如下:
XXPermissions.with(this)
.permission(PermissionLists.getReadMediaImagesPermission())
.request(new OnPermissionCallback() {
@Override
public void onResult(@NonNull List<IPermission> grantedList, @NonNull List<IPermission> deniedList) {
if (deniedList.isEmpty()) {
// 所有权限都已授予
Toast.makeText(MainActivity.this, "图片权限申请成功", Toast.LENGTH_SHORT).show();
} else {
// 有权限被拒绝
Toast.makeText(MainActivity.this, "图片权限申请失败", Toast.LENGTH_SHORT).show();
// 判断是否有被永久拒绝的权限
if (XXPermissions.isDoNotAskAgainPermissions(MainActivity.this, deniedList)) {
// 引导用户到设置界面开启权限
XXPermissions.startPermissionActivity(MainActivity.this, deniedList);
}
}
}
});
申请多个媒体权限
如果应用需要同时访问图片和视频,可以一次性申请多个权限:
XXPermissions.with(this)
.permission(PermissionLists.getReadMediaImagesPermission())
.permission(PermissionLists.getReadMediaVideoPermission())
.request(new OnPermissionCallback() {
@Override
public void onResult(@NonNull List<IPermission> grantedList, @NonNull List<IPermission> deniedList) {
if (deniedList.isEmpty()) {
// 所有权限都已授予
Toast.makeText(MainActivity.this, "图片和视频权限申请成功", Toast.LENGTH_SHORT).show();
} else {
// 有权限被拒绝
StringBuilder deniedPermissions = new StringBuilder();
for (IPermission permission : deniedList) {
deniedPermissions.append(permission.getPermissionName()).append(", ");
}
Toast.makeText(MainActivity.this, "以下权限被拒绝: " + deniedPermissions, Toast.LENGTH_SHORT).show();
}
}
});
Kotlin实现
XXPermissions同样支持Kotlin语言,以下是Kotlin版本的权限申请代码:
XXPermissions.with(this)
.permission(PermissionLists.getReadMediaAudioPermission())
.request(object : OnPermissionCallback {
override fun onResult(grantedList: MutableList<IPermission>, deniedList: MutableList<IPermission>) {
if (deniedList.isEmpty()) {
// 所有权限都已授予
Toast.makeText(this@MainActivity, "音频权限申请成功", Toast.LENGTH_SHORT).show()
} else {
// 有权限被拒绝
Toast.makeText(this@MainActivity, "音频权限申请失败", Toast.LENGTH_SHORT).show()
}
}
})
版本兼容处理
XXPermissions内置了版本兼容机制,自动处理不同Android版本的权限差异。
自动适配机制
以图片权限为例,ReadMediaImagesPermission.java中的getOldPermissions方法定义了Android 13以下设备的兼容权限:
@NonNull
@Override
public List<IPermission> getOldPermissions(Context context) {
// Android 13 以下访问媒体文件需要用到读取外部存储的权限
return PermissionUtils.asArrayList(PermissionLists.getReadExternalStoragePermission());
}
这意味着,当应用在Android 13以下设备上申请READ_MEDIA_IMAGES权限时,XXPermissions会自动改为申请READ_EXTERNAL_STORAGE权限。
分区存储适配
对于需要访问媒体文件的应用,还需要考虑Android 10引入的分区存储特性。如果项目已经适配了分区存储,可以在AndroidManifest.xml中添加以下配置:
<application>
<meta-data
android:name="ScopedStorage"
android:value="true" />
</application>
这一配置告诉XXPermissions,应用已经适配分区存储,无需进行额外的权限处理。
高级应用
权限申请结果处理
XXPermissions提供了丰富的API,帮助开发者处理各种权限申请结果场景:
// 判断权限是否已授予
boolean isGranted = XXPermissions.isGrantedPermission(this, PermissionLists.getReadMediaImagesPermission());
// 获取已授予的权限列表
List<IPermission> grantedPermissions = XXPermissions.getGrantedPermissions(this, allPermissions);
// 获取被拒绝的权限列表
List<IPermission> deniedPermissions = XXPermissions.getDeniedPermissions(this, allPermissions);
// 判断是否有被永久拒绝的权限
boolean hasDoNotAskAgain = XXPermissions.isDoNotAskAgainPermissions(this, deniedPermissions);
// 跳转到权限设置页面
XXPermissions.startPermissionActivity(this, deniedPermissions);
自定义权限说明
XXPermissions允许开发者自定义权限申请前的说明对话框,帮助用户理解为什么需要这些权限:
XXPermissions.setPermissionDescription(MyPermissionDescription.class);
其中,MyPermissionDescription需要实现OnPermissionDescription接口:
public class MyPermissionDescription implements OnPermissionDescription {
@Override
public String getDescription(Context context, IPermission permission) {
if (PermissionUtils.equalsPermission(permission, PermissionNames.READ_MEDIA_IMAGES)) {
return "需要访问您的图片以展示相册内容";
} else if (PermissionUtils.equalsPermission(permission, PermissionNames.READ_MEDIA_VIDEO)) {
return "需要访问您的视频以提供播放功能";
}
return null;
}
}
常见问题解决
权限冲突异常
当同时申请媒体权限和READ_EXTERNAL_STORAGE权限时,XXPermissions会抛出异常。这是因为媒体权限已经包含了对相应媒体文件的访问权限,无需重复申请。
解决方案:移除READ_EXTERNAL_STORAGE权限申请,仅保留媒体权限申请。XXPermissions会自动处理不同Android版本的权限兼容。
部分授权处理
在Android 14上,用户可能只授予应用访问部分图片/视频的权限。此时,应用需要能够处理这种部分授权场景,只访问用户允许的媒体文件。
XXPermissions通过ReadMediaImagesPermission.java中的逻辑,确保即使在部分授权情况下,应用也能正常运行。
总结
XXPermissions为Android媒体权限申请提供了简洁、高效的解决方案,特别是针对Android 14的新特性做了全面适配。通过本文介绍的方法,开发者可以轻松实现媒体权限的申请和管理,同时确保应用在不同Android版本上都能正常运行。
XXPermissions的优势不仅在于简化了权限申请流程,更在于其强大的兼容性和错误检测机制。框架会自动处理不同Android版本的权限差异,并在开发阶段帮助开发者发现和解决权限相关的问题。
建议开发者在使用XXPermissions时,遵循以下最佳实践:
- 只申请应用必需的权限,减少用户顾虑。
- 清晰说明每个权限的用途,提高用户授权意愿。
- 妥善处理各种授权结果,特别是被拒绝的情况。
- 定期更新XXPermissions到最新版本,确保兼容性。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考




