### Start a Download Source: https://github.com/khushpanchal/ketch/blob/master/README.md Call the download() function with the URL, filename, and path. Observe the download status using the returned ID. Ensure appropriate storage permissions are added. ```Kotlin val id = ketch.download(url, fileName, path) lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloadById(id) .flowOn(Dispatchers.IO) .collect { downloadModel -> // use downloadModel } } } ``` -------------------------------- ### ketch.getContentLength() Source: https://context7.com/khushpanchal/ketch/llms.txt A suspend function that makes a lightweight HEAD request to retrieve the `Content-Length` header, returning the remote file size in bytes without starting a full download. ```APIDOC ## `ketch.getContentLength(url, headers)` ### Description Fetches the remote file size by making a HEAD request to the given URL and retrieving the `Content-Length` header. This is useful for determining file size without initiating a full download. ### Parameters - **url** (String) - Required - The URL of the file. - **headers** (Map) - Optional - A map of headers to include in the request. ### Request Example ```kotlin viewModelScope.launch { val bytes = ketch.getContentLength( url = "https://example.com/video.mp4", headers = hashMapOf("Authorization" to "Bearer token123") ) val mb = bytes / 1024.0 / 1024.0 fileSizeText.text = "File size: %.2f MB".format(mb) // Expected output: "File size: 158.34 MB" } ``` ### Response #### Success Response (200) - **bytes** (Long) - The size of the remote file in bytes. ``` -------------------------------- ### Fetch Remote File Size with `ketch.getContentLength()` Source: https://context7.com/khushpanchal/ketch/llms.txt This suspend function performs a HEAD request to get the remote file size in bytes from the `Content-Length` header without initiating a download. It accepts optional headers. ```kotlin viewModelScope.launch { val bytes = ketch.getContentLength( url = "https://example.com/video.mp4", headers = hashMapOf("Authorization" to "Bearer token123") ) val mb = bytes / 1024.0 / 1024.0 fileSizeText.text = "File size: %.2f MB".format(mb) // Expected output: "File size: 158.34 MB" } ``` -------------------------------- ### Initialize Ketch Singleton Instance Source: https://context7.com/khushpanchal/ketch/llms.txt Create and configure the singleton Ketch instance in your Application class. Customize download timeouts, notification settings, OkHttp client, and logging. ```kotlin // MainApplication.kt class MainApplication : Application() { lateinit var ketch: Ketch override fun onCreate() { super.onCreate() ketch = Ketch.builder() .setDownloadConfig( DownloadConfig( connectTimeOutInMs = 20000L, // default: 10000L readTimeOutInMs = 15000L // default: 10000L ) ) .setNotificationConfig( NotificationConfig( enabled = true, channelName = "Downloads", channelDescription = "Shows file download progress", smallIcon = R.drawable.ic_launcher_foreground, // required showSpeed = true, showSize = true, showTime = true ) ) .setOkHttpClient( OkHttpClient.Builder() .connectTimeout(20, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS) .addInterceptor(HttpLoggingInterceptor()) .build() ) .enableLogs(true) .build(this) } } ``` -------------------------------- ### Provide Custom OkHttpClient Source: https://github.com/khushpanchal/ketch/blob/master/README.md Integrate a custom OkHttpClient instance for network requests by passing it during Ketch initialization. ```Kotlin ketch = Ketch.builder().setOkHttpClient( okHttpClient = OkHttpClient .Builder() .connectTimeout(10000L) .readTimeout(10000L) .build() ).build(this) ``` -------------------------------- ### Resume a Download Source: https://github.com/khushpanchal/ketch/blob/master/README.md Use the resume() function with the download ID, tag, or resumeAll() to continue paused downloads. ```Kotlin ketch.resume(downloadModel.id) // other options: resume(tag), resumeAll() ``` -------------------------------- ### Initialize Ketch Singleton Source: https://context7.com/khushpanchal/ketch/llms.txt Initializes the singleton Ketch instance, typically in Application.onCreate(). Allows optional configuration for download timeouts, notifications, OkHttp client, and logging. ```APIDOC ## `Ketch.builder().build(context)` — Initialize the Singleton Creates (or returns) the singleton `Ketch` instance. Must be called once, typically in `Application.onCreate()`. The builder exposes optional configuration for download timeouts, notifications, OkHttp, and logging. ```kotlin // MainApplication.kt class MainApplication : Application() { lateinit var ketch: Ketch override fun onCreate() { super.onCreate() ketch = Ketch.builder() .setDownloadConfig( DownloadConfig( connectTimeOutInMs = 20000L, // default: 10000L readTimeOutInMs = 15000L // default: 10000L ) ) .setNotificationConfig( NotificationConfig( enabled = true, channelName = "Downloads", channelDescription = "Shows file download progress", smallIcon = R.drawable.ic_launcher_foreground, // required showSpeed = true, showSize = true, showTime = true ) ) .setOkHttpClient( OkHttpClient.Builder() .connectTimeout(20, TimeUnit.SECONDS) .readTimeout(15, TimeUnit.SECONDS) .addInterceptor(HttpLoggingInterceptor()) .build() ) .enableLogs(true) .build(this) } } ``` ``` -------------------------------- ### Observe Downloads by Tag Source: https://context7.com/khushpanchal/ketch/llms.txt Observe a list of downloads filtered by a specific tag. Useful for monitoring groups of related downloads, like all videos. ```kotlin viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloadByTag("videos") .flowOn(Dispatchers.IO) .collect { val completed = it.count { it.status == Status.SUCCESS } titleText.text = "Videos: $completed / ${it.size} done" } } } ``` -------------------------------- ### Observe All Downloads Source: https://github.com/khushpanchal/ketch/blob/master/README.md Observe the state flow of all download items from a Fragment. Each item contains detailed download information. ```Kotlin //To observe from Fragment viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloads() .flowOn(Dispatchers.IO) .collect { //set items to adapter } } } ``` -------------------------------- ### Initialize Ketch Instance Source: https://github.com/khushpanchal/ketch/blob/master/README.md Create an instance of Ketch in your application's onCreate method. Ketch is a singleton and will be automatically created on first use. ```Kotlin private lateinit var ketch: Ketch override fun onCreate() { super.onCreate() ketch = Ketch.builder().build(this) } ``` -------------------------------- ### Observe All Downloads as Flow Source: https://context7.com/khushpanchal/ketch/llms.txt Observe all download states and update UI elements like RecyclerView adapters and progress bars. Ensure observation is lifecycle-aware. ```kotlin viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloads() .flowOn(Dispatchers.IO) .collect { downloads: List -> // Bind to RecyclerView adapter adapter.submitList(downloads) // Example: show aggregate progress val inProgress = downloads.filter { it.status == Status.PROGRESS } val avgProgress = inProgress.map { it.progress }.average() progressBar.progress = avgProgress.toInt() } } } ``` -------------------------------- ### Set Custom Download Timeouts Source: https://github.com/khushpanchal/ketch/blob/master/README.md Configure custom connect and read timeouts for downloads using DownloadConfig during Ketch initialization. ```Kotlin ketch = Ketch.builder().setDownloadConfig( config = DownloadConfig( connectTimeOutInMs = 20000L, //Default: 10000L readTimeOutInMs = 15000L //Default: 10000L ) ).build(this) ``` -------------------------------- ### Initialize Ketch with Notification Config Source: https://github.com/khushpanchal/ketch/blob/master/README.md Pass a NotificationConfig during Ketch initialization to enable and customize notifications. A small icon is required. ```Kotlin ketch = Ketch.builder().setNotificationConfig( config = NotificationConfig( enabled = true, smallIcon = R.drawable.ic_launcher_foreground // It is required to pass the smallIcon for notification. ) ).build(this) ``` -------------------------------- ### Observe Downloads by Tag Source: https://context7.com/khushpanchal/ketch/llms.txt Observe a Flow of DownloadModel lists filtered by a specific tag, allowing for grouped monitoring. ```APIDOC ## `ketch.observeDownloadByTag(tag)` — Observe Downloads by Tag Returns a `Flow>` filtered by tag, enabling grouped monitoring of related downloads. ```kotlin viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloadByTag("videos") .flowOn(Dispatchers.IO) .collect { val completed = videoDownloads.count { it.status == Status.SUCCESS } titleText.text = "Videos: $completed / ${videoDownloads.size} done" } } } ``` ``` -------------------------------- ### ketch.getAllDownloads() / ketch.getDownloadModelById() / ketch.getDownloadModelByStatus() / ketch.getDownloadModelByIds() / ketch.getDownloadModelByTags() Source: https://context7.com/khushpanchal/ketch/llms.txt Suspend functions for one-time (non-reactive) queries against the download database. Allows fetching all downloads, a specific download by ID, downloads by status, or batches by IDs or tags. ```APIDOC ## `ketch.getAllDownloads()` ### Description Fetches all download entries currently tracked in the database. ### Response #### Success Response (200) - **all** (List) - A list of all download models. ### Request Example ```kotlin val all: List = ketch.getAllDownloads() println("Total tracked: ${all.size}") ``` ## `ketch.getDownloadModelById(downloadId)` ### Description Fetches a specific download entry by its unique ID. ### Parameters - **downloadId** (Int) - Required - The ID of the download to retrieve. ### Response #### Success Response (200) - **model** (DownloadModel?) - The download model if found, otherwise null. ### Request Example ```kotlin val model: DownloadModel? = ketch.getDownloadModelById(downloadId) println("Status: ${model?.status}, Progress: ${model?.progress}%") ``` ## `ketch.getDownloadModelByStatus(status)` ### Description Fetches all download entries that match the specified status. ### Parameters - **status** (Status) - Required - The status to filter downloads by (e.g., `Status.FAILED`). ### Response #### Success Response (200) - **failed** (List) - A list of download models with the specified status. ### Request Example ```kotlin val failed: List = ketch.getDownloadModelByStatus(Status.FAILED) failed.forEach { println("Failed: ${it.fileName} — ${it.failureReason}") } ``` ## `ketch.getDownloadModelByIds(ids)` ### Description Fetches multiple download entries by a list of their IDs. ### Parameters - **ids** (List) - Required - A list of download IDs to retrieve. ### Response #### Success Response (200) - **batch** (List) - A list of download models corresponding to the provided IDs. May contain nulls if an ID is not found. ### Request Example ```kotlin val batch: List = ketch.getDownloadModelByIds(listOf(1, 2, 3)) ``` ## `ketch.getDownloadModelByTags(tags)` ### Description Fetches all download entries that are associated with any of the provided tags. ### Parameters - **tags** (List) - Required - A list of tags to filter downloads by. ### Response #### Success Response (200) - **tagged** (List) - A list of download models matching any of the specified tags. ### Request Example ```kotlin val tagged: List = ketch.getDownloadModelByTags(listOf("videos", "documents")) ``` ``` -------------------------------- ### Observe All Downloads Source: https://context7.com/khushpanchal/ketch/llms.txt Observe all downloads as a Flow, emitting updated lists whenever any download state changes. Each DownloadModel contains full metadata. ```APIDOC ## `ketch.observeDownloads()` — Observe All Downloads as Flow Returns a `Flow>` that emits updated lists whenever any download state changes. Each `DownloadModel` carries full metadata: URL, path, file name, tag, ID, status, progress (0–100), speed in bytes/ms, total size in bytes, ETag, metadata, and failure reason. ```kotlin // In a Fragment — lifecycle-aware observation viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloads() .flowOn(Dispatchers.IO) .collect { downloads: List -> // Bind to RecyclerView adapter adapter.submitList(downloads) // Example: show aggregate progress val inProgress = downloads.filter { it.status == Status.PROGRESS } val avgProgress = inProgress.map { it.progress }.average() progressBar.progress = avgProgress.toInt() } } } ``` ``` -------------------------------- ### Query Download Database with Ketch Source: https://context7.com/khushpanchal/ketch/llms.txt Use suspend functions like `getAllDownloads`, `getDownloadModelById`, `getDownloadModelByStatus`, `getDownloadModelByIds`, and `getDownloadModelByTags` for one-time queries against the download database. ```kotlin viewModelScope.launch { // Fetch all downloads once val all: List = ketch.getAllDownloads() println("Total tracked: ${all.size}") // Fetch by ID val model: DownloadModel? = ketch.getDownloadModelById(downloadId) println("Status: ${model?.status}, Progress: ${model?.progress}%") // Fetch all with FAILED status val failed: List = ketch.getDownloadModelByStatus(Status.FAILED) failed.forEach { println("Failed: ${it.fileName} — ${it.failureReason}") } // Fetch by multiple IDs val batch: List = ketch.getDownloadModelByIds(listOf(1, 2, 3)) // Fetch by multiple tags val tagged: List = ketch.getDownloadModelByTags(listOf("videos", "documents")) } ``` -------------------------------- ### Tag Downloads for Grouping Source: https://github.com/khushpanchal/ketch/blob/master/README.md Assign a tag to downloads to group them, allowing for easier cancellation, pausing, resuming, and deletion. ```Kotlin ketch.download(url, fileName, path, tag = tag, //Default: null ) ``` -------------------------------- ### Observe Downloads by Status Source: https://context7.com/khushpanchal/ketch/llms.txt Observe downloads filtered by their current status (e.g., FAILED). This is useful for displaying counts or enabling retry buttons for specific states. ```kotlin // Monitor all currently failing downloads viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloadsByStatus(Status.FAILED) .flowOn(Dispatchers.IO) .collect { retryAllButton.isVisible = it.isNotEmpty() failedCount.text = "${it.size} failed" } } } ``` -------------------------------- ### Resume Downloads Source: https://context7.com/khushpanchal/ketch/llms.txt Resume paused downloads by ID, tag, or all paused downloads. Ketch attempts to use the Range header to continue from the last downloaded byte. ```kotlin // Resume by ID ketch.resume(downloadId) // Resume by tag ketch.resume("videos") // Resume all paused downloads ketch.resumeAll() ``` -------------------------------- ### Add Jitpack Repository to settings.gradle Source: https://github.com/khushpanchal/ketch/blob/master/README.md Include the Jitpack repository in your project's settings.gradle file to resolve Ketch dependencies. ```Groovy dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() maven { url 'https://jitpack.io' } // this one } } ``` -------------------------------- ### Retry a Download Source: https://github.com/khushpanchal/ketch/blob/master/README.md Use the retry() function with the download ID, tag, or retryAll() to re-initiate failed downloads. ```Kotlin ketch.retry(downloadModel.id) // other options: retry(tag), retryAll() ``` -------------------------------- ### Enqueue a File Download Source: https://context7.com/khushpanchal/ketch/llms.txt Queue a file download asynchronously using the Ketch instance. Supports optional headers, tags, metadata, and pause/resume functionality. Returns a unique download ID. ```kotlin // Download a video file val videoId = ketch.download( url = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).path, fileName = "BigBuckBunny.mp4", tag = "videos", // optional: group downloads for bulk operations metaData = "my-extra-info", // optional: any string payload headers = hashMapOf("Authorization" to "Bearer token123"), // optional supportPauseResume = true // default: true ) // Download a PDF val pdfId = ketch.download( url = "https://example.com/report.pdf", path = requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)!!.path, fileName = "report.pdf", tag = "documents" ) // Enqueue multiple downloads in parallel listOf( Triple("https://example.com/a.mp4", "a.mp4", "batch"), Triple("https://example.com/b.mp4", "b.mp4", "batch"), Triple("https://example.com/c.jpg", "c.jpg", "batch"), ).forEach { (url, name, tag) -> ketch.download(url = url, path = downloadsPath, fileName = name, tag = tag) } ``` -------------------------------- ### Add Ketch Dependency to build.gradle Source: https://context7.com/khushpanchal/ketch/llms.txt Include the Ketch library in your module's build.gradle file. Ensure JitPack is added to your settings.gradle. ```groovy // settings.gradle dependencyResolutionManagement { repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS) repositories { google() mavenCentral() maven { url 'https://jitpack.io' } } } // app/build.gradle dependencies { implementation 'com.github.khushpanchal:Ketch:2.0.6' } ``` -------------------------------- ### Pause a Download Source: https://github.com/khushpanchal/ketch/blob/master/README.md Use the pause() function with the download ID, tag, or pauseAll() to temporarily halt downloads. ```Kotlin ketch.pause(downloadModel.id) // other options: pause(tag), pauseAll() ``` -------------------------------- ### Remove Downloads from Database with Ketch Source: https://context7.com/khushpanchal/ketch/llms.txt Use `clearDb` to remove download entries and optionally their files. `clearAllDb` wipes the entire database. Specify download ID, tag, or timestamp for targeted removal. ```kotlin // Remove a single entry and its file ketch.clearDb(downloadId) ``` ```kotlin // Remove entry but keep the file on disk ketch.clearDb(downloadId, deleteFile = false) ``` ```kotlin // Remove all entries for a tag ketch.clearDb("videos") ``` ```kotlin // Remove all entries older than 7 days val sevenDaysAgo = System.currentTimeMillis() - (7 * 24 * 60 * 60 * 1000L) ketch.clearDb(sevenDaysAgo) ``` ```kotlin // Wipe everything ketch.clearAllDb() ``` -------------------------------- ### Observe Single Download by ID Source: https://context7.com/khushpanchal/ketch/llms.txt Observe the state of a specific download using its ID. The flow emits null if the download entry is removed. Useful for updating UI for a single item. ```kotlin val downloadId = ketch.download( url = "https://example.com/video.mp4", path = downloadsPath, fileName = "video.mp4" ) viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloadById(downloadId) .flowOn(Dispatchers.IO) .collect { model: DownloadModel? -> if (model == null) return@collect when (model.status) { Status.PROGRESS -> { progressBar.progress = model.progress speedText.text = "${model.speedInBytePerMs * 1000} B/s" sizeText.text = "${model.total / 1024 / 1024} MB" } Status.SUCCESS -> showOpenButton(model.path, model.fileName) Status.FAILED -> showRetryButton(model.failureReason) Status.PAUSED -> showResumeButton() else -> {} } } } } ``` -------------------------------- ### Enqueue a Download Synchronously (Coroutine) Source: https://context7.com/khushpanchal/ketch/llms.txt Use the suspend variant of `download()` for enqueuing downloads within coroutines. A mutex prevents race conditions, and the download ID is returned immediately after database entry. ```kotlin viewModelScope.launch { val id = ketch.downloadSync( url = "https://example.com/large-dataset.zip", path = context.filesDir.path, fileName = "dataset.zip", tag = "sync-downloads" ) // id is valid immediately; download proceeds in background println("Enqueued with ID: $id") } ``` -------------------------------- ### Clear Download Database Entry Source: https://github.com/khushpanchal/ketch/blob/master/README.md Use clearDb() to remove download entries from the database. Pass 'false' to skip actual file deletion. ```Kotlin ketch.clearDb(downloadModel.id) // other options: clearDb(tag), clearAllDb(), clearDb(timeInMillis) ``` ```Kotlin ketch.clearDb(downloadModel.id, false) // Pass "false" to skip the actual file deletion (only clear entry from DB) ``` -------------------------------- ### Status Enum and UI Mapping Source: https://context7.com/khushpanchal/ketch/llms.txt Defines the lifecycle states for downloads and provides a function to map these statuses to UI colors. ```kotlin enum class Status { QUEUED, STARTED, PROGRESS, SUCCESS, PAUSED, CANCELLED, FAILED, DEFAULT } ``` ```kotlin fun statusColor(status: Status): Int = when (status) { Status.SUCCESS -> Color.GREEN Status.FAILED -> Color.RED Status.PAUSED -> Color.YELLOW Status.CANCELLED -> Color.GRAY Status.PROGRESS, Status.STARTED, Status.QUEUED -> Color.BLUE Status.DEFAULT -> Color.LTGRAY } ``` -------------------------------- ### Logger Interface Source: https://context7.com/khushpanchal/ketch/llms.txt Implement the `Logger` interface to redirect Ketch's internal logs to your own logging framework. ```APIDOC ## `Logger` Interface ### Description Implement this interface to customize how Ketch logs messages. This allows you to integrate Ketch's logging with your preferred logging framework (e.g., Timber, Firebase Crashlytics). ### Methods - **`log(tag: String?, msg: String?, tr: Throwable?, type: LogType)`**: This method is called by Ketch for each log event. You should handle the logging based on the provided `tag`, `msg`, `tr` (throwable), and `type`. ### `LogType` Enum Represents the severity of the log message: - `VERBOSE` - `DEBUG` - `INFO` - `WARN` - `ERROR` ### Request Example (Implementing with Timber) ```kotlin class TimberKetchLogger : Logger { override fun log(tag: String?, msg: String?, tr: Throwable?, type: LogType) { val fullMsg = "[$tag] $msg" when (type) { LogType.VERBOSE -> Timber.v(tr, fullMsg) LogType.DEBUG -> Timber.d(tr, fullMsg) LogType.INFO -> Timber.i(tr, fullMsg) LogType.WARN -> Timber.w(tr, fullMsg) LogType.ERROR -> Timber.e(tr, fullMsg) } } } // Register at build time ketch = Ketch.builder() .setLogger(TimberKetchLogger()) .build(this) ``` ``` -------------------------------- ### Observe Downloads by Status Source: https://context7.com/khushpanchal/ketch/llms.txt Observe a Flow of DownloadModel lists filtered by a specific Status enum value. ```APIDOC ## `ketch.observeDownloadsByStatus(status)` — Observe Downloads by Status Returns a `Flow>` filtered by a specific `Status` enum value. ```kotlin // Monitor all currently failing downloads viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloadsByStatus(Status.FAILED) .flowOn(Dispatchers.IO) .collect { retryAllButton.isVisible = failed.isNotEmpty() failedCount.text = "${failed.size} failed" } } } ``` ``` -------------------------------- ### Implement Custom Logging with `Logger` Interface Source: https://context7.com/khushpanchal/ketch/llms.txt Implement the `Logger` interface to redirect Ketch's internal logs to your preferred logging framework. Register your custom logger using the `Ketch.builder()`. ```kotlin class TimberKetchLogger : Logger { override fun log(tag: String?, msg: String?, tr: Throwable?, type: LogType) { val fullMsg = "[$tag] $msg" when (type) { LogType.VERBOSE -> Timber.v(tr, fullMsg) LogType.DEBUG -> Timber.d(tr, fullMsg) LogType.INFO -> Timber.i(tr, fullMsg) LogType.WARN -> Timber.w(tr, fullMsg) LogType.ERROR -> Timber.e(tr, fullMsg) } } } // Register at build time ketch = Ketch.builder() .setLogger(TimberKetchLogger()) .build(this) ``` -------------------------------- ### Cancel a Download Source: https://github.com/khushpanchal/ketch/blob/master/README.md Use the cancel() function with the download ID, tag, or cancelAll() to stop ongoing downloads. ```Kotlin ketch.cancel(downloadModel.id) // other options: cancel(tag), cancelAll() ``` -------------------------------- ### Add Headers to Network Request Source: https://github.com/khushpanchal/ketch/blob/master/README.md Provide custom headers for the network request by passing a headers map to the download function. ```Kotlin ketch.download(url, fileName, path, headers = headers, //Default: Empty hashmap ) ``` -------------------------------- ### Enqueue a Download Synchronously (Coroutine) Source: https://context7.com/khushpanchal/ketch/llms.txt Suspend variant of `download()`. Uses a mutex to prevent race conditions when enqueuing from multiple coroutines concurrently. Returns the download ID once the entry is safely written to the database. ```APIDOC ## `ketch.downloadSync()` — Enqueue a Download Synchronously (Coroutine) Suspend variant of `download()`. Uses a mutex to prevent race conditions when enqueuing from multiple coroutines concurrently. Returns the download ID once the entry is safely written to the database. ```kotlin viewModelScope.launch { val id = ketch.downloadSync( url = "https://example.com/large-dataset.zip", path = context.filesDir.path, fileName = "dataset.zip", tag = "sync-downloads" ) // id is valid immediately; download proceeds in background println("Enqueued with ID: $id") } ``` ``` -------------------------------- ### Retry Failed Downloads Source: https://context7.com/khushpanchal/ketch/llms.txt Retry downloads that are in a FAILED or CANCELLED state. The download restarts from the beginning. ```kotlin // Retry a specific download ketch.retry(downloadId) // Retry all failed downloads in a group ketch.retry("documents") // Retry all failed/cancelled downloads ketch.retryAll() ``` -------------------------------- ### Resume Downloads Source: https://context7.com/khushpanchal/ketch/llms.txt Resume paused downloads by ID, tag, or all paused downloads. Uses the Range header to continue from the last downloaded byte offset if supported by the server. ```APIDOC ## `ketch.resume()` / `ketch.resumeAll()` — Resume Downloads Resumes a paused download. Ketch sends a `Range` header to continue from the last downloaded byte offset (if the server supports it). ```kotlin // Resume by ID ketch.resume(downloadId) // Resume by tag ketch.resume("videos") // Resume all paused downloads ketch.resumeAll() ``` ``` -------------------------------- ### Observe Single Download by ID Source: https://context7.com/khushpanchal/ketch/llms.txt Observe a single download by its ID. Returns a Flow that emits the DownloadModel or null if the entry is removed. ```APIDOC ## `ketch.observeDownloadById(id)` — Observe a Single Download Returns a `Flow` scoped to a single download ID. Emits `null` if the entry is removed from the database. ```kotlin val downloadId = ketch.download( url = "https://example.com/video.mp4", path = downloadsPath, fileName = "video.mp4" ) viewLifecycleOwner.lifecycleScope.launch { repeatOnLifecycle(Lifecycle.State.STARTED) { ketch.observeDownloadById(downloadId) .flowOn(Dispatchers.IO) .collect { model: DownloadModel? -> if (model == null) return@collect when (model.status) { Status.PROGRESS -> { progressBar.progress = model.progress speedText.text = "${model.speedInBytePerMs * 1000} B/s" sizeText.text = "${model.total / 1024 / 1024} MB" } Status.SUCCESS -> showOpenButton(model.path, model.fileName) Status.FAILED -> showRetryButton(model.failureReason) Status.PAUSED -> showResumeButton() else -> {} } } } } ``` ``` -------------------------------- ### ketch.clearDb() / ketch.clearAllDb() Source: https://context7.com/khushpanchal/ketch/llms.txt Removes download entries from the Room database. Optionally deletes the actual file from storage. Can target by ID, tag, timestamp threshold, or all records. ```APIDOC ## `ketch.clearDb(downloadId)` / `ketch.clearDb(downloadId, deleteFile)` ### Description Removes a single download entry from the Room database. The `deleteFile` parameter (defaulting to `true`) determines if the actual file on storage is also deleted. ### Parameters - **downloadId** (String or Int) - Required - The ID of the download entry to remove. - **deleteFile** (Boolean) - Optional - If `true`, deletes the file from storage. Defaults to `true`. ### Request Example ```kotlin // Remove a single entry and its file ketch.clearDb(downloadId) // Remove entry but keep the file on disk ketch.clearDb(downloadId, deleteFile = false) ``` ## `ketch.clearDb(tag)` ### Description Removes all download entries associated with a specific tag. ### Parameters - **tag** (String) - Required - The tag to filter downloads by. ### Request Example ```kotlin // Remove all entries for a tag ketch.clearDb("videos") ``` ## `ketch.clearDb(timestampThreshold)` ### Description Removes all download entries that were added before the specified timestamp. ### Parameters - **timestampThreshold** (Long) - Required - The timestamp in milliseconds. Entries older than this will be removed. ### Request Example ```kotlin val sevenDaysAgo = System.currentTimeMillis() - (7 * 24 * 60 * 60 * 1000L) ketch.clearDb(sevenDaysAgo) ``` ## `ketch.clearAllDb()` ### Description Removes all download entries and their associated files from the database and storage. ### Request Example ```kotlin // Wipe everything ketch.clearAllDb() ``` ``` -------------------------------- ### Enqueue a File Download Source: https://context7.com/khushpanchal/ketch/llms.txt Queues a file download asynchronously. Returns a unique integer ID for the download. Supports optional headers, tags, metadata, and pause/resume functionality. ```APIDOC ## `ketch.download()` — Enqueue a File Download Queues a file download asynchronously and immediately returns a unique integer ID derived from the combination of URL, path, and file name. Supports optional headers, tags, metadata, and pause/resume capability. ```kotlin // Download a video file val videoId = ketch.download( url = "https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4", path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).path, fileName = "BigBuckBunny.mp4", tag = "videos", // optional: group downloads for bulk operations metaData = "my-extra-info", // optional: any string payload headers = hashMapOf("Authorization" to "Bearer token123"), // optional supportPauseResume = true // default: true ) // Download a PDF val pdfId = ketch.download( url = "https://example.com/report.pdf", path = requireContext().getExternalFilesDir(Environment.DIRECTORY_DOCUMENTS)!!.path, fileName = "report.pdf", tag = "documents" ) // Enqueue multiple downloads in parallel listOf( Triple("https://example.com/a.mp4", "a.mp4", "batch"), Triple("https://example.com/b.mp4", "b.mp4", "batch"), Triple("https://example.com/c.jpg", "c.jpg", "batch"), ).forEach { (url, name, tag) -> ketch.download(url = url, path = downloadsPath, fileName = name, tag = tag) } ``` ``` -------------------------------- ### DownloadModel Data Class Source: https://context7.com/khushpanchal/ketch/llms.txt Represents the state of a download. All fields are read-only. Used to display download progress and information. ```kotlin data class DownloadModel( val url: String, val path: String, val fileName: String, val tag: String, val id: Int, val headers: HashMap, val timeQueued: Long, val status: Status, val total: Long, val progress: Int, val speedInBytePerMs: Float, val lastModified: Long, val eTag: String, val metaData: String, val failureReason: String ) ``` ```kotlin fun bind(model: DownloadModel) { fileNameView.text = model.fileName statusView.text = model.status.name progressBar.progress = model.progress val speedKbps = model.speedInBytePerMs * 1000 / 1024 speedView.text = "%.1f KB/s".format(speedKbps) val totalMb = model.total / 1024.0 / 1024.0 sizeView.text = "%.2f MB".format(totalMb) } ``` -------------------------------- ### Validate Content with `ketch.isContentValid()` Source: https://context7.com/khushpanchal/ketch/llms.txt This suspend function checks if a downloaded file is current by comparing its stored ETag with the server's ETag. Use this for cache invalidation before re-downloading. ```kotlin viewModelScope.launch { val storedETag = prefs.getString("video_etag", "") ?: "" val isValid = ketch.isContentValid( url = "https://example.com/video.mp4", headers = hashMapOf("Authorization" to "Bearer token123"), eTag = storedETag ) if (!isValid) { // Re-download the file since content changed on server ketch.download( url = "https://example.com/video.mp4", path = downloadsPath, fileName = "video.mp4" ) } } ``` -------------------------------- ### Add Ketch Dependency to build.gradle Source: https://github.com/khushpanchal/ketch/blob/master/README.md Add the Ketch library dependency to your module-level build.gradle file. Ensure you use the latest available version. ```Groovy dependencies { implementation 'com.github.khushpanchal:Ketch:2.0.6' // Use latest available version } ``` -------------------------------- ### Retry Failed Downloads Source: https://context7.com/khushpanchal/ketch/llms.txt Retry downloads that are in a FAILED or CANCELLED state. The download restarts from scratch. ```APIDOC ## `ketch.retry()` / `ketch.retryAll()` — Retry Failed Downloads Re-enqueues a download that is in `FAILED` or `CANCELLED` state, restarting from scratch. ```kotlin // Retry a specific download ketch.retry(downloadId) // Retry all failed downloads in a group ketch.retry("documents") // Retry all failed/cancelled downloads ketch.retryAll() ``` ``` -------------------------------- ### Configure Custom Notification Settings Source: https://github.com/khushpanchal/ketch/blob/master/README.md Customize notification appearance and behavior, including channel name, importance, icons, and display of speed/size/time, via NotificationConfig. ```Kotlin ketch = Ketch.builder().setNotificationConfig( config = NotificationConfig( enabled = true, //Default: false channelName = channelName, //Default: "File Download" channelDescription = channelDescription, //Default: "Notify file download status" importance = importance, //Default: NotificationManager.IMPORTANCE_HIGH smallIcon = smallIcon, //It is required showSpeed = true, //Default: true showSize = true, //Default: true showTime = true //Default: true ) ).build(this) ``` -------------------------------- ### Cancel Downloads Source: https://context7.com/khushpanchal/ketch/llms.txt Cancel downloads by ID, tag, or all downloads. This action deletes the partial file and updates the database status to CANCELLED. ```kotlin // Cancel by ID ketch.cancel(downloadId) // Cancel all downloads in a category ketch.cancel("batch") // Cancel everything ketch.cancelAll() ``` -------------------------------- ### Pause Downloads Source: https://context7.com/khushpanchal/ketch/llms.txt Pause downloads by ID, tag, or all active downloads. Paused downloads preserve partial data and can be resumed later. ```kotlin // Pause a specific download ketch.pause(downloadId) // Pause all downloads tagged "videos" ketch.pause("videos") // Pause every active download ketch.pauseAll() ``` -------------------------------- ### ketch.isContentValid() Source: https://context7.com/khushpanchal/ketch/llms.txt A suspend function that checks whether a previously downloaded file is still current by comparing its stored ETag against the server's current ETag. Useful for cache invalidation. ```APIDOC ## `ketch.isContentValid(url, headers, eTag)` ### Description Validates if the content at the given URL is still valid by comparing its ETag with the one provided. This is useful for cache invalidation to avoid re-downloading unchanged files. ### Parameters - **url** (String) - Required - The URL of the content. - **headers** (Map) - Optional - A map of headers to include in the request. - **eTag** (String) - Required - The stored ETag of the previously downloaded content. ### Request Example ```kotlin viewModelScope.launch { val storedETag = prefs.getString("video_etag", "") ?: "" val isValid = ketch.isContentValid( url = "https://example.com/video.mp4", headers = hashMapOf("Authorization" to "Bearer token123"), eTag = storedETag ) if (!isValid) { // Re-download the file since content changed on server ketch.download( url = "https://example.com/video.mp4", path = downloadsPath, fileName = "video.mp4" ) } } ``` ### Response #### Success Response (200) - **isValid** (Boolean) - `true` if the content is valid (ETags match), `false` otherwise. ``` -------------------------------- ### Pause Downloads Source: https://context7.com/khushpanchal/ketch/llms.txt Pause downloads by ID, tag, or all active downloads. Partially downloaded bytes are preserved. ```APIDOC ## `ketch.pause()` / `ketch.pauseAll()` — Pause Downloads Pauses a download by ID, by tag, or all active downloads. The partially downloaded bytes are preserved; the download resumes from the byte offset when resumed. ```kotlin // Pause a specific download ketch.pause(downloadId) // Pause all downloads tagged "videos" ketch.pause("videos") // Pause every active download ketch.pauseAll() ``` ``` -------------------------------- ### Cancel Downloads Source: https://context7.com/khushpanchal/ketch/llms.txt Cancel downloads by ID, tag, or all active downloads. The partial file is deleted, and the database entry status is updated to CANCELLED. ```APIDOC ## `ketch.cancel()` / `ketch.cancelAll()` — Cancel Downloads Cancels a download and deletes the partial file from disk. The database entry status is updated to `CANCELLED`. ```kotlin // Cancel by ID ketch.cancel(downloadId) // Cancel all downloads in a category ketch.cancel("batch") // Cancel everything ketch.cancelAll() ``` ``` -------------------------------- ### Add Notification Permission Source: https://github.com/khushpanchal/ketch/blob/master/README.md Add the POST_NOTIFICATIONS permission in the manifest for Android 13+ and request it from the user. ```XML ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.