Commit f1eb821d authored by wanglei's avatar wanglei

...

parent 3b960565
......@@ -72,6 +72,7 @@ dependencies {
implementation(libs.material)
implementation(libs.androidx.activity)
implementation(libs.androidx.constraintlayout)
implementation(libs.core)
testImplementation(libs.junit)
androidTestImplementation(libs.androidx.junit)
androidTestImplementation(libs.androidx.espresso.core)
......
......@@ -7,6 +7,9 @@ import com.base.browserwhite.utils.ActivityManagerUtils
import com.downloader.PRDownloader
import com.downloader.PRDownloaderConfig
import com.facebook.FacebookSdk
import com.google.ar.core.Config
import com.liulishuo.filedownloader.FileDownloader
import com.liulishuo.filedownloader.connection.FileDownloadConnection
class MyApplication : Application() {
......@@ -103,11 +106,16 @@ class MyApplication : Application() {
}
private fun initPRDownloader() {
val config = PRDownloaderConfig.newBuilder()
.setReadTimeout(30000)
.setConnectTimeout(30000)
.setDatabaseEnabled(true)
.build()
PRDownloader.initialize(applicationContext, config)
// 创建 FileDownloader 的配置对象
// val config = FileDownloader.Config.Builder()
// .setConnectionComponent(FileDownloadConnection.Impl.create(this).setRetryOnGone(true))
// .setMinIntervalMillisCallbackProcess(1000) // 设置回调间隔时间
// .setPath("path/to/your/download/directory", true) // 设置下载文件的存储路径
// // 其他配置...
// .build()
// 初始化 FileDownloader
FileDownloader.setupOnApplicationOnCreate(this)
}
}
\ No newline at end of file
package com.base.browserwhite.bean
import com.downloader.Status
data class DownloadBean(
var downloadId: Int = -1,
var path: String = "",
val uri: String = "",
val url: String = "",
var time: String = "",
) {
var state: Status = Status.UNKNOWN
var progress: Int = -1
var name: String = ""
var isTime: Boolean = false
var uiType: Int = 1
var size: Long = -1
}
\ No newline at end of file
......@@ -20,18 +20,22 @@ import com.base.browserwhite.bean.DownloadBean
import com.base.browserwhite.databinding.FragmentWebViewBinding
import com.base.browserwhite.ui.adapter.DownloadAdapter
import com.base.browserwhite.ui.fragment.BaseFragment
import com.base.browserwhite.ui.views.DialogViews.showDownloadVideoDialog
import com.base.browserwhite.ui.views.DownloadDialog.showDownloadVideoDialog
import com.base.browserwhite.utils.DownloadHelper.getDownloadJson
import com.base.browserwhite.utils.DownloadHelper.getNotFinishList
import com.base.browserwhite.utils.KotlinExt.toFormatTime
import com.base.browserwhite.utils.LogEx
import com.downloader.PRDownloader
import com.downloader.Status
import com.google.gson.Gson
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import org.json.JSONArray
import java.io.IOException
import kotlin.random.Random
......@@ -75,6 +79,7 @@ class WebViewFragment : BaseFragment<FragmentWebViewBinding>() {
}
reloadWebView()
}
binding.flDownload.setOnClickListener {
if (downloadAdapter == null) {
downloadAdapter = DownloadAdapter()
......@@ -97,15 +102,10 @@ class WebViewFragment : BaseFragment<FragmentWebViewBinding>() {
val recordFile = requireContext().getDownloadJson()
val gson = Gson()
val list = downloadList.filter {
it.state == Status.PAUSED || it.state == Status.RUNNING
}
val list = downloadList
list.forEach { it.time = System.currentTimeMillis().toFormatTime() }
val olderList = getNotFinishList(recordFile, gson).filter { old ->
val status = PRDownloader.getStatus(old.downloadId)
status == Status.PAUSED || status == Status.RUNNING
}.filter { !list.contains(it) }
val olderList = getNotFinishList(recordFile, gson).filter { !list.contains(it) }
val arrayList = arrayListOf<DownloadBean>()
arrayList.addAll(olderList)
......@@ -283,20 +283,32 @@ class WebViewFragment : BaseFragment<FragmentWebViewBinding>() {
LogEx.logDebug(TAG, "value=$value")
// 将字符串转换为JSON数组,然后处理
val jsonArray = JSONArray(value)
if (jsonArray.length() != 0) {
binding.flDownload.visibility = View.VISIBLE
binding.tvDownloadNumber.text = jsonArray.length().toString()
}
val recordFile = requireContext().getDownloadJson()
val olderList = getNotFinishList(recordFile, Gson())
val set = hashSetOf<String>()
for (i in 0 until jsonArray.length()) {
val videoUrl = jsonArray.optString(i)
LogEx.logDebug(TAG, videoUrl)
val olderBean = olderList.findLast { it.uri == videoUrl }
set.add(videoUrl)
}
if (set.size != 0) {
binding.flDownload.visibility = View.VISIBLE
binding.tvDownloadNumber.text = set.size.toString()
}
set.forEach { url ->
LogEx.logDebug(TAG, url)
val olderBean = olderList.findLast { it.url == url }
if (olderBean != null) {
LogEx.logDebug(TAG, "old path=${olderBean.path} ${olderBean.downloadId}")
downloadList.add(olderBean)
} else {
downloadList.add(DownloadBean(uri = videoUrl).apply { uiType = 2 })
downloadList.add(DownloadBean(url = url).apply { uiType = 2 })
}
}
lifecycleScope.launch(Dispatchers.IO) {
downloadList.forEach {
fastGetSize(it)
}
}
isParsing = false
......@@ -339,4 +351,39 @@ class WebViewFragment : BaseFragment<FragmentWebViewBinding>() {
}
}
private fun fastGetSize(bean: DownloadBean) {
if (bean.size == -1L) {
val client = OkHttpClient()
val request = Request.Builder()
.url(bean.url)
.head() // 发送 HEAD 请求
.build()
try {
client.newCall(request).enqueue(object : Callback {
override fun onFailure(call: Call, e: IOException) {
// 处理请求失败的情况
LogEx.logDebug(TAG, "onFailure")
}
override fun onResponse(call: Call, response: Response) {
if (response.isSuccessful) {
val contentLength = response.header("Content-Length") // 获取内容长度
contentLength?.let {
// 将内容长度转换为 Long 类型
val videoSize = it.toLong()
// 在这里使用视频大小,例如在主线程更新 UI 或存储到变量中
bean.size = videoSize
LogEx.logDebug(TAG, "videoSize=$videoSize")
}
}
}
})
} catch (e: Exception) {
// 处理异常情况
}
}
}
}
\ No newline at end of file
......@@ -11,16 +11,24 @@ import com.base.browserwhite.bean.DownloadBean
import com.base.browserwhite.databinding.ItemDownloadBinding
import com.base.browserwhite.databinding.ItemDownloadCardBinding
import com.base.browserwhite.databinding.ItemDownloadTimeBinding
import com.base.browserwhite.ui.views.DownloadDialog.showDownloadConfirmDialog
import com.base.browserwhite.utils.KotlinExt.toFormatSize
import com.base.browserwhite.utils.LogEx
import com.base.browserwhite.utils.VideoDownloader
import com.base.browserwhite.utils.VideoDownloader.getDownloadPath
import com.base.browserwhite.utils.XmlEx.inflate
import com.bumptech.glide.Glide
import com.chad.library.adapter4.BaseQuickAdapter
import com.downloader.PRDownloader
import com.downloader.Status
import com.downloader.internal.DownloadRequestQueue
import com.liulishuo.filedownloader.BaseDownloadTask
import com.liulishuo.filedownloader.FileDownloadListener
import com.liulishuo.filedownloader.FileDownloader
import com.liulishuo.filedownloader.model.FileDownloadStatus
import okhttp3.Call
import okhttp3.Callback
import okhttp3.OkHttpClient
import okhttp3.Request
import okhttp3.Response
import java.io.File
import java.io.IOException
class DownloadAdapter : BaseQuickAdapter<DownloadBean, DownloadAdapter.DownloadViewHolder>() {
......@@ -29,7 +37,7 @@ class DownloadAdapter : BaseQuickAdapter<DownloadBean, DownloadAdapter.DownloadV
inner class DownloadViewHolder(view: View) : ViewHolder(view)
var downloadAction: ((item: DownloadBean) -> Unit)? = null
var downloadAction: (() -> Unit)? = null
override fun onBindViewHolder(holder: DownloadViewHolder, position: Int, item: DownloadBean?) {
if (item == null) return
......@@ -47,25 +55,30 @@ class DownloadAdapter : BaseQuickAdapter<DownloadBean, DownloadAdapter.DownloadV
} else if (item.uiType == 2) {
val binding = ItemDownloadCardBinding.bind(holder.itemView)
Glide.with(context).load(item.uri).centerCrop().into(binding.iv)
binding.tvName.text = if (item.name.isNotEmpty()) item.name else item.uri.split("/").last()
Glide.with(context).load(item.url).centerCrop().into(binding.iv)
binding.tvName.text = if (item.name.isNotEmpty()) item.name else item.url.split("/").last()
binding.tvSize.text = item.size.toFormatSize()
binding.ivDownload.isVisible = item.downloadId == -1
binding.flDownload.isVisible = item.state != Status.UNKNOWN
val status = FileDownloader.getImpl().getStatus(item.url, item.path)
LogEx.logDebug(TAG, "status=${status} item.path=${item.path}")
binding.ivDownload.isVisible = status == FileDownloadStatus.INVALID_STATUS
binding.flDownload.isVisible = !binding.ivDownload.isVisible
binding.ivFinish.isVisible = false
when (item.state) {
Status.PAUSED -> {
when (status) {
FileDownloadStatus.paused -> {
binding.ivXiazaiZantin.setImageResource(R.mipmap.zanting_download)
binding.circularProgressBar.progress = item.progress.toFloat()
}
Status.RUNNING -> {
FileDownloadStatus.progress -> {
binding.ivXiazaiZantin.setImageResource(R.mipmap.xiazhaiz_download)
binding.circularProgressBar.progress = item.progress.toFloat()
replaceListener(item)
}
Status.COMPLETED -> {
FileDownloadStatus.completed -> {
binding.flDownload.isVisible = false
binding.ivFinish.isVisible = true
}
......@@ -76,16 +89,12 @@ class DownloadAdapter : BaseQuickAdapter<DownloadBean, DownloadAdapter.DownloadV
}
binding.ivDownload.setOnClickListener {
downloadAction?.invoke(item)
downloadAction?.invoke()
context.showDownloadConfirmDialog(item) {
downloadItem(context, item)
}
}
binding.flDownload.setOnClickListener {
val status: Status = PRDownloader.getStatus(item.downloadId)
if (status == Status.PAUSED) {
PRDownloader.resume(item.downloadId)
}
if (status == Status.RUNNING) {
PRDownloader.pause(item.downloadId)
}
}
}
......@@ -108,25 +117,76 @@ class DownloadAdapter : BaseQuickAdapter<DownloadBean, DownloadAdapter.DownloadV
}
@SuppressLint("NotifyDataSetChanged")
fun downloadItem(bean: DownloadBean) {
val pair = VideoDownloader.downloadVideo2(
context, bean.uri, bean.name,
progressAction = { progress ->
LogEx.logDebug(TAG, "progress=$progress")
bean.progress = progress
val status: Status = PRDownloader.getStatus(bean.downloadId)
bean.state = status
fun downloadItem(context: Context, bean: DownloadBean) {
bean.path = context.getDownloadPath(bean.url, bean.name)
val downloadTask = FileDownloader.getImpl().create(bean.url)
.setPath(bean.path)
.setCallbackProgressMinInterval(500)
.setListener(object : FileDownloadListener() {
override fun pending(task: BaseDownloadTask?, soFarBytes: Int, totalBytes: Int) {
}
override fun progress(task: BaseDownloadTask?, soFarBytes: Int, totalBytes: Int) {
val percent = soFarBytes * 100 / totalBytes
bean.progress = percent
notifyDataSetChanged()
}
override fun connected(task: BaseDownloadTask?, etag: String?, isContinue: Boolean, soFarBytes: Int, totalBytes: Int) {
super.connected(task, etag, isContinue, soFarBytes, totalBytes)
if (isContinue) {
// 如果是继续之前的下载
}
}
override fun completed(task: BaseDownloadTask?) {
notifyDataSetChanged()
}
override fun paused(task: BaseDownloadTask?, soFarBytes: Int, totalBytes: Int) {
}
override fun error(task: BaseDownloadTask?, e: Throwable?) {
}
override fun warn(task: BaseDownloadTask?) {
}
})
downloadTask.start()
}
private fun replaceListener(item: DownloadBean) {
FileDownloader.getImpl().replaceListener(item.downloadId, object : FileDownloadListener() {
override fun pending(task: BaseDownloadTask?, soFarBytes: Int, totalBytes: Int) {
}
@SuppressLint("NotifyDataSetChanged")
override fun progress(task: BaseDownloadTask?, soFarBytes: Int, totalBytes: Int) {
val percent = soFarBytes * 100 / totalBytes
item.progress = percent
notifyDataSetChanged()
},
finishAction = {
val status: Status = PRDownloader.getStatus(bean.downloadId)
bean.state = status
LogEx.logDebug(TAG, "status=$status")
}
@SuppressLint("NotifyDataSetChanged")
override fun completed(task: BaseDownloadTask?) {
notifyDataSetChanged()
}
)
bean.downloadId = pair.first
bean.path = pair.second.absolutePath
override fun paused(task: BaseDownloadTask?, soFarBytes: Int, totalBytes: Int) {
}
override fun error(task: BaseDownloadTask?, e: Throwable?) {
}
override fun warn(task: BaseDownloadTask?) {
}
})
}
}
\ No newline at end of file
......@@ -234,114 +234,5 @@ object DialogViews {
}
}
fun Context.showDownloadVideoDialog(
adapter: DownloadAdapter,
list: List<DownloadBean>,
dismissAction: () -> Unit
): DownloadAdapter {
val TAG = "DownloadVideoDialog"
val dialog = BottomSheetDialog(this)
val binding = DialogDownloadVideoBinding.inflate(LayoutInflater.from(this))
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(false)
dialog.show()
val itemHeight = resources.getDimensionPixelOffset(R.dimen.dp_97)
LogEx.logDebug(TAG, "itemHeight=$itemHeight")
if (list.size > 3) {
val recyclerViewHeight: Int = 3 * itemHeight
binding.rv.layoutParams.height = recyclerViewHeight
binding.rv.requestLayout()
}
val parentView = binding.root.parent as View
val behavior = BottomSheetBehavior.from(parentView)
//展开
behavior.state = BottomSheetBehavior.STATE_EXPANDED
adapter.downloadAction = { item: DownloadBean ->
dialog.dismiss()
showDownloadConfirmDialog(item) {
adapter.downloadItem(item)
}
}
binding.rv.adapter = adapter
adapter.submitList(list)
dialog.setOnDismissListener {
dismissAction.invoke()
}
binding.tvDownloadDir.setOnClickListener {
dialog.dismiss()
startActivity(Intent(this, WebDownloadManagerActivity::class.java))
}
return adapter
}
private fun Context.showDownloadConfirmDialog(item: DownloadBean, download: () -> Unit) {
val dialog = BottomSheetDialog(this)
val binding = DialogDownloadConfirmBinding.inflate(LayoutInflater.from(this))
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(false)
dialog.show()
val parentView = binding.root.parent as View
val behavior = BottomSheetBehavior.from(parentView)
//展开
behavior.state = BottomSheetBehavior.STATE_EXPANDED
Glide.with(this).load(item.uri).centerCrop().into(binding.iv)
binding.editName.setText(item.uri.split("/").last())
binding.ivEdit.setOnClickListener {
binding.editName.isEnabled = true
binding.editName.setBackgroundResource(android.R.drawable.edit_text)
binding.editName.requestFocus()
}
binding.editName.setOnFocusChangeListener { v, hasFocus ->
if (hasFocus) {
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
imm?.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT)
}
}
binding.editName.setOnEditorActionListener(object : OnEditorActionListener {
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
if (actionId == EditorInfo.IME_ACTION_DONE) {
binding.editName.isEnabled = false
binding.editName.background = null
return true
}
return false
}
})
binding.tvCancel.setOnClickListener {
dialog.dismiss()
}
binding.tvConfirm.setOnClickListener {
if (binding.editName.text.isNullOrEmpty()) {
Toast.makeText(this, "name is empty", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
item.name = binding.editName.text.toString()
dialog.dismiss()
download.invoke()
}
}
fun Context.showDownloadFinishDialog() {
val binding = DialogDownloadFinishBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).create()
dialog.setView(binding.root)
dialog.show()
val params = dialog.window?.attributes
params?.width = resources.getDimensionPixelOffset(R.dimen.dp_335)
dialog.window?.attributes = params
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
}
}
\ No newline at end of file
package com.base.browserwhite.ui.views
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.View
import android.view.inputmethod.EditorInfo
import android.view.inputmethod.InputMethodManager
import android.widget.TextView
import android.widget.TextView.OnEditorActionListener
import android.widget.Toast
import com.base.browserwhite.R
import com.base.browserwhite.bean.DownloadBean
import com.base.browserwhite.databinding.DialogDownloadConfirmBinding
import com.base.browserwhite.databinding.DialogDownloadFinishBinding
import com.base.browserwhite.databinding.DialogDownloadVideoBinding
import com.base.browserwhite.ui.activity.download.WebDownloadManagerActivity
import com.base.browserwhite.ui.adapter.DownloadAdapter
import com.base.browserwhite.utils.LogEx
import com.bumptech.glide.Glide
import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog
object DownloadDialog {
fun Context.showDownloadVideoDialog(
adapter: DownloadAdapter,
list: List<DownloadBean>,
dismissAction: () -> Unit
) {
val TAG = "DownloadVideoDialog"
val dialog = BottomSheetDialog(this)
val binding = DialogDownloadVideoBinding.inflate(LayoutInflater.from(this))
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(false)
dialog.show()
val itemHeight = resources.getDimensionPixelOffset(R.dimen.dp_97)
LogEx.logDebug(TAG, "itemHeight=$itemHeight")
if (list.size > 3) {
val recyclerViewHeight: Int = 3 * itemHeight
binding.rv.layoutParams.height = recyclerViewHeight
binding.rv.requestLayout()
}
val parentView = binding.root.parent as View
val behavior = BottomSheetBehavior.from(parentView)
//展开
behavior.state = BottomSheetBehavior.STATE_EXPANDED
adapter.downloadAction = {
dialog.dismiss()
}
binding.rv.adapter = adapter
adapter.submitList(list)
dialog.setOnDismissListener {
dismissAction.invoke()
}
binding.tvDownloadDir.setOnClickListener {
dialog.dismiss()
startActivity(Intent(this, WebDownloadManagerActivity::class.java))
}
}
fun Context.showDownloadConfirmDialog(item: DownloadBean, download: () -> Unit) {
val dialog = BottomSheetDialog(this)
val binding = DialogDownloadConfirmBinding.inflate(LayoutInflater.from(this))
dialog.setContentView(binding.root)
dialog.setCanceledOnTouchOutside(false)
dialog.show()
val parentView = binding.root.parent as View
val behavior = BottomSheetBehavior.from(parentView)
//展开
behavior.state = BottomSheetBehavior.STATE_EXPANDED
Glide.with(this).load(item.url).centerCrop().into(binding.iv)
binding.editName.setText(item.url.split("/").last())
binding.ivEdit.setOnClickListener {
binding.editName.isEnabled = true
binding.editName.setBackgroundResource(android.R.drawable.edit_text)
binding.editName.requestFocus()
}
binding.editName.setOnFocusChangeListener { v, hasFocus ->
if (hasFocus) {
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager?
imm?.showSoftInput(v, InputMethodManager.SHOW_IMPLICIT)
}
}
binding.editName.setOnEditorActionListener(object : OnEditorActionListener {
override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
if (actionId == EditorInfo.IME_ACTION_DONE) {
binding.editName.isEnabled = false
binding.editName.background = null
return true
}
return false
}
})
binding.tvCancel.setOnClickListener {
dialog.dismiss()
}
binding.tvConfirm.setOnClickListener {
if (binding.editName.text.isNullOrEmpty()) {
Toast.makeText(this, "name is empty", Toast.LENGTH_SHORT).show()
return@setOnClickListener
}
item.name = binding.editName.text.toString()
dialog.dismiss()
download.invoke()
}
}
fun Context.showDownloadFinishDialog() {
val binding = DialogDownloadFinishBinding.inflate(LayoutInflater.from(this))
val dialog = AlertDialog.Builder(this).create()
dialog.setView(binding.root)
dialog.show()
val params = dialog.window?.attributes
params?.width = resources.getDimensionPixelOffset(R.dimen.dp_335)
dialog.window?.attributes = params
dialog.window?.setBackgroundDrawableResource(android.R.color.transparent)
}
}
\ No newline at end of file
package com.base.browserwhite.utils
import android.app.DownloadManager
import android.app.DownloadManager.Request.NETWORK_WIFI
import android.content.Context
import android.net.Uri
import android.os.Environment
import com.base.browserwhite.R
import com.downloader.Error
import com.downloader.OnDownloadListener
import com.downloader.PRDownloader
import com.downloader.internal.DownloadTask
import java.io.File
object VideoDownloader {
//https://assets.mixkit.co/videos/4702/4702-720.mp4
fun downloadVideo(context: Context, uri: String, name: String): Pair<Long, File> {
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
var fileName = uri.split("/").last()
if (name.isNotEmpty()) {
fileName = name
}
// 创建一个DownloadManager.Request对象
val request = DownloadManager.Request(Uri.parse(uri))
// 设置下载的标题和描述
request.setTitle(fileName)
request.setDescription("Downloading $fileName")
request.setAllowedNetworkTypes(NETWORK_WIFI)
// 设置通知栏的可见性
request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE)
// 设置下载的文件类型
request.setMimeType("video/mp4")
// 设置下载文件的存储位置
val subPath = context.resources.getString(R.string.app_name) + "/$fileName"
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, subPath)
// 设置是否允许漫游
request.setAllowedOverRoaming(false)
// 将下载请求加入下载队列
val downloadId = downloadManager.enqueue(request)
val filePath = File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), subPath)
return Pair(downloadId, filePath)
}
fun downloadVideo2(
context: Context,
fun Context.getDownloadPath(
url: String,
name: String,
progressAction: (progress: Int) -> Unit,
finishAction: () -> Unit
): Pair<Int, File> {
): String {
var fileName = url.split("/").last()
if (name.isNotEmpty()) {
fileName = name
}
// 设置下载文件的存储位置
val dirPath = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
context.resources.getString(R.string.app_name)
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS), resources.getString(R.string.app_name)
).absolutePath
val downloadId = PRDownloader.download(url, dirPath, fileName)
.build()
.setOnStartOrResumeListener { }
.setOnPauseListener { }
.setOnCancelListener { }
.setOnProgressListener {
val percent = it.currentBytes * 100 / it.totalBytes
progressAction.invoke(percent.toInt())
}.start(object : OnDownloadListener {
override fun onDownloadComplete() {
finishAction.invoke()
}
val path = "$dirPath/$fileName"
override fun onError(p0: Error?) {
finishAction.invoke()
}
})
val filePath = File(dirPath, fileName)
return Pair(downloadId, filePath)
return path
}
}
\ No newline at end of file
......@@ -14,6 +14,7 @@ navigationUiKtx = "2.6.0"
viewbinding = "8.5.1"
navigationFragmentKtxVersion = "2.6.0"
navigationUiKtxVersion = "2.6.0"
core = "1.45.0"
[libraries]
androidx-core-ktx = { group = "androidx.core", name = "core-ktx", version.ref = "coreKtx" }
......@@ -26,6 +27,7 @@ androidx-activity = { group = "androidx.activity", name = "activity", version.re
androidx-constraintlayout = { group = "androidx.constraintlayout", name = "constraintlayout", version.ref = "constraintlayout" }
androidx-navigation-fragment-ktx = { group = "androidx.navigation", name = "navigation-fragment-ktx", version.ref = "navigationFragmentKtxVersion" }
androidx-navigation-ui-ktx = { group = "androidx.navigation", name = "navigation-ui-ktx", version.ref = "navigationUiKtxVersion" }
core = { group = "com.google.ar", name = "core", version.ref = "core" }
[plugins]
androidApplication = { id = "com.android.application", version.ref = "agp" }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment