Fix page saving
This commit is contained in:
@@ -1,87 +0,0 @@
|
||||
package org.koitharu.kotatsu.utils
|
||||
|
||||
import android.app.DownloadManager
|
||||
import android.app.DownloadManager.Request.*
|
||||
import android.content.BroadcastReceiver
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.content.IntentFilter
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Environment
|
||||
import androidx.core.net.toUri
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.suspendCancellableCoroutine
|
||||
import kotlinx.coroutines.withContext
|
||||
import okhttp3.Cookie
|
||||
import okhttp3.CookieJar
|
||||
import okhttp3.HttpUrl.Companion.toHttpUrl
|
||||
import org.koitharu.kotatsu.R
|
||||
import org.koitharu.kotatsu.core.network.CommonHeaders
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.parsers.util.toFileNameSafe
|
||||
import java.io.File
|
||||
import kotlin.coroutines.resume
|
||||
|
||||
class DownloadManagerHelper(
|
||||
private val context: Context,
|
||||
private val cookieJar: CookieJar,
|
||||
) {
|
||||
|
||||
private val manager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
|
||||
private val subDir = context.getString(R.string.app_name).toFileNameSafe()
|
||||
|
||||
fun downloadPage(page: MangaPage, fullUrl: String): Long {
|
||||
val uri = fullUrl.toUri()
|
||||
val cookies = cookieJar.loadForRequest(fullUrl.toHttpUrl())
|
||||
val dest = subDir + File.separator + uri.lastPathSegment
|
||||
val request = DownloadManager.Request(uri)
|
||||
.addRequestHeader(CommonHeaders.REFERER, page.referer)
|
||||
.addRequestHeader(CommonHeaders.COOKIE, cookieHeader(cookies))
|
||||
.setAllowedOverMetered(true)
|
||||
.setAllowedNetworkTypes(NETWORK_WIFI or NETWORK_MOBILE)
|
||||
.setNotificationVisibility(VISIBILITY_VISIBLE)
|
||||
.setDestinationInExternalPublicDir(Environment.DIRECTORY_PICTURES, dest)
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
|
||||
@Suppress("DEPRECATION")
|
||||
request.allowScanningByMediaScanner()
|
||||
}
|
||||
return manager.enqueue(request)
|
||||
}
|
||||
|
||||
suspend fun awaitDownload(id: Long): Uri {
|
||||
getUriForDownloadedFile(id)?.let { return it } // fast path
|
||||
suspendCancellableCoroutine<Unit> { cont ->
|
||||
val receiver = object : BroadcastReceiver() {
|
||||
override fun onReceive(context: Context, intent: Intent?) {
|
||||
if (
|
||||
intent?.action == DownloadManager.ACTION_DOWNLOAD_COMPLETE &&
|
||||
intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0L) == id
|
||||
) {
|
||||
context.unregisterReceiver(this)
|
||||
cont.resume(Unit)
|
||||
}
|
||||
}
|
||||
}
|
||||
context.registerReceiver(
|
||||
receiver,
|
||||
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE)
|
||||
)
|
||||
cont.invokeOnCancellation {
|
||||
context.unregisterReceiver(receiver)
|
||||
}
|
||||
}
|
||||
return checkNotNull(getUriForDownloadedFile(id))
|
||||
}
|
||||
|
||||
private suspend fun getUriForDownloadedFile(id: Long) = withContext(Dispatchers.IO) {
|
||||
manager.getUriForDownloadedFile(id)
|
||||
}
|
||||
|
||||
private fun cookieHeader(cookies: List<Cookie>): String = buildString {
|
||||
cookies.forEachIndexed { index, cookie ->
|
||||
if (index > 0) append("; ")
|
||||
append(cookie.name).append('=').append(cookie.value)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.koitharu.kotatsu.utils
|
||||
|
||||
import android.content.Context
|
||||
import android.net.Uri
|
||||
import kotlinx.coroutines.Dispatchers
|
||||
import kotlinx.coroutines.runInterruptible
|
||||
import okio.IOException
|
||||
import org.koitharu.kotatsu.parsers.model.MangaPage
|
||||
import org.koitharu.kotatsu.reader.domain.PageLoader
|
||||
|
||||
class ExternalStorageHelper(context: Context) {
|
||||
|
||||
private val contentResolver = context.contentResolver
|
||||
|
||||
suspend fun savePage(page: MangaPage, destination: Uri) {
|
||||
val pageLoader = PageLoader()
|
||||
val pageFile = pageLoader.loadPage(page, force = false)
|
||||
runInterruptible(Dispatchers.IO) {
|
||||
contentResolver.openOutputStream(destination)?.use { output ->
|
||||
pageFile.inputStream().use { input ->
|
||||
input.copyTo(output)
|
||||
}
|
||||
} ?: throw IOException("Output stream is null")
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user