art*_*man 9 android mediastore scoped-storage
我正在更新我的应用以使用 Android 10 中引入的 Scoped Storage 功能。
我的应用程序与 MediaStore 一起使用并显示图像、视频和音频文件,并为用户提供删除项目的能力。
我之前删除文件的操作:
MediaStore.MediaColumns.DATAnew File(path).delete()删除该文件现在 MediaStore.MediaColumns.DATA 不可用,我迁移到使用ContentResolver.delete()从 MediaStore 删除项目
例如,我有项目的 uri:(content://media/external/images/media/502它的有效 uri,我在网格中显示它的缩略图)。我是否在 MediaStore 或其他一些应用程序中插入了这个项目都没有关系。
我用context.getContentResolver().delete(uri, null, null). 它要么成功删除(返回 1 行),要么捕获RecoverableSecurityException用于startIntentSenderForResult()访问当前 uri,然后使用相同的内容getContentResolver().delete()将其删除onActivityResult(),然后成功删除。
无论哪种方式,该项目都会从 MediaStore 中删除,并且在我查询 MediaStore 以获取图像时也不会在结果中显示,也不会在其他应用程序中显示。
但是此文件存在于文件系统中(使用 SAF 和各种文件管理器(Google Files、Total Commander)进行检查)
有时(取决于 Android 版本和媒体类型)这些项目会在手机重启后(或打开 Google 相册后 - 它扫描文件系统)带回 MediaStore
例如:我的 Google Pixel 和 Google Pixel 3a XL 上的 Android 10 对图像/视频/音频的行为如上所述,但小米 A2 Lite 上的 Android 9 仅对音频文件的行为如此,而删除图像/视频则很好。
我有android:requestLegacyExternalStorage="false"清单。
有没有办法强制 MediaStore 删除文件系统上的数据?为什么文件系统上的文件被留下了?
是的,正如您所指出的,这就是我们必须删除媒体文件的方式。我们必须通过形成 File 对象来删除文件的物理副本,并使用 ContentResolver.delete() 删除 MediaStore 中的索引文件(或者)对已删除的文件进行媒体扫描,这将删除它在 MediaStore 中的条目。
这就是它在 Android 10 以下操作系统中的工作方式。如果您通过在清单 android:requestLegacyExternalStorage="true" 中指定来选择退出范围存储,那么在 Android 10 中仍然可以正常工作
现在,在Android 11中,您被迫使用范围存储。如果您想删除任何非您创建的媒体文件,您必须获得用户的许可。您可以使用 MediaStore.createDeleteRequest() 获取权限。这将显示一个对话框,描述用户将要执行的操作,一旦授予权限,Android 就会有一个内部代码来负责删除物理文件和 MediaStore 中的条目。
private void requestDeletePermission(List<Uri> uriList){
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
PendingIntent pi = MediaStore.createDeleteRequest(mActivity.getContentResolver(), uriList);
try {
startIntentSenderForResult(pi.getIntentSender(), REQUEST_PERM_DELETE, null, 0, 0,
0);
} catch (SendIntentException e) { }
}
}
Run Code Online (Sandbox Code Playgroud)
上面的代码将同时执行这两项操作,请求删除权限,一旦授予权限,也会删除文件。
您将在 onActivityResult() 中获得回调结果
使用此函数使用文件的显示名称删除文件: 此函数将删除 Android-10 或 Android-Q 文件系统上的 MediaStore 项目及其关联数据
注意:就我而言,我正在处理类似 MediaStore.Files.FileColumns.. 的文件。
public static boolean deleteFileUsingDisplayName(Context context, String displayName) {
Uri uri = getUriFromDisplayName(context, displayName);
if (uri != null) {
final ContentResolver resolver = context.getContentResolver();
String[] selectionArgsPdf = new String[]{displayName};
try {
resolver.delete(uri, MediaStore.Files.FileColumns.DISPLAY_NAME + "=?", selectionArgsPdf);
return true;
} catch (Exception ex) {
ex.printStackTrace();
// show some alert message
}
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
使用此函数从 DisplayName 获取 Uri
public static Uri getUriFromDisplayName(Context context, String displayName) {
String[] projection;
projection = new String[]{MediaStore.Files.FileColumns._ID};
// TODO This will break if we have no matching item in the MediaStore.
Cursor cursor = context.getContentResolver().query(extUri, projection,
MediaStore.Files.FileColumns.DISPLAY_NAME + " LIKE ?", new String[]{displayName}, null);
assert cursor != null;
cursor.moveToFirst();
if (cursor.getCount() > 0) {
int columnIndex = cursor.getColumnIndex(projection[0]);
long fileId = cursor.getLong(columnIndex);
cursor.close();
return Uri.parse(extUri.toString() + "/" + fileId);
} else {
return null;
}
}
Run Code Online (Sandbox Code Playgroud)
小智 2
根据我的观察,没有强制删除。
我通常会添加多项检查,以确定 Android Q 上的文件是否确实被删除,如果用户不手动确认每个文件,也不可能删除整个相册。这使得删除设备上的文件对我来说变得无趣
| 归档时间: |
|
| 查看次数: |
5679 次 |
| 最近记录: |