Android 11 Java开发:如何通过路径删除非本应用创建的音乐文件
问题原因
从Android 10(API 29)开始系统引入分区存储机制,第三方应用默认无法直接通过File API修改/删除公共存储目录下其他应用创建的文件,哪怕你在AndroidManifest里声明了存储权限,直接调用File.delete()也会被系统拦截返回false。
解决方案
有两种可选方案,你可以根据自己的上架需求选择:
方案1:使用MediaStore删除(官方推荐,无需全文件访问权限,上架无限制)
不需要申请MANAGE_EXTERNAL_STORAGE高危权限,适配所有Android版本,代码示例如下:
private boolean deleteMusicFile(Context context, File file) { String filePath = file.getAbsolutePath(); long id = -1; // 先从MediaStore查询对应文件的id Cursor cursor = context.getContentResolver().query( MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, new String[]{MediaStore.Audio.Media._ID}, MediaStore.Audio.Media.DATA + "=? ", new String[]{filePath}, null); if (cursor != null && cursor.moveToFirst()) { id = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID)); cursor.close(); } if (id == -1) { return false; } // 执行删除 Uri uri = ContentUris.withAppendedId(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI, id); try { int deleteRow = context.getContentResolver().delete(uri, null, null); // 同时删除物理文件缓存(如果存在) if (file.exists()) { file.delete(); } return deleteRow > 0; } catch (SecurityException e) { // Android 11及以上如果没有修改权限,会抛异常,需要申请修改权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { IntentSender intentSender = MediaStore.createDeleteRequest(context.getContentResolver(), Collections.singletonList(uri)).getIntentSender(); // 你需要在当前Activity启动这个IntentSender,等待用户授权后再执行删除 ((Activity) context).startIntentSenderForResult(intentSender, 1001, null, 0, 0, 0); } return false; } }
你原来的长按删除逻辑改成调用这个方法即可:
@Override public boolean onItemLongClick(AdapterView<?> adapterView, View view, int i, long l) { File file = files.get(i); boolean deleted = deleteMusicFile(this, file); return deleted; }
方案2:申请全文件访问权限(适合不上架Google Play的场景)
如果你要继续用File API删除,可以申请MANAGE_EXTERNAL_STORAGE权限,除了清单里的声明,还要补充以下逻辑:
- 先在AndroidManifest的application标签里补充属性,适配Android 10过渡:
android:requestLegacyExternalStorage="true"
- 应用启动时动态申请权限:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) { if (!Environment.isExternalStorageManager()) { Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION); intent.setData(Uri.parse("package:" + getPackageName())); startActivityForResult(intent, 1002); } }
用户授权后,你原来的File.delete()逻辑就能正常执行。
注意事项
- MANAGE_EXTERNAL_STORAGE属于高危权限,如果你要上架Google Play,需要提交应用功能说明证明你确实需要全文件访问权限,否则会被拒审,优先选择方案1。
- Android 13及以上版本,原来的
READ_EXTERNAL_STORAGE权限已经废弃,你需要换成READ_MEDIA_AUDIO权限申请。
内容的提问来源于stack exchange,提问作者namanop
相关产品推荐
相关产品推荐

