在安卓设备上下载文件并显示进度条:完整指南

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

在安卓上下载文件:从想法到可运行的代码

\n\n

每一位安卓开发者迟早都会遇到从网络下载文件的任务。这可能是应用更新、下载图片、PDF文档或音乐文件。但仅仅下载文件只是成功了一半。用户需要看到过程正在进展:已下载多少、还剩多少、以及应用没有卡死。

\n\n

在本文中,我们将解析一个来自 Stack Overflow 的经典问题,该问题获得了数千次浏览:如何在安卓上下载文件并在对话框中显示进度。我们将使用 Java 编写代码,利用 AsyncTask 和 ProgressDialog(尽管在现代项目中它们常被协程或RxJava取代,但理解经典方法仍是不可或缺的基础)。

\n\n

准备好了吗?我们开始吧!

\n\n

为什么这么难?安卓下载的三个陷阱

\n\n

乍一看,任务很简单:打开连接、读取字节流、写入文件。但在实践中,开发者常常在三个方面遇到问题:

\n\n
    \n
  • UI线程被阻塞 — 如果在主线程中启动下载,应用会“冻结”,安卓会显示“应用无响应”对话框。
  • \n
  • 进度不更新 — 即使你计算了字节数,也不能直接从后台线程更改UI。
  • \n
  • 配置发生变化 — 用户旋转屏幕,你的 Activity 被重建。对话框消失,下载也失去了目标。
  • \n
\n\n

我们将解决所有这三个问题。先从架构开始,然后编写代码。

\n\n

选择工具:AsyncTask 和 ProgressDialog

\n\n

出于教学目的,我们使用经典方法:

\n
    \n
  • AsyncTask — 用于执行后台工作并发布进度。
  • \n
  • ProgressDialog — 用于显示百分比。
  • \n
  • HttpURLConnection — 用于HTTP请求(它仍然可用,尽管已过时)。
  • \n
\n\n

重要提示: 在实际项目中,如今更常使用 DownloadManager、WorkManager 或诸如 Retrofit + OkHttp 之类的库。但理解“手动”下载的工作原理是任何开发者的必备技能。

\n\n

完整代码:使用ProgressDialog下载文件

\n\n

下面是一个现成的下载类。代码附有中文注释,以便您立即理解正在发生的事情。

\n\n
import android.app.ProgressDialog;\nimport android.content.Context;\nimport android.os.AsyncTask;\nimport android.os.Environment;\nimport android.widget.Toast;\n\nimport java.io.File;\nimport java.io.FileOutputStream;\nimport java.io.InputStream;\nimport java.net.HttpURLConnection;\nimport java.net.URL;\n\npublic class DownloadFileTask extends AsyncTask<String, Integer, String> {\n\n    private Context context;\n    private ProgressDialog progressDialog;\n\n    public DownloadFileTask(Context context) {\n        this.context = context;\n    }\n\n    @Override\n    protected void onPreExecute() {\n        super.onPreExecute();\n        // 创建并显示进度对话框\n        progressDialog = new ProgressDialog(context);\n        progressDialog.setTitle("文件下载");\n        progressDialog.setMessage("正在下载...");\n        progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);\n        progressDialog.setCancelable(false); // 防止意外关闭\n        progressDialog.show();\n    }\n\n    @Override\n    protected String doInBackground(String... params) {\n        String fileUrl = params[0];\n        String fileName = "downloaded_file.pdf"; // 可以作为第二个参数传递\n        InputStream inputStream = null;\n        FileOutputStream outputStream = null;\n\n        try {\n            // 1. 建立连接\n            URL url = new URL(fileUrl);\n            HttpURLConnection connec                

博客

书籍推荐