android 下载管理器超时
timeout for android DownloadManager
我正在使用 android 内置 DownloadManager 从 Internet 下载文件。问题是一旦我排队下载,它会尝试永远下载文件!有没有办法设置下载超时?
不幸的是Android没有在DownloadManager中设置超时的解决方案但实际上你可以在处于挂起状态时设置一个TIMEOUT ClockWake:DownloadManager.STATUS_PENDING
DownloadManager.Query query = null;
Cursor c = null;
DownloadManager downloadManager = null;
downloadManager = (DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE);
query = new DownloadManager.Query();
if(query!=null) {
query.setFilterByStatus(DownloadManager.STATUS_FAILED|DownloadManager.STATUS_PAUSED|DownloadManager.STATUS_SUCCESSFUL|
DownloadManager.STATUS_RUNNING|DownloadManager.STATUS_PENDING);
} else {
return;
}
c = downloadManager.query(query);
if(c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch(status) {
case DownloadManager.STATUS_PAUSED:
break;
case DownloadManager.STATUS_PENDING:
//here you can set your TIMEOUT solution
break;
case DownloadManager.STATUS_RUNNING:
break;
case DownloadManager.STATUS_SUCCESSFUL:
break;
case DownloadManager.STATUS_FAILED:
break;
}
@Sofien Rahmouni Virtuel 和 @flegare 解决方案是好主意,但我会尝试给出一个完整的可行示例。我试图花更多时间解决这个问题,这样可以节省某人的 'googling' 时间。主要思想是在大小文件失败或超时时重试下载过程 - 在 6-7MB 上测试。首先删除具有该 ID 的下载并调用下载方法。对于 STATUS_RUNNING,我递归调用 manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
方法以确保下载成功完成。
唯一的问题是我总是在第一次检查时得到 STATUS_PENDING
,即使它必须是 STATUS_RUNNING,我实施了一个解决方法来避免这种情况。
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
/**
* Created by Android Developer on 29.10.2015. Copyright ©
*/
public class DownloadFile {
private static Context mContext = App.getUniversalContext();//here just get aplication context - I have a static method in App class
private static DownloadManager downloadManager = (DownloadManager) App.getUniversalContext().getSystemService(Context.DOWNLOAD_SERVICE);
private static int RETRIES_MAX_NUMBER = 3; //nr of retries
private static int alreadyRetried;
private static boolean isEntered = false;
public static void downloadFile(String urlLink, String pathUri, String fileName) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(urlLink));
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
request.setDestinationInExternalPublicDir(pathUri, fileName);
request.setDescription("System download");
request.setTitle("ADMINISTRATOR");
request.setVisibleInDownloadsUi(false);
request.setNotificationVisibility(2)
final long downloadId = downloadManager.enqueue(request);
manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
App.getUniversalContext().registerReceiver(new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
if (downloadId == intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID)) {
mContext.unregisterReceiver(this);
//done use your file
}
}
}, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
/*check for timeout / errors and retry logic*/
private static void manageDownloadProcess(final String urlLink, final String pathUri, final String fileName, final long downloadId) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterByStatus(DownloadManager.STATUS_PENDING | DownloadManager.STATUS_SUCCESSFUL | DownloadManager.STATUS_PAUSED | DownloadManager.STATUS_RUNNING | DownloadManager.STATUS_FAILED);
final Cursor cursor = downloadManager.query(query.setFilterById(downloadId));
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (status) {
/*I introdused 'isEntered' param to eliminate first response from this method
* I don't know why but I get STATUS_PENDING always on first run, so this is an ugly workaround*/
case DownloadManager.STATUS_PENDING: {
Log.d("status", "STATUS_PENDING - timeout");
if (isEntered) {
if (alreadyRetried < RETRIES_MAX_NUMBER) {
alreadyRetried++;
downloadManager.remove(downloadId);
downloadFile(urlLink, pathUri, fileName);
manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
}
} else {
isEntered = true;
manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
}
break;
}
case DownloadManager.STATUS_PAUSED: {
Log.d("status", "STATUS_PAUSED - error");
if (alreadyRetried < RETRIES_MAX_NUMBER) {
alreadyRetried++;
downloadManager.remove(downloadId);
downloadFile(urlLink, pathUri, fileName);
}
break;
}
case DownloadManager.STATUS_RUNNING: {
Log.d("status", "STATUS_RUNNING - good");
manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
break;
}
case DownloadManager.STATUS_SUCCESSFUL: {
Log.d("status", "STATUS_SUCCESSFUL - done");
break;
}
case DownloadManager.STATUS_FAILED: {
Log.d("status", "STATUS_FAILED - error");
if (alreadyRetried < RETRIES_MAX_NUMBER) {
alreadyRetried++;
downloadManager.remove(downloadId);
downloadFile(urlLink, pathUri, fileName);
}
break;
}
}
}
}
}, 5000);//do this after 5 sec
}
}
我正在使用 android 内置 DownloadManager 从 Internet 下载文件。问题是一旦我排队下载,它会尝试永远下载文件!有没有办法设置下载超时?
不幸的是Android没有在DownloadManager中设置超时的解决方案但实际上你可以在处于挂起状态时设置一个TIMEOUT ClockWake:DownloadManager.STATUS_PENDING
DownloadManager.Query query = null;
Cursor c = null;
DownloadManager downloadManager = null;
downloadManager = (DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE);
query = new DownloadManager.Query();
if(query!=null) {
query.setFilterByStatus(DownloadManager.STATUS_FAILED|DownloadManager.STATUS_PAUSED|DownloadManager.STATUS_SUCCESSFUL|
DownloadManager.STATUS_RUNNING|DownloadManager.STATUS_PENDING);
} else {
return;
}
c = downloadManager.query(query);
if(c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch(status) {
case DownloadManager.STATUS_PAUSED:
break;
case DownloadManager.STATUS_PENDING:
//here you can set your TIMEOUT solution
break;
case DownloadManager.STATUS_RUNNING:
break;
case DownloadManager.STATUS_SUCCESSFUL:
break;
case DownloadManager.STATUS_FAILED:
break;
}
@Sofien Rahmouni Virtuel 和 @flegare 解决方案是好主意,但我会尝试给出一个完整的可行示例。我试图花更多时间解决这个问题,这样可以节省某人的 'googling' 时间。主要思想是在大小文件失败或超时时重试下载过程 - 在 6-7MB 上测试。首先删除具有该 ID 的下载并调用下载方法。对于 STATUS_RUNNING,我递归调用 manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
方法以确保下载成功完成。
唯一的问题是我总是在第一次检查时得到 STATUS_PENDING
,即使它必须是 STATUS_RUNNING,我实施了一个解决方法来避免这种情况。
import android.app.DownloadManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.util.Log;
/**
* Created by Android Developer on 29.10.2015. Copyright ©
*/
public class DownloadFile {
private static Context mContext = App.getUniversalContext();//here just get aplication context - I have a static method in App class
private static DownloadManager downloadManager = (DownloadManager) App.getUniversalContext().getSystemService(Context.DOWNLOAD_SERVICE);
private static int RETRIES_MAX_NUMBER = 3; //nr of retries
private static int alreadyRetried;
private static boolean isEntered = false;
public static void downloadFile(String urlLink, String pathUri, String fileName) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(urlLink));
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE | DownloadManager.Request.NETWORK_WIFI);
request.setDestinationInExternalPublicDir(pathUri, fileName);
request.setDescription("System download");
request.setTitle("ADMINISTRATOR");
request.setVisibleInDownloadsUi(false);
request.setNotificationVisibility(2)
final long downloadId = downloadManager.enqueue(request);
manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
App.getUniversalContext().registerReceiver(new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
if (downloadId == intent.getExtras().getLong(DownloadManager.EXTRA_DOWNLOAD_ID)) {
mContext.unregisterReceiver(this);
//done use your file
}
}
}, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
/*check for timeout / errors and retry logic*/
private static void manageDownloadProcess(final String urlLink, final String pathUri, final String fileName, final long downloadId) {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterByStatus(DownloadManager.STATUS_PENDING | DownloadManager.STATUS_SUCCESSFUL | DownloadManager.STATUS_PAUSED | DownloadManager.STATUS_RUNNING | DownloadManager.STATUS_FAILED);
final Cursor cursor = downloadManager.query(query.setFilterById(downloadId));
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
if (cursor.moveToFirst()) {
int status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch (status) {
/*I introdused 'isEntered' param to eliminate first response from this method
* I don't know why but I get STATUS_PENDING always on first run, so this is an ugly workaround*/
case DownloadManager.STATUS_PENDING: {
Log.d("status", "STATUS_PENDING - timeout");
if (isEntered) {
if (alreadyRetried < RETRIES_MAX_NUMBER) {
alreadyRetried++;
downloadManager.remove(downloadId);
downloadFile(urlLink, pathUri, fileName);
manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
}
} else {
isEntered = true;
manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
}
break;
}
case DownloadManager.STATUS_PAUSED: {
Log.d("status", "STATUS_PAUSED - error");
if (alreadyRetried < RETRIES_MAX_NUMBER) {
alreadyRetried++;
downloadManager.remove(downloadId);
downloadFile(urlLink, pathUri, fileName);
}
break;
}
case DownloadManager.STATUS_RUNNING: {
Log.d("status", "STATUS_RUNNING - good");
manageDownloadProcess(urlLink, pathUri, fileName, downloadId);
break;
}
case DownloadManager.STATUS_SUCCESSFUL: {
Log.d("status", "STATUS_SUCCESSFUL - done");
break;
}
case DownloadManager.STATUS_FAILED: {
Log.d("status", "STATUS_FAILED - error");
if (alreadyRetried < RETRIES_MAX_NUMBER) {
alreadyRetried++;
downloadManager.remove(downloadId);
downloadFile(urlLink, pathUri, fileName);
}
break;
}
}
}
}
}, 5000);//do this after 5 sec
}
}