我正在尝试从互联网下载大文件(> 20Mb)
private class DownloadTask extends AsyncTask<DatabaseInfo, Integer, String> {
private DatabaseInfo info;
protected String doInBackground(DatabaseInfo... dbInfo) {
int count;
info = dbInfo[0];
try {
URL url = new URL(dbInfo[0].dbPath);
InputStream input = new BufferedInputStream(url.openStream());
OutputStream output = new FileOutputStream("/sdcard/db.zip");
byte data[] = new byte[1024];
int total = 0;
while ((count = input.read(data)) != -1) {
//output.write(data, 0, count);
total += count;
if (total % 10240 == 0) {
publishProgress(total);
}
}
output.flush();
output.close();
input.close();
}
catch (Exception e) {
Log.e("err", e.getMessage());
}
return null;
}
protected void onProgressUpdate(Integer... total) {
int perc = (int) ((float) total[0] / (float) info.dbZipSize * 100);
mProgressDialog.setProgress(perc);
}
protected void onPostExecute(String s) {
dismissDialog(DIALOG_PROGRESS);
Log.e("err", "finish!");
}
}
如果我取消注释行
//output.write(data, 0, count);
7-15%下载进度条对话框后,我看到“完成!”在日志中。为什么呢?
答案 0 :(得分:5)
您应该考虑实现HTTP范围。这将允许您在失败时重新开始下载。
至于它停止的原因,一些运营商实施下载限制,这将在一定时间或下载量后丢弃连接。我亲眼看到一家英国航空公司的第一手资料,并在其他航空公司上被告知。通过尝试通过Androids浏览器下载文件来验证限制通常很容易,如果你看到它停止或停止你知道它很可能是一个载体问题(是的,下载可以终止而不会抛出异常)。
Http Range实现将允许您从停止的位置继续下载,因此您的doInBackground方法使用hold-off和resume算法,以便每次连接中断时等待一段时间然后尝试恢复下载停止的地方(当然,实现重试限制,这样当手机真的无法下载文件时,你不会以无限循环结束)。
答案 1 :(得分:0)
有一个很好的库可以处理所有这些问题,此外还具有恢复功能,以应对网络因某些未知原因脱机的情况。 android库称为PRDownloader,可在Github上找到: https://github.com/MindorksOpenSource/PRDownloader
首先,您需要将其添加到gradle文件中,如下所示(当前版本为os 0.6.0)
implementation 'com.mindorks.android:prdownloader:0.6.0'
之后,可以在我开发的应用中实现的类中使用它,如下所示。它使用进度对话框显示下载的百分比,并且如上所述,在网络脱机或用户退出应用程序的情况下,可以稍后进行下载。 可以根据具体需要进行调整,代码如下:
public class DownloadManager {
private MainActivity activity;
private ProgressDialog progressDialog;
private int downloadStatus;
private String filename="";
private static String dirPath;
private String URL = "https://someurl.com/dummyfile.pdf";
public DownloadManager(MainActivity _activity){
this.activity=_activity;
dirPath = Utils.getRootDirPath(activity);
downloadStatus=0;
}
public void setDownloadUrl(String url){
this.URL=url;
}
public String getFileNameDirPath(){
return dirPath+"/"+filename;
};
public void setFilename(String filename){
this.filename=filename;
}
public String getFilename(){
return this.filename;
}
public String getDirectoryPath(){
return this.filename;
}
public void startFileDownload(){
if (Status.RUNNING == PRDownloader.getStatus(downloadStatus)) {
PRDownloader.pause(downloadStatus);
return;
}
this.progressDialog = new ProgressDialog(this.activity);
this.progressDialog.setIndeterminate(true);
this.progressDialog.setTitle("Title");
this.progressDialog.setMessage("Downloading file...");
this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.progressDialog.setCancelable(false);
this.progressDialog.setMax(100);
this.progressDialog.show();
if (Status.PAUSED == PRDownloader.getStatus(downloadStatus)) {
PRDownloader.resume(downloadStatus);
return;
}
downloadStatus = PRDownloader.download(URL, dirPath, this.filename)
.build()
.setOnStartOrResumeListener(new OnStartOrResumeListener() {
@Override
public void onStartOrResume() {
progressDialog.setIndeterminate(false);
}
})
.setOnPauseListener(new OnPauseListener() {
@Override
public void onPause() {
}
})
.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel() {
progressDialog.setProgress(0);
downloadStatus = 0;
progressDialog.setIndeterminate(false);
progressDialog.dismiss();
}
})
.setOnProgressListener(new OnProgressListener() {
@Override
public void onProgress(Progress progress) {
long progressPercent = progress.currentBytes * 100 / progress.totalBytes;
progressDialog.setProgress((int) progressPercent);
progressDialog.setIndeterminate(false);
}
})
.start(new OnDownloadListener() {
@Override
public void onDownloadComplete() {
progressDialog.dismiss();
activity.fragmentManagement.setCurrentFragment("MapFragment");
}
@Override
public void onError(Error error) {
Toast.makeText(activity, "Error downloading file", Toast.LENGTH_SHORT).show();
progressDialog.setProgress(0);
downloadStatus = 0;
progressDialog.setIndeterminate(false);
progressDialog.dismiss();
}
});
}
public static final class Utils {
private Utils() {
// no instance
}
public static String getRootDirPath(Context context) {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File file = ContextCompat.getExternalFilesDirs(context.getApplicationContext(),
null)[0];
return file.getAbsolutePath();
} else {
return context.getApplicationContext().getFilesDir().getAbsolutePath();
}
}
public static String getProgressDisplayLine(long currentBytes, long totalBytes) {
return getBytesToMBString(currentBytes) + "/" + getBytesToMBString(totalBytes);
}
private static String getBytesToMBString(long bytes){
return String.format(Locale.ENGLISH, "%.2fMb", bytes / (1024.00 * 1024.00));
}
}
}