问题
Is there an easy mechanism to determine when a DownloadManager remove() has completed, as it appears to be partially asynchronous. The function returns almost instantaneously with a count of the entries in the Download table it's deleted, but the actual filesystem housekeeping appears to be pushed into some background thread.
Issue is I've written a little bit of code that looks for and deletes any existing DownloadManager entry for file X (and hopefully the filesystem object), before pulling a new copy. Unfortunately the new copy is making it to the directory before the filesystem housekeeping has kicked in, for the previous incarnation. So the housekeeping actually ends up deleting the new version at some point and leaving an orphan entry in the DownloadManager table.
Could do with some way to block till the filesystem delete is actioned.
Debug code:
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());
Example output:
… 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
回答1:
I had this same problem - when replacing small files in a fast network, the replacement files would sometimes arrive within a fraction of a second after calling DownloadManager.remove(...)
In this case, the newly arrived files would be deleted.
The solution I'm using is, before I call DownloadManager.remove(...)
, I setup up a FileObserver to monitor the file. I then call remove(...)
, but then wait for the DELETE event to fire before initiating the replacement download.
This ended being a significant amount of code distributed among multiple classes. There are other complicating factors - for example I put a timeout mechanism in just in case the DownloadManager never deletes the file. (I can't imagine why it wouldn't, but it's not my component).
So in answer to the question "Is there an easy mechanism.....": There are mechanisms available to you, but unfortunately not particularly easy ones.
回答2:
The way i'm solved this timing problem is just to delete the file before DownloadManager.remove function. The reference to the download will be removed by the "remove" function anyway.
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);
after that there was no timing problems anymore.
来源:https://stackoverflow.com/questions/26269217/android-downloadmanager-remove-how-to-determine-when-the-remove-operation