是否有一种简单的机制可以确定DownloadManager remove()何时完成,因为它看起来是部分异步的。该函数几乎立即返回其删除的下载表中的条目计数,但实际的文件系统内务似乎被推到了某个后台线程中。
问题是,我已经编写了一些代码,在获取新副本之前,查找并删除文件X(希望还有文件系统对象)的任何现有DownloadManager条目。不幸的是,对于上一个版本,新副本在文件系统内务管理开始之前就已经到达了目录。因此,内务管理实际上会在某个时刻删除新版本,并在DownloadManager表中留下一个孤立条目。
可以通过某种方式进行阻止,直到执行文件系统删除。
调试代码:
DownloadManager.Query query = new DownloadManager.Query().setFilterByStatus(DownloadManager.STATUS_SUCCESSFUL);
downloads = getAllDownloadIds(manager.query(query));
path = activity.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS);
//If a file name was passed remove any existing entry / version of the file
if ( fileName != null && ! fileName.isEmpty() ){
if ( downloads.containsKey(fileName)){
ids = downloads.get(fileName);
for (Long id : ids) {
Uri path = manager.getUriForDownloadedFile(id);
File checkFile = new File(path.toString());
Log.e(TAG, "Removing existing file: " + path.toString() + ":" + id);
int entriesRemoved = manager.remove(id);
Log.e(TAG, "Existing files removed: " + entriesRemoved);
}
}
}
...
Log.v(TAG, "Attempting to create a file in the 'Download' directory on the external storage::" + path.toString() +"/"+ fileName);
file = new File(path, fileName);
Log.v(TAG, "Does the file already exist::" + file.exists());
示例输出:
… V/Export﹕ Removing existing file: file:///storage/sdcard/Download/appData.csv:101
… V/Export﹕ Existing files removed: 1
… V/Export﹕ Attempting to create a file in the 'Download' directory on the external storage::/storage/sdcard/Download/appData.csv
… V/Export﹕ Does the file already exist::true
我也遇到了同样的问题-在快速网络中替换小文件时,替换文件有时会在调用DownloadManager.remove(...)
后的几分之一秒内到达。在这种情况下,新到达的文件会被删除。
我使用的解决方案是,在调用DownloadManager.remove(...)
之前,我设置一个FileObserver来监视文件。然后我调用remove(...)
,但在启动替换下载之前等待DELETE事件触发。
这导致大量代码分布在多个类中。还有其他复杂的因素——例如,我设置了一个超时机制,以防下载管理器永远不会删除文件。(我无法想象为什么它不会,但它不是我的组件)。
因此,在回答"是否有一个简单的机制……"的问题时:你可以使用一些机制,但不幸的是,这些机制不是特别容易。
我解决这个时间问题的方法只是删除DownloadManager.remove函数之前的文件。无论如何,"删除"功能都会删除对下载的引用。
int idFromCursor = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_ID));
String localPathOfFile =cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME));
File fileToDelete= new File(localPathOfFile);
if(fileToDelete.exists()){
fileToDelete.delete();
}
downloadManager.remove(idFromCursor);
之后就再也没有时间问题了。