通过'ContentResolver'删除文件与通过'file.delete()'删除文件的区别

16

我刚刚在 Android 应用程序中使用 Java 的标准 'File' 类编写了一个删除文件的函数。例如:

String fileName= "/mnt/Gallery/Img001.jpg";
File file = new File(fileName);
file.delete();

虽然上述过程足够简单,但我一直在想是否通过“ContentResolver”执行相同操作有任何优势。如有建议,请指教。

------------------------------------------ 编辑 ----------------------------------------

以下是通过Content Resolver删除文件的示例。此示例假定要删除的文件是图像,其“id”已知。

long mediaId = 155; // NOTE: You would normally obtain this from the content provider!
Uri contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
Uri itemUri = ContentUris.withAppendedId(contentUri, mediaId);

int rows = getContentResolver().delete(itemUri, null, null);

String path = itemUri.getEncodedPath();
if(rows == 0)
{
    Log.e("Example Code:","Could not delete "+path+" :(");
}
else
{
    Log.d("Example Code:","Deleted "+path+ " ^_^");
}

2
经过一番调查,我发现当被删除的文件由Android的“内容提供程序”管理时,有一个优势。例如,图像会在图像表中维护,以便应用程序可以快速查看设备上的图像列表。在您的活动中使用“getContentResolver().delete(uri, null, null)”将自动删除内容表中关联的条目。仅使用“file.delete()”将仅删除物理文件,之后需要提示媒体扫描程序更新内容表。 - Jazza
什么是通过内容提供程序删除文件的正确方法?我尝试过:getContentResolver().delete(Uri.fromFile(new File(fileName)), null, null); 但是我得到了“未知URL”异常。 - PerracoLabs
@Zhenya: 我最初犯了和你一样的错误,试图传入一个'URL'来删除文件。delete() 函数需要一个指向内容提供程序表中行的 'uri'。这一行不能通过调用 Uri.fromFile() 来获取!我已经编辑了我的问题以说明如何构建这个 Uri。 - Jazza
1个回答

12

与直接操作数据相比,Android的内容提供程序框架具有某些额外的优势。

您可以思考'文件位于何处以及谁可能正在删除它'。

情景1

文件位于SD卡上(应用可访问的路径),您的应用正在删除它。

解决方案 : 由于该路径对您是可访问的,因此使用类似于以下的带有文件 Uri 的 Java 方法将起作用:

file://mnt/sdcard/downloads/image.jpeg

情景2

文件位于另一个应用程序中(例如 Dropbox),您的应用程序需要删除该文件。

解决方案 : 这意味着文件实际上位于另一个应用程序的私有存储中。使用上述方法的文件: Uri 将会给出访问被拒绝的错误。因此,您的应用程序将需要从包含文件的应用程序获取内容 Uri 并调用其内容提供程序来删除。

fileUri = Uri.parse ("content : // " + packageContainingTheFile " + fileId); // 用从应用中获得的 Uri 替换。 getContext().getContentResolver().delete (fileUri, null, null);

情景3

文件位于您的应用程序包目录中,即 data/data/com.yourpackage/yourfolder/yourfile.xxx 下,并且只有您的应用程序可以删除它。

解决方案 : 在这种情况下,以上任一方法都可以工作,因为您可以访问并删除该文件。 Uri 将如下所示:

file://data/data/yourpackage/folder/file.ext

在此处使用内容提供程序的主要优势是,您自动获得观察器模型。内容提供程序回调是修改数据的明确定义入口点。因此,这是使用以下方式通知其他人更改的期望位置:

getContext().getContentResolver().notify(uri, null)

假设您有显示此类文件项列表的视图。在删除完成后,可以通知您。

方案 4

文件位于您的应用程序包目录下,即 data/data/com.yourpackage/yourfolder/yourfile.xxx,并且您希望将删除功能暴露给其他应用程序。

解决方案: 这与情况 1 类似,只是相反。其他应用程序无法使用如下 Uri 删除您私有存储中的文件:

file://data/data/yourpackage/folder/file.ext // 只适用于您自己的应用程序

他们需要调用您的内容提供程序来使用如下 Uri 进行删除:

content://providerAuthority/delete/id 您的内容提供程序将需要将其映射到 file.ext 绝对路径。

总结

总之,在某些情况下,使用内容提供程序是必要的,而在其他情况下则是可选的。这主要取决于您的应用程序要求。如果您有视图、CursorLoader 并想要了解更新或希望向其他应用程序公开删除应用程序数据的功能,则内容提供程序是最干净的方法。


我正在使用一个键值对存储,其中包含对象数组。对象中存储了应用程序的私有存储中文件的路径。同时还使用了提供者。如何删除、插入或更新文件和保存这些文件路径的对象,并影响内容提供者,以便第三方应用程序可以知道更改,同时目录、键值存储和内容提供者都应该同步。 - CrackerKSR

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接