download episode images
This commit is contained in:
parent
3ff492d94c
commit
7dbf951d5a
4 changed files with 56 additions and 34 deletions
|
@ -29,6 +29,7 @@ import androidx.fragment.app.FragmentManager
|
||||||
import androidx.lifecycle.Lifecycle
|
import androidx.lifecycle.Lifecycle
|
||||||
import androidx.lifecycle.lifecycleScope
|
import androidx.lifecycle.lifecycleScope
|
||||||
import androidx.media3.common.util.UnstableApi
|
import androidx.media3.common.util.UnstableApi
|
||||||
|
import androidx.media3.exoplayer.offline.Download
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import ani.dantotsu.connections.anilist.Anilist
|
import ani.dantotsu.connections.anilist.Anilist
|
||||||
import ani.dantotsu.connections.anilist.AnilistHomeViewModel
|
import ani.dantotsu.connections.anilist.AnilistHomeViewModel
|
||||||
|
@ -249,15 +250,19 @@ class MainActivity : AppCompatActivity() {
|
||||||
|
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
val index = Helper.downloadManager(this@MainActivity).downloadIndex
|
val index = Helper.downloadManager(this@MainActivity).downloadIndex
|
||||||
if (index != null) {
|
|
||||||
val downloadCursor = index.getDownloads()
|
val downloadCursor = index.getDownloads()
|
||||||
if (downloadCursor != null) {
|
|
||||||
while (downloadCursor.moveToNext()) {
|
while (downloadCursor.moveToNext()) {
|
||||||
val download = downloadCursor.download
|
val download = downloadCursor.download
|
||||||
Log.e("Downloader", download.request.uri.toString())
|
Log.e("Downloader", download.request.uri.toString())
|
||||||
Log.e("Downloader", download.request.id.toString())
|
Log.e("Downloader", download.request.id.toString())
|
||||||
Log.e("Downloader", download.request.mimeType.toString())
|
Log.e("Downloader", download.request.mimeType.toString())
|
||||||
}
|
Log.e("Downloader", download.request.data.size.toString())
|
||||||
|
Log.e("Downloader", download.bytesDownloaded.toString())
|
||||||
|
Log.e("Downloader", download.state.toString())
|
||||||
|
Log.e("Downloader", download.failureReason.toString())
|
||||||
|
|
||||||
|
if (download.state == Download.STATE_FAILED) { //simple cleanup
|
||||||
|
Helper.downloadManager(this@MainActivity).removeDownload(download.request.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,6 +20,7 @@ import androidx.media3.common.util.UnstableApi
|
||||||
import androidx.media3.exoplayer.offline.Download
|
import androidx.media3.exoplayer.offline.Download
|
||||||
import androidx.media3.exoplayer.offline.DownloadManager
|
import androidx.media3.exoplayer.offline.DownloadManager
|
||||||
import androidx.media3.exoplayer.offline.DownloadService
|
import androidx.media3.exoplayer.offline.DownloadService
|
||||||
|
import ani.dantotsu.FileUrl
|
||||||
import ani.dantotsu.R
|
import ani.dantotsu.R
|
||||||
import ani.dantotsu.currActivity
|
import ani.dantotsu.currActivity
|
||||||
import ani.dantotsu.download.DownloadedType
|
import ani.dantotsu.download.DownloadedType
|
||||||
|
@ -84,7 +85,6 @@ class AnimeDownloaderService : Service() {
|
||||||
setSmallIcon(R.drawable.ic_round_download_24)
|
setSmallIcon(R.drawable.ic_round_download_24)
|
||||||
priority = NotificationCompat.PRIORITY_DEFAULT
|
priority = NotificationCompat.PRIORITY_DEFAULT
|
||||||
setOnlyAlertOnce(true)
|
setOnlyAlertOnce(true)
|
||||||
setProgress(0, 0, false)
|
|
||||||
}
|
}
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
||||||
startForeground(
|
startForeground(
|
||||||
|
@ -216,43 +216,39 @@ class AnimeDownloaderService : Service() {
|
||||||
}
|
}
|
||||||
|
|
||||||
saveMediaInfo(task)
|
saveMediaInfo(task)
|
||||||
var continueDownload = false
|
val downloadStarted = hasDownloadStarted(downloadManager, task, 30000) // 30 seconds timeout
|
||||||
downloadManager.addListener(
|
|
||||||
object : androidx.media3.exoplayer.offline.DownloadManager.Listener {
|
|
||||||
override fun onDownloadChanged(
|
|
||||||
downloadManager: DownloadManager,
|
|
||||||
download: Download,
|
|
||||||
finalException: Exception?
|
|
||||||
) {
|
|
||||||
continueDownload = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
//set an async timeout of 30 seconds before setting continueDownload to true
|
if (!downloadStarted) {
|
||||||
launch {
|
logger("Download failed to start")
|
||||||
kotlinx.coroutines.delay(30000)
|
builder.setContentText("${task.title} - ${task.episode} Download failed to start")
|
||||||
continueDownload = true
|
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
||||||
|
snackString("${task.title} - ${task.episode} Download failed to start")
|
||||||
|
broadcastDownloadFailed(task.getTaskName())
|
||||||
|
return@withContext
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// periodically check if the download is complete
|
// periodically check if the download is complete
|
||||||
while (downloadManager.downloadIndex.getDownload(task.video.file.url) != null || continueDownload == false) {
|
while (downloadManager.downloadIndex.getDownload(task.video.file.url) != null) {
|
||||||
val download = downloadManager.downloadIndex.getDownload(task.video.file.url)
|
val download = downloadManager.downloadIndex.getDownload(task.video.file.url)
|
||||||
if (download != null) {
|
if (download != null) {
|
||||||
if (download.state == androidx.media3.exoplayer.offline.Download.STATE_FAILED) {
|
if (download.state == androidx.media3.exoplayer.offline.Download.STATE_FAILED) {
|
||||||
logger("Download failed")
|
logger("Download failed")
|
||||||
builder.setContentText("${task.title} - ${task.episode} Download failed")
|
builder.setContentText("${task.title} - ${task.episode} Download failed")
|
||||||
.setProgress(0, 0, false)
|
|
||||||
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
||||||
snackString("${task.title} - ${task.episode} Download failed")
|
snackString("${task.title} - ${task.episode} Download failed")
|
||||||
|
logger("Download failed: ${download.failureReason}")
|
||||||
|
FirebaseCrashlytics.getInstance().recordException(Exception("Anime Download failed:" +
|
||||||
|
" ${download.failureReason}" +
|
||||||
|
" url: ${task.video.file.url}" +
|
||||||
|
" title: ${task.title}" +
|
||||||
|
" episode: ${task.episode}"))
|
||||||
broadcastDownloadFailed(task.getTaskName())
|
broadcastDownloadFailed(task.getTaskName())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if (download.state == androidx.media3.exoplayer.offline.Download.STATE_COMPLETED) {
|
if (download.state == androidx.media3.exoplayer.offline.Download.STATE_COMPLETED) {
|
||||||
logger("Download completed")
|
logger("Download completed")
|
||||||
builder.setContentText("${task.title} - ${task.episode} Download completed")
|
builder.setContentText("${task.title} - ${task.episode} Download completed")
|
||||||
.setProgress(0, 0, false)
|
|
||||||
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
||||||
snackString("${task.title} - ${task.episode} Download completed")
|
snackString("${task.title} - ${task.episode} Download completed")
|
||||||
getSharedPreferences(getString(R.string.anime_downloads), Context.MODE_PRIVATE).edit().putString(
|
getSharedPreferences(getString(R.string.anime_downloads), Context.MODE_PRIVATE).edit().putString(
|
||||||
|
@ -272,13 +268,11 @@ class AnimeDownloaderService : Service() {
|
||||||
if (download.state == androidx.media3.exoplayer.offline.Download.STATE_STOPPED) {
|
if (download.state == androidx.media3.exoplayer.offline.Download.STATE_STOPPED) {
|
||||||
logger("Download stopped")
|
logger("Download stopped")
|
||||||
builder.setContentText("${task.title} - ${task.episode} Download stopped")
|
builder.setContentText("${task.title} - ${task.episode} Download stopped")
|
||||||
.setProgress(0, 0, false)
|
|
||||||
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
||||||
snackString("${task.title} - ${task.episode} Download stopped")
|
snackString("${task.title} - ${task.episode} Download stopped")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
broadcastDownloadProgress(task.getTaskName(), download.percentDownloaded.toInt())
|
broadcastDownloadProgress(task.getTaskName(), download.percentDownloaded.toInt())
|
||||||
builder.setProgress(100, download.percentDownloaded.toInt(), false)
|
|
||||||
if (notifi) {
|
if (notifi) {
|
||||||
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
notificationManager.notify(NOTIFICATION_ID, builder.build())
|
||||||
}
|
}
|
||||||
|
@ -294,6 +288,19 @@ class AnimeDownloaderService : Service() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@androidx.annotation.OptIn(UnstableApi::class) suspend fun hasDownloadStarted(downloadManager: DownloadManager, task: DownloadTask, timeout: Long): Boolean {
|
||||||
|
val startTime = System.currentTimeMillis()
|
||||||
|
while (System.currentTimeMillis() - startTime < timeout) {
|
||||||
|
val download = downloadManager.downloadIndex.getDownload(task.video.file.url)
|
||||||
|
if (download != null) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
// Delay between each poll
|
||||||
|
kotlinx.coroutines.delay(500)
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
@OptIn(DelicateCoroutinesApi::class)
|
@OptIn(DelicateCoroutinesApi::class)
|
||||||
private fun saveMediaInfo(task: DownloadTask) {
|
private fun saveMediaInfo(task: DownloadTask) {
|
||||||
GlobalScope.launch(Dispatchers.IO) {
|
GlobalScope.launch(Dispatchers.IO) {
|
||||||
|
@ -323,6 +330,13 @@ class AnimeDownloaderService : Service() {
|
||||||
media.cover = media.cover?.let { downloadImage(it, directory, "cover.jpg") }
|
media.cover = media.cover?.let { downloadImage(it, directory, "cover.jpg") }
|
||||||
media.banner = media.banner?.let { downloadImage(it, directory, "banner.jpg") }
|
media.banner = media.banner?.let { downloadImage(it, directory, "banner.jpg") }
|
||||||
if (task.episodeImage != null) {
|
if (task.episodeImage != null) {
|
||||||
|
media.anime?.episodes?.get(task.episode)?.let { episode ->
|
||||||
|
episode.thumb = downloadImage(task.episodeImage, episodeDirectory, "episodeImage.jpg")?.let {
|
||||||
|
FileUrl(
|
||||||
|
it
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
downloadImage(task.episodeImage, episodeDirectory, "episodeImage.jpg")
|
downloadImage(task.episodeImage, episodeDirectory, "episodeImage.jpg")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -219,7 +219,8 @@ object Helper {
|
||||||
episode: String,
|
episode: String,
|
||||||
video: Video,
|
video: Video,
|
||||||
subtitle: Subtitle? = null,
|
subtitle: Subtitle? = null,
|
||||||
sourceMedia: Media? = null
|
sourceMedia: Media? = null,
|
||||||
|
episodeImage: String? = null
|
||||||
) {
|
) {
|
||||||
if (!isNotificationPermissionGranted(context)) {
|
if (!isNotificationPermissionGranted(context)) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
@ -236,7 +237,8 @@ object Helper {
|
||||||
episode,
|
episode,
|
||||||
video,
|
video,
|
||||||
subtitle,
|
subtitle,
|
||||||
sourceMedia
|
sourceMedia,
|
||||||
|
episodeImage
|
||||||
)
|
)
|
||||||
|
|
||||||
val downloadsManger = Injekt.get<DownloadsManager>()
|
val downloadsManger = Injekt.get<DownloadsManager>()
|
||||||
|
|
|
@ -283,7 +283,8 @@ class SelectorDialogFragment : BottomSheetDialogFragment() {
|
||||||
episode.number,
|
episode.number,
|
||||||
video,
|
video,
|
||||||
null,
|
null,
|
||||||
media
|
media,
|
||||||
|
episode.thumb?.url?: media!!.banner?: media!!.cover
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
dismiss()
|
dismiss()
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue