安卓下载文件主要有三种方式
- 自己写
- 用框架
- 用系统DownloadManager
我这里简单封装了一下DownloadManager,方便使用。
注意,需要申请【网络】【存储】权限。
还需要配置<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
import android.app.DownloadManager
import android.content.Context
import android.content.Context.DOWNLOAD_SERVICE
import android.database.Cursor
import android.net.Uri
import android.os.Handler
import android.os.Looper
import com.damailab.camera.App
import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService
class DownloadUtil(
private val context: Context,
private var listener: DownloadListener?,
private val updateTime: Long = 500
) {
companion object {
private const val HANDLE_DOWNLOAD = 1
private const val HANDLE_LOOP = 2
}
interface DownloadListener {
fun onSuccess()
fun onFailed()
fun onProgress(progress: Float)
}
private var downloadManager: DownloadManager? = null
private var scheduledExecutorService: ScheduledExecutorService? = null
private var downloadIds = mutableListOf<Long>()
private val downLoadHandler = Handler(Looper.getMainLooper()) {
if (it.what == HANDLE_DOWNLOAD) {
when (it.obj as Int) {
DownloadManager.STATUS_FAILED -> {
listener?.onFailed()
}
}
if (it.arg1 >= 0 && it.arg2 > 0) {
if (it.arg1 == it.arg2) {
listener?.onSuccess()
}
listener?.onProgress(it.arg1.toFloat() / it.arg2)
}
} else if (it.what == HANDLE_LOOP) {
updateProgress()
}
return@Handler true
}
fun download(url: String, startListen: Boolean = true) {
downloadManager = App.appContext.getSystemService(DOWNLOAD_SERVICE) as DownloadManager
scheduledExecutorService = Executors.newSingleThreadScheduledExecutor()
val request = DownloadManager.Request(Uri.parse(url))
request.apply {
setAllowedOverRoaming(true)
//setDestinationUri(Uri.fromFile(File(path)))
setDestinationInExternalFilesDir(context, "file", url.substringAfterLast("/"))
setNotificationVisibility(DownloadManager.Request.VISIBILITY_HIDDEN)
setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI or DownloadManager.Request.NETWORK_MOBILE)
}
downloadIds.add(downloadManager?.enqueue(request) ?: -1L)
downLoadHandler.removeMessages(HANDLE_LOOP)
if (startListen) {
downLoadHandler.sendMessageDelayed(
downLoadHandler.obtainMessage(HANDLE_LOOP),
updateTime
)
}
}
fun cancel() {
for (id in downloadIds) {
downloadManager?.remove(id)
}
downLoadHandler.removeCallbacksAndMessages(null)
clear()
}
fun clear() {
downloadIds = mutableListOf()
listener = null
}
private fun updateProgress() {
val result = intArrayOf(0, 0, 0)
for (id in downloadIds) {
val bytesAndStatus: IntArray = getBytesAndStatus(id)
result[0] += bytesAndStatus[0]
result[1] += bytesAndStatus[1]
if (bytesAndStatus[2] == DownloadManager.STATUS_FAILED) {
result[2] = bytesAndStatus[2]
}
}
downLoadHandler.sendMessage(
downLoadHandler.obtainMessage(
HANDLE_DOWNLOAD,
result[0], result[1], result[2]
)
)
downLoadHandler.sendMessageDelayed(downLoadHandler.obtainMessage(HANDLE_LOOP), updateTime)
}
private fun getBytesAndStatus(downloadId: Long): IntArray {
val bytesAndStatus = intArrayOf(
0, 0, 0
)
val query = DownloadManager.Query().setFilterById(downloadId)
var cursor: Cursor? = null
try {
cursor = downloadManager!!.query(query)
if (cursor != null && cursor.moveToFirst()) {
//已经下载文件大小
bytesAndStatus[0] =
cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
//下载文件的总大小
bytesAndStatus[1] =
cursor.getInt(cursor.getColumnIndexOrThrow(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
//下载状态
bytesAndStatus[2] =
cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
}
} catch (e: Exception) {
} finally {
cursor?.close()
}
return bytesAndStatus
}
}
使用方法:
downloadUtils = DownloadUtil(this, object : DownloadUtil.DownloadListener {
override fun onFailed() {
Log.d("qweqweqwe","下载失败")
downloadUtils.cancel()
}
override fun onProgress(progress: Float) {
Log.d("qweqweqwe","下载中$progress")
}
override fun onSuccess() {
Log.d("qweqweqwe","下载成功")
downloadUtils.clear()
}
}).apply {
download("https://xxx", false)
download("https://xxx")
Log.d("qweqweqwe","下载开始")
}
更多扩展可以自行阅读源码