如果cache
目录已满,则尝试执行简单请求将失败而不发送DownloadManager.ACTION_DOWNLOAD_COMPLETE
广播。
注意:问题很普遍,但主要可以在缓存有限的低端设备上重现( /data/data/com.android.providers.downloads/cache )尺寸。
接收器配置正确,因为我在操作成功时仍然收到广播,但由于其他原因失败。
DownloadManager.Request request = new DownloadManager.Request(Uri.parse("http://www.apkmirror.com/wp-content/themes/APKMirror/download.php?id=44753"));
request.setTitle("Facebook");
DownloadManager downloadManager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
downloadManager.enqueue(request);
我对特定问题的解决方案感兴趣,或者如果您也遇到过更多信息。
不正在寻找需要我停止使用DownloadManager
或添加WRITE_EXTERNAL_STORAGE
权限的解决方案。
当缓存变满时,最后当缓存不再容纳时,您可以观察到以下日志入口(使用downloadmanager
过滤)
11-08 08:47:06.079 830-14261/? I/DownloadManager: Download 135 starting
11-08 08:47:06.989 830-14261/? W/DownloadManager: Downloads data dir: /data/data/com.android.providers.downloads/cache is running low on space. space available (in bytes): -6994124
11-08 08:47:06.999 830-14261/? I/DownloadManager: discardPurgeableFiles: destination = 2, targetBytes = 10485760
11-08 08:47:06.999 830-14261/? I/DownloadManager: Purged files, freed 0 for 10485760 requested
11-08 08:47:07.309 830-14261/? W/DownloadManager: Aborting request for download 135: not enough free space in the filesystem rooted at: /data/data/com.android.providers.downloads/cache and unable to free any more
11-08 08:47:07.319 830-14261/? I/DownloadManager: Download 135 finished with status INSUFFICIENT_SPACE_ERROR
这是一个可以证明问题的DEMO PROJECT。请记住,缓存目录必须在该点填满(通过不可清除的项目,根据我的经验基本上意味着,中止下载)
答案 0 :(得分:2)
由于DownloadManager本质上是一个系统ContentProvider,您可以向其注册您自己的ContentObserver, 因此,当下载提供程序更新时,它将选择在INSUFFICIENT_SPACE的情况下通知观察者。
final DownloadManager downloadManager = (DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
context.getContentResolver().registerContentObserver(Uri.parse("content://downloads/my_downloads"),
true, new ContentObserver(null) {
@Override
public void onChange(boolean selfChange) {
super.onChange(selfChange);
Cursor localCursor = downloadManager.query(
new DownloadManager.Query());
if (localCursor.getCount() == 0) {
localCursor.close();
}
localCursor.moveToFirst();
do {
if ((localCursor.getInt(localCursor.getColumnIndex(DownloadManager.COLUMN_STATUS)) & DownloadManager.STATUS_FAILED )!=0) {
// Download failed, go see why
if (localCursor.getInt(localCursor.getColumnIndex(DownloadManager.COLUMN_REASON)) == DownloadManager.ERROR_INSUFFICIENT_SPACE){
Log.w("DownloadStatus", " Download failed with ERROR_INSUFFICIENT_SPACE");
}
}
}while (localCursor.moveToNext());
}
});
请注意,不要设置状态为DownloadManager.STATUS_FAILED的查询过滤器,因为DownloadManager奇怪地只考虑400到600之间的状态为失败状态, 但INSUFFICIENT_SPACE的错误代码为198 ...
android.app.DownloadManager.Request:
Cursor runQuery(ContentResolver resolver, String[] projection, Uri baseUri) {
.....
if ((mStatusFlags & STATUS_FAILED) != 0) {
parts.add("(" + statusClause(">=", 400)
+ " AND " + statusClause("<", 600) + ")");
}
}
答案 1 :(得分:0)
您可以通过以下代码获取INSUFFICIENT_SPACE_ERROR
的理由来接收DownloadManager.STATUS_FAILED
广播
private void DownloadStatus(Cursor cursor, long DownloadId){
//column for download status
int columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS);
int status = cursor.getInt(columnIndex);
//column for reason code if the download failed or paused
int columnReason = cursor.getColumnIndex(DownloadManager.COLUMN_REASON);
int reason = cursor.getInt(columnReason);
//get the download filename
int filenameIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);
String filename = cursor.getString(filenameIndex);
String statusText = "";
String reasonText = "";
switch(status){
case DownloadManager.STATUS_FAILED:
statusText = "STATUS_FAILED";
switch(reason){
case DownloadManager.ERROR_CANNOT_RESUME:
reasonText = "ERROR_CANNOT_RESUME";
break;
case DownloadManager.ERROR_DEVICE_NOT_FOUND:
reasonText = "ERROR_DEVICE_NOT_FOUND";
break;
case DownloadManager.ERROR_FILE_ALREADY_EXISTS:
reasonText = "ERROR_FILE_ALREADY_EXISTS";
break;
case DownloadManager.ERROR_FILE_ERROR:
reasonText = "ERROR_FILE_ERROR";
break;
case DownloadManager.ERROR_HTTP_DATA_ERROR:
reasonText = "ERROR_HTTP_DATA_ERROR";
break;
case DownloadManager.ERROR_INSUFFICIENT_SPACE:
reasonText = "ERROR_INSUFFICIENT_SPACE";
break;
case DownloadManager.ERROR_TOO_MANY_REDIRECTS:
reasonText = "ERROR_TOO_MANY_REDIRECTS";
break;
case DownloadManager.ERROR_UNHANDLED_HTTP_CODE:
reasonText = "ERROR_UNHANDLED_HTTP_CODE";
break;
case DownloadManager.ERROR_UNKNOWN:
reasonText = "ERROR_UNKNOWN";
break;
}
break;
case DownloadManager.STATUS_PAUSED:
statusText = "STATUS_PAUSED";
switch(reason){
case DownloadManager.PAUSED_QUEUED_FOR_WIFI:
reasonText = "PAUSED_QUEUED_FOR_WIFI";
break;
case DownloadManager.PAUSED_UNKNOWN:
reasonText = "PAUSED_UNKNOWN";
break;
case DownloadManager.PAUSED_WAITING_FOR_NETWORK:
reasonText = "PAUSED_WAITING_FOR_NETWORK";
break;
case DownloadManager.PAUSED_WAITING_TO_RETRY:
reasonText = "PAUSED_WAITING_TO_RETRY";
break;
}
break;
case DownloadManager.STATUS_PENDING:
statusText = "STATUS_PENDING";
break;
case DownloadManager.STATUS_RUNNING:
statusText = "STATUS_RUNNING";
break;
case DownloadManager.STATUS_SUCCESSFUL:
statusText = "STATUS_SUCCESSFUL";
reasonText = "Filename:\n" + filename;
break;
}
}
答案 2 :(得分:0)
我认为Gracie解决方案需要一些改进,例如取消注册和检查下载ID。
如果您对请求不使用任何限制,则可以在排队后尝试检查文件大小-这不是完美的解决方案:
private static void checkFileSize(Context context, DownloadManager downloadManager, long myDownloadReference, DownloadInfo downloadInfo) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(myDownloadReference);
Handler handler = new Handler();
handler.postDelayed(() -> {
Cursor cursor = downloadManager.query(query);
if (!cursor.moveToFirst()) {
KLog.i("download list is empty");
return;
}
int size = cursor.getInt(cursor
.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES));
int status = cursor.getInt(cursor
.getColumnIndex(DownloadManager.COLUMN_STATUS));
int reason = cursor.getInt(cursor
.getColumnIndex(DownloadManager.COLUMN_REASON));
cursor.close();
if (reason == DownloadManager.ERROR_INSUFFICIENT_SPACE)
DownloadedReceiver.handleInsufficientSpace(context, downloadInfo);
}, 1500);
}