Download Manager library using Coroutine, Flow and WorkManager.
Using other 3xCool libraries:
- Fileman for File Management;
- CoroExecutor for Coroutine executor schema (Queue, Conflate and Concurrency).
Status: BETA
See below a small overview what you can do with LookDown:
With Resume the download will restart from where it stopped.
LookDownOverview.mp4
LookDown_Queue.mp4
LookDownConcurrent.mp4
LookDownConflate.mp4
LookDownWMServiceShort2_Part1.mp4
LookDownWMServiceShort2_Part2.mp4
LookDownWMServiceShort2_Part3.mp4
In build.gradle (app)
dependencies {
implementation 'com.3xcool:lookdown:$LATEST_VERSION'
}
fun buildLookDown(context:Context): LookDown {
val builder = LookDown.Builder(context)
return builder.apply {
setChunkSize(4096)
setFileExtension(LDGlobals.LD_VIDEO_MP4_EXT) //you can change file extension for each download call
setDriver(LDGlobals.LD_DEFAULT_DRIVER) //0 = Sandbox (Where the app is installed), 1 = Internal (Phone), 2 = SD Card
setFolder(LDGlobals.LD_DEFAULT_FOLDER)
setForceResume(true) //check if server allow resume
setTimeout(5000)
setConnectTimeout(5000)
setProgressRenderDelay(500L) //very important to avoid to flaky issues in RecyclerView render, probably fixed in Jetpack Compose
setLogTag("LookDown")
activateLogs()
}.build()
}
Class that represents a LookDown file.
data class LDDownload(
var id: String = UUID.randomUUID().toString(),
var url: String? = null,
var filename: String? = null,
var fileExtension: String? = null,
var file: File? = null,
var fileSize: Long? = null,
var downloadedBytes: Long? = null,
var lastModified: String? = null,
var progress: Int = 0,
var state: LDDownloadState? = LDDownloadState.Empty,
var feedback: String? = null,
var title: String? = null,
var workId: UUID? = null,
var params: MutableMap<String, String>? = null,
)
To handle LookDown file progress state.
sealed class LDDownloadState{
object Empty : LDDownloadState()
object Queued : LDDownloadState()
object Downloading : LDDownloadState()
object Paused : LDDownloadState()
object Incomplete : LDDownloadState()
object Downloaded : LDDownloadState()
data class Error(val message: String) : LDDownloadState()
}
Pass LDDownload object or all the necessary parameters to download a file.
lookDown.download(url= url,filename= filename) //necessary parameters
lookDown.download(url= url,filename= filename, fileExtension= extension, resume = true, title="Take A Tour")
val ldDownload = LDDownload(id= i, url = takeatour, filename = "Take a Tour ${i+1}", fileExtension = ".mp4", title = "Filename ${i+1}")
lookDown.download(ldDownload)
Control UI events by updating LDDownload object with:
lookDown.updateLDDownload(ldDownload, forceUpdate = true)
By setting forceUpdate to false, it will update the LiveData only if the elapsed time has passed the "setProgressRenderDelay" value.
Download as Service uses WorkManager + Coroutine to allow the download even when the app is not running.
Set notificationId to null to let LookDown counter handle it
For NotificationImportance use the same as NotificationManager values: MIN = 1 / LOW = 2 / DEFAULT =3 / HIGH = 4
val workId = lookDown.downloadAsService(ldDownload, notificationId, notificationImportance = 4)
Important: downloadAsService returns the WorkManagerId (UUID) in order to observe worker progress. Use lookDown.getWorkInfoByLiveData().
lookDown.getWorkInfoByLiveData(workId).observe(lifecycleOwner){ workInfo ->
//handle workInfo
}
lookDown.cancelDownloadService(workId)
Get WorkInfo list with the current downloads that are running as a service.
lookDown.getCurrentWorks()
LookDown uses Fileman library under the hood:
fun getFile(filename: String, fileExtension: String = this.fileExtension, driver: Int? = this.driver , folder: String? = this.folder): File? {
return Fileman.getFile(context, driver?:this.driver, folder ?:this.folder, filename + fileExtension)
}
fun deleteFile(filename: String, fileExtension: String=this.fileExtension, driver: Int = this.driver , folder: String = this.folder, context: Context?=null): Boolean {
return Fileman.deleteFile(context ?: this.context, driver, folder, filename + fileExtension)
}