用android下载一个文件,在ProgressDialog显示下载进度

  1. 使用AsyncTask,在一个对话框中显示下载进度

这个方法可以让你进行后台处理的同时更新UI(在这种情况下,我们将更新一个进度条)
这是实例代码:

// 声明对话框是你activity的成员字段
ProgressDialog mProgressDialog;

// 举例说明在onCreate中的方法
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

DownloadFile downloadFile = new DownloadFile();
downloadFile.execute("the url to the file you want to download");

AsyncTask像这样:

// 通常,AsyncTask子类在activity类中进行声明
// 这样,你可以很容易在这里修改UI线程
private class DownloadFile extends AsyncTask<String, Integer, String> {
    @Override
    protected String doInBackground(String... sUrl) {
        try {
            URL url = new URL(sUrl[0]);
            URLConnection connection = url.openConnection();
            connection.connect();
            //这将是有用的,这样你可以显示一个典型的0-100%的进度条
            int fileLength = connection.getContentLength();

            // 下载文件
            InputStream input = new BufferedInputStream(url.openStream());
            OutputStream output = new FileOutputStream("/sdcard/file_name.extension");

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } catch (Exception e) {
        }
        return null;
    }

上边的方法(doInBackground)一直在一个后台线程中进行。你不需要做任何UI的任务。另一方面,onProgressUpdate和onPreExecute在UI线程上运行,因此你可以改变进度条

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        mProgressDialog.setProgress(progress[0]);
    }
}

一旦文件已经下载完,如果你想要执行一些代码(例如mProgressDialog.dismiss()),你也可能想要重写onPostExecute方法。

2.从服务器下载

这个大的问题是:我如何从服务器上更新我的activity?在下个示例中,我们将使用两个你可能没有太注意过的类:ResultReceiver和IntentService. ResultReceiver允许我们从服务器上更新我们的线程的类,IntentService 是Service的一个子类,从那,它可以产生一个线程来处理后台任务(你应该知道,你的应用的Service在同样的进程运行;当你继承Service时,你必须手动生成新的线程来运行CPU的阻塞操作)
可以像这样:

public class DownloadService extends IntentService {
   public static final int UPDATE_PROGRESS= 8344;‘
   public DownloadService() {
       super("DownloadService");
   }
   @Override
   protected void onHandleIntent(Intent intent) {
       String urlToDownload= intent.getStringExtra("url");
       ResultReceiver receiver= (ResultReceiver)
 intent.getParcelableExtra("receiver");
       try {
            URL url= new URL(urlToDownload);
           URLConnection connection= url.openConnection();
            connection.connect();
           // 这将是有用的,这样你可以显示一个典型的0-100%的进度条
           int fileLength= connection.getContentLength();
           // 下载文件
           InputStream input= new BufferedInputStream(url.openStream());
           OutputStream output= new FileOutputStream("/sdcard/BarcodeScanner-debug.apk");
           byte data[] = new byte[1024];
           long total= 0;
           int count;
           while ((count= input.read(data)) != -1) {
                total+= count;
               Bundle resultData= new Bundle();
                resultData.putInt("progress" ,(int) (total* 100 / fileLength));
                receiver.send(UPDATE_PROGRESS, resultData);
                output.write(data, 0, count);
           }
            output.flush();
            output.close();
            input.close();

}catch (IOException e) {

            e.printStackTrace();
       }
       Bundle resultData= new Bundle();
        resultData.putInt("progress" ,100);
        receiver.send(UPDATE_PROGRESS, resultData);
   }
}

向你的manifest中加service

<service android:name=".DownloadService"/>

Activity将像这样

// 像第一个例子那样初始化进度条

//这是你怎么启动下载器
mProgressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url", "url of the file to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);

这是ResultReceiver开始起作用

private class DownloadReceiver extends ResultReceiver{
    public DownloadReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);
        if (resultCode == DownloadService.UPDATE_PROGRESS) {
            int progress = resultData.getInt("progress");
            mProgressDialog.setProgress(progress);
            if (progress == 100) {
                mProgressDialog.dismiss();
            }
        }
    }
}

3.使用DownloadManager 类(GingerBread ,而且仅仅是最新的)
这个方法是可怕的,你不用担心手动下载文件,处理线程,数据流,等等。GingerBread有一个新的特点,DownloadManager可以让你很容易的下载文件,然后将辛苦的工作给系统做。

/**
 * @ param上下文用来检查设备的版本和DownloadManager信息
 * @如果下载管理器可以用,则返回true
 */
public static boolean isDownloadManagerAvailable(Context context) {
   try {
       if (Build.VERSION.SDK_INT< Build.VERSION_CODES.GINGERBREAD) {
           return false;
       }
       Intent intent= new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setClassName("com.android.providers.downloads.ui", "com.android.providers.downloads.ui.DownloadList");
       List<ResolveInfo> list= context.getPackageManager().queryIntentActivities(intent,
               PackageManager.MATCH_DEFAULT_ONLY);
       return list.size() > 0;
   } catch (Exception e) {
       return false;
   }
}

方法的名字直接就解释了。一旦你确定DownloadManager是可用的,你可以做下边这些:

String url= "url you want to download";
DownloadManager.Request request= new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");request.setTitle("Some title");
// 如果为了让它运行,你必须用android3.2编译你的应用程序
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.HONEYCOMB) {
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext");
// 获得下载服务和队列文件
DownloadManager manager= (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);

下载进度条将在通知栏显示
结语
第一个和第二个方法仅仅是冰山一角。如果你想要你的app是健壮的,这有很多事情需要你记住。这是一个简短的列表:

  • 你必须检查用户是否有可用的网络链接。

  • 确定你有权限((INTERNET and
    WRITEEXTERNALSTORAGE);如果你想要检查网络是否可用也可以用ACCESSNETWORKSTATE

  • 确保你要下载的文件的目录存在,有读写权限

  • 如果下载包太大,之前的下载失败了,你可能需要实现一种方法来恢复下载

  • 如果你允许用户中断下载,他们会很感激你。

除非你已经完全控制了下载过程,否则我强烈建议你使用DownloadManager ,它已经实现了上边列出的大部分功能。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值