在Android应用中,获取本地音乐文件的权限是实现音乐扫描功能的关键步骤之一。随着Android版本的不断更新,从Android 6.0(API级别23)开始,应用需要动态请求权限,而到了android 13以上需要的权限又做了进一步改变。
1. 需要添加存储权限到AndroidManifest.xml中,android 6.0到android 12只需要存储权限,android 13开始对权限做了更细致的处理,而不是READ_EXTERNAL_STORAGE,拆分成下面三个权限。如果同时请求 READ_MEDIA_IMAGES
权限和 READ_MEDIA_VIDEO
权限,系统只会显示一个系统权限对话框。如果您的应用之前已获得 READ_EXTERNAL_STORAGE 权限,则在升级时,系统会自动授予任何请求的 READ_MEDIA_*
权限。如果您的应用只需要访问图片、照片和视频,优先使用照片选择器,而不是声明 READ_MEDIA_IMAGES
和 READ_MEDIA_VIDEO
权限。如果是只要音频文件同理只需要READ_MEDIA_VIDEO
权限即可。
一般我们获取音频文件,只需要添加下面权限即可
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"
android:maxSdkVersion="32" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"
tools:ignore="ScopedStorage" android:maxSdkVersion="32"/>
<uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
2.动态请求权限
检查是否有获取音频文件权限
fun checkPermission(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.checkSelfPermission(
context,
Manifest.permission.READ_MEDIA_AUDIO
) == PackageManager.PERMISSION_GRANTED
} else {
ContextCompat.checkSelfPermission(
context,
Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
}
}
请求权限
fun requestPermission(activity: Activity, requestCode: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.READ_MEDIA_AUDIO,Manifest.permission.POST_NOTIFICATIONS), requestCode
)
} else {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
requestCode
)
}
}
一般我们写成一个数组里面一起去请求
private static final String[] permissionsArray = new String[]{
Manifest.permission.READ_EXTERNAL_STORAGE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.RECORD_AUDIO
};
private static final String[] permissionsArray13 = new String[]{
Manifest.permission.READ_MEDIA_AUDIO,
Manifest.permission.RECORD_AUDIO,
Manifest.permission.POST_NOTIFICATIONS
};
private void checkRequiredPermission(final Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
for (String permission : permissionsArray13) {
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
}
}
} else {
for (String permission : permissionsArray) {
if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
}
}
}
if (permissionsList != null && permissionsList.size() > 0) {
ActivityCompat.requestPermissions(activity, permissionsList.toArray(new String[permissionsList.size()]), REQUEST_PERMISSION);
} else {
//去初始化
}
}
去请求权限可以用一个对话框去处理会显得更友好
final PermissionDialog permissionDialog = new PermissionDialog(this, R.color.library_dialog_bg, getString(R.string.permission_title));
permissionDialog.setPermissionDialogListener(new PermissionDialog.IPermissionDialogListener() {
@Override
public void cancelClick() {
finish();
permissionDialog.cancel();
}
@Override
public void okClick() {
boolean isBannedPermission = MusicPermissionUtils.INSTANCE.isBannedPermission(MusicLibraryActivity.this);
if (!isBannedPermission) {
Utils.goToSettingIntent(MusicLibraryActivity.this);
} else {
MusicPermissionUtils.INSTANCE.requestPermission(MusicLibraryActivity.this, REQUEST_PERMISSION);
}
permissionDialog.cancel();
}
});
permissionDialog.show();
处理权限请求结果,如果全部权限都已同意可以去做初始化,一般我们做权限请求最好每个功能点需要用到的权限一个个去请求会更友好。
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
switch (requestCode) {
case REQUEST_PERMISSION:
boolean isAllRequest = false;
for (int i = 0; i < permissions.length; i++) {
if (grantResults[i] == PackageManager.PERMISSION_GRANTED) {
isAllRequest = true;
} else {
//去请求权限
showPermissionDialog();
return;
}
}
if (isAllRequest) {
//初始化或者继续操作
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
用户如果不同意权限可以跳转到设置找到应用去同意添加权限,用户有可能会拒绝权限请求,最好在界面添加可以继续请求的按钮或者直接跳转到设置里面让用户找到应用去添加需要的权限
public static void goToSettingIntent(Context context) {
Intent localIntent = new Intent();
localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
if (Build.VERSION.SDK_INT >= 9) {
localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
localIntent.setData(Uri.fromParts("package", context.getPackageName(), null));
} else if (Build.VERSION.SDK_INT <= 8) {
localIntent.setAction(Intent.ACTION_VIEW);
localIntent.setClassName("com.android.settings", "com.android.settings.InstalledAppDetails");
localIntent.putExtra("com.android.settings.ApplicationPkgName", context.getPackageName());
}
context.startActivity(localIntent);
}
音乐权限请求工具代码
object MusicPermissionUtils {
fun hasMusicPermission(context: Context): Boolean {
val permission = checkPermission(context)
if (permission == PackageManager.PERMISSION_GRANTED) {
return true
}
return false
}
fun isBannedPermission(activity: Activity): Boolean {
val isBannedPermission: Boolean =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ActivityCompat.shouldShowRequestPermissionRationale(
activity,
Manifest.permission.READ_MEDIA_AUDIO
)
} else {
ActivityCompat.shouldShowRequestPermissionRationale(
activity,
Manifest.permission.READ_EXTERNAL_STORAGE
)
}
return isBannedPermission
}
fun requestPermission(activity: Activity, requestCode: Int) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.READ_MEDIA_AUDIO,Manifest.permission.POST_NOTIFICATIONS), requestCode
)
} else {
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.READ_EXTERNAL_STORAGE),
requestCode
)
}
}
fun checkReadPermission(context: Context): Boolean {
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.checkSelfPermission(
context,
Manifest.permission.READ_MEDIA_AUDIO
) == PackageManager.PERMISSION_GRANTED
} else {
ContextCompat.checkSelfPermission(
context,
Manifest.permission.READ_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
}
}
fun checkPermission(context: Context): Int {
val checkWriteStoragePermission: Int =
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.checkSelfPermission(
context, Manifest.permission.READ_MEDIA_AUDIO
)
} else {
ContextCompat.checkSelfPermission(
context, Manifest.permission.READ_EXTERNAL_STORAGE
)
}
return checkWriteStoragePermission
}
}