【问题标题】:Android: download large fileAndroid:下载大文件
【发布时间】:2011-02-07 19:28:36
【问题描述】:

我正在尝试从 Internet 下载大文件 (>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% 下载进度条对话框消失后,我看到“完成!”在日志中。为什么?

【问题讨论】:

  • 你是在设备还是模拟器上试过??如果您在模拟器中尝试过,则无法正常工作。因为你需要高系统配置。
  • 模拟器。好的,我会在设备上试试

标签: android asynchronous download android-asynctask


【解决方案1】:

您应该考虑实现 HTTP 范围。这将允许您在下载失败时重新开始下载。

至于为什么停止,一些运营商实施了下载限制,在一定时间或下载量后会断开连接。我在一家英国运营商上亲眼目睹了这一点,并在其他运营商上被告知过。尝试通过 Android 浏览器下载文件通常很容易验证限制,如果您看到它停止或停止,您知道这很可能是运营商问题(是的,下载可以终止而不会引发异常)。

Http Range 实现将允许您从中断处继续下载,因此您的 doInBackground 方法可以使用延迟和恢复算法,以便每次连接中断时您等待一段时间然后尝试从停止的地方继续下载(当然,实现重试限制,这样当手机真的无法下载文件时,您就不会陷入无限循环)。

【讨论】:

    【解决方案2】:

    有一个非常好的库可以处理所有这些,并且在网络由于某种未知原因而脱机的情况下具有恢复功能。 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));
        }
    
    }
    

    }

    【讨论】:

      猜你喜欢
      • 2022-01-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-04
      • 1970-01-01
      • 2022-10-18
      • 2018-11-14
      相关资源
      最近更新 更多