Android-+-+-++++=+_+Ԧ¥i
# Android文件下载:从基础到进阶的完整指南
在Android应用开发中,文件下载是一个常见且重要的功能。无论是更新应用、下载媒体内容还是获取文档,一个稳定高效的下载系统都能显著提升用户体验。本文将深入探讨Android文件下载的各个方面,从基础实现到高级优化。
## 基础实现:使用DownloadManager
Android系统内置了`DownloadManager`类,这是最简单且功能强大的下载解决方案之一。
### 基本配置与使用
```kotlin
val downloadManager = getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val request = DownloadManager.Request(Uri.parse("https://example.com/file.pdf"))
.setTitle("示例文件")
.setDescription("正在下载文件...")
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "file.pdf")
.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
.setAllowedOverRoaming(false)
val downloadId = downloadManager.enqueue(request)
```
### 监听下载进度
```kotlin
val query = DownloadManager.Query().setFilterById(downloadId)
val cursor = downloadManager.query(query)
if (cursor.moveToFirst()) {
val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
val bytesDownloaded = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
val bytesTotal = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
if (bytesTotal > 0) {
val progress = (bytesDownloaded * 100L / bytesTotal).toInt()
// 更新UI显示进度
}
}
```
## 进阶方案:自定义下载服务
对于更复杂的需求,如断点续传、多任务并行下载或自定义通知,需要实现自己的下载服务。
### 创建下载服务
```kotlin
class FileDownloadService : Service() {
private val binder = LocalBinder()
private val executor = Executors.newFixedThreadPool(3)
inner class LocalBinder : Binder() {
fun getService(): FileDownloadService = this@FileDownloadService
}
override fun onBind(intent: Intent): IBinder = binder
fun downloadFile(url: String, destination: File, callback: DownloadCallback) {
executor.execute {
try {
val connection = URL(url).openConnection() as HttpURLConnection
connection.connect()
if (connection.responseCode == HttpURLConnection.HTTP_OK) {
val totalSize = connection.contentLength
val inputStream = connection.inputStream
val outputStream = FileOutputStream(destination)
val buffer = ByteArray(4096)
var downloaded: Long = 0
var bytesRead: Int
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
outputStream.write(buffer, 0, bytesRead)
downloaded += bytesRead
// 计算并回调进度
val progress = if (totalSize > 0) {
(downloaded * 100 / totalSize).toInt()
} else 0
callback.onProgress(progress)
}
outputStream.close()
inputStream.close()
callback.onSuccess(destination)
}
} catch (e: Exception) {
callback.onError(e)
}
}
}
interface DownloadCallback {
fun onProgress(progress: Int)
fun onSuccess(file: File)
fun onError(exception: Exception)
}
}
```
## 网络库集成:使用Retrofit + OkHttp
现代Android开发中,Retrofit和OkHttp是处理网络请求的标准方案。
### 配置与实现
```kotlin
// 创建OkHttpClient支持进度监听
val okHttpClient = OkHttpClient.Builder()
.addInterceptor { chain ->
val originalResponse = chain.proceed(chain.request())
originalResponse.newBuilder()
.body(ProgressResponseBody(originalResponse.body!!) { bytesRead, contentLength, done ->
// 处理进度更新
val progress = if (contentLength > 0) {
(bytesRead * 100 / contentLength).toInt()
} else 0
runOnUiThread {
// 更新UI
}
})
.build()
}
.build()
// 创建Retrofit实例
val retrofit = Retrofit.Builder()
.baseUrl("https://api.example.com/")
.client(okHttpClient)
.build()
// 定义下载接口
interface DownloadService {
@Streaming
@GET
suspend fun downloadFile(@Url fileUrl: String): Response