本文使用OkDownloader进行文件下载
https://github.com/ydxlt/okdownloader
https://ydxlt.github.io/okdownloader/
implementation("io.github.ydxlt:okdownloader:1.0.0")
val downloader = Downloader.Builder().build()
val request = Download.Request.Builder()
.url(it.url)
.into(it.savepath) // or into(file)
.build()
val call = downloader.newCall(request)
同步
call.execute()
异步调用
call.enqueue()
取消
call.cancel()
同步和异步都支持回调
call.execute(object : Download.Callback {
override fun onStart(call: Download.Call) {
}
override fun onSuccess(call: Download.Call, response: Download.Response) {
}
override fun onFailure(call: Download.Call, response: Download.Response) {
}
override fun onLoading(call: Download.Call, current: Long, total: Long) {
}
})
import com.billbook.lib.downloader.Download
import com.billbook.lib.downloader.Downloader
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import java.util.LinkedList
import java.util.Queue
object DownLoadUtils {
val queue: Queue<DownloadItem> = LinkedList()
var callbackList = mutableListOf<DownloadCallback>()
var isRunning = false
/**
* 页面启动 添加回调
*/
fun addCallback(callback: DownloadCallback) {
callbackList.add(callback)
}
/**
* 页面关闭 删除回调
*/
fun removeCallback(callback: DownloadCallback) {
callbackList.remove(callback)
}
/**
* 下载文件
*/
fun addDownload(url: String, tag: String, savepath: String) {
queue.add(DownloadItem(url, tag, savepath, 0))
downloadAction()
}
private fun downloadAction() {
if (isRunning) {
return
}
val coroutineScope = CoroutineScope(Dispatchers.IO)
coroutineScope.launch {
while (queue.size > 0) {
isRunning = true
val downItem = queue.peek()
downItem?.let {
try {
val downloader = Downloader.Builder().build()
val request = Download.Request.Builder()
.url(it.url)
.into(it.savepath) // or into(file)
.build()
val call = downloader.newCall(request)
call.execute(object : Download.Callback {
override fun onStart(call: Download.Call) {
for (downloadCallback in callbackList) {
downloadCallback.onStart(downItem)
}
}
override fun onSuccess(call: Download.Call, response: Download.Response) {
// do your job
queue.poll()
for (downloadCallback in callbackList) {
downloadCallback.onSuccess(downItem)
}
}
override fun onFailure(call: Download.Call, response: Download.Response) {
// do your job
queue.poll()
for (downloadCallback in callbackList) {
downloadCallback.onFailure(downItem)
}
}
override fun onLoading(call: Download.Call, current: Long, total: Long) {
for (downloadCallback in callbackList) {
val progress = (current * 100 / total).toInt()
if (progress != downItem.progress) {
downItem.progress = progress
downloadCallback.onLoading(downItem)
}
}
}
})
} catch (e: Exception) {
queue.poll()
for (downloadCallback in callbackList) {
downloadCallback.onFailure(downItem)
}
}
}
}
isRunning = false
}
}
}
data class DownloadItem(val url: String, val tag: String, val savepath: String, var progress: Int)
interface DownloadCallback {
fun onStart(downItem: DownloadItem)
fun onSuccess(downItem: DownloadItem)
fun onFailure(downItem: DownloadItem)
fun onLoading(downItem: DownloadItem)
}
使用
DisposableEffect(Unit) {
// 初始化操作,类似于 onCreate()
val callback = object : DownloadCallback {
override fun onStart(downItem: DownloadItem) {
Log.i("下载", "下载开始")
}
override fun onSuccess(downItem: DownloadItem) {
Log.i("下载", "下载成功")
}
override fun onFailure(downItem: DownloadItem) {
Log.i("下载", "下载失败")
}
override fun onLoading(downItem: DownloadItem) {
Log.i("下载", "下载进度${downItem.progress}")
}
}
DownLoadUtils.addCallback(callback)
onDispose {
// 清理资源,类似于 onDestroy()
DownLoadUtils.removeCallback(callback)
}
}
下载调用
DownLoadUtils.addDownload(
CommonData.fileUrl + appItem.apkPath,
appItem.appPackage,
File(baseContext.getExternalFilesDir(null), appItem.appPackage + ".apk").absolutePath
)