first working version of anime downloads

This commit is contained in:
Finnley Somdahl 2023-12-30 05:12:46 -06:00
parent 41830dba4d
commit d16fbd9a43
19 changed files with 402 additions and 156 deletions

View file

@ -15,43 +15,43 @@ class DownloadsManager(private val context: Context) {
private val gson = Gson()
private val downloadsList = loadDownloads().toMutableList()
val mangaDownloads: List<Download>
get() = downloadsList.filter { it.type == Download.Type.MANGA }
val animeDownloads: List<Download>
get() = downloadsList.filter { it.type == Download.Type.ANIME }
val novelDownloads: List<Download>
get() = downloadsList.filter { it.type == Download.Type.NOVEL }
val mangaDownloadedTypes: List<DownloadedType>
get() = downloadsList.filter { it.type == DownloadedType.Type.MANGA }
val animeDownloadedTypes: List<DownloadedType>
get() = downloadsList.filter { it.type == DownloadedType.Type.ANIME }
val novelDownloadedTypes: List<DownloadedType>
get() = downloadsList.filter { it.type == DownloadedType.Type.NOVEL }
private fun saveDownloads() {
val jsonString = gson.toJson(downloadsList)
prefs.edit().putString("downloads_key", jsonString).apply()
}
private fun loadDownloads(): List<Download> {
private fun loadDownloads(): List<DownloadedType> {
val jsonString = prefs.getString("downloads_key", null)
return if (jsonString != null) {
val type = object : TypeToken<List<Download>>() {}.type
val type = object : TypeToken<List<DownloadedType>>() {}.type
gson.fromJson(jsonString, type)
} else {
emptyList()
}
}
fun addDownload(download: Download) {
downloadsList.add(download)
fun addDownload(downloadedType: DownloadedType) {
downloadsList.add(downloadedType)
saveDownloads()
}
fun removeDownload(download: Download) {
downloadsList.remove(download)
removeDirectory(download)
fun removeDownload(downloadedType: DownloadedType) {
downloadsList.remove(downloadedType)
removeDirectory(downloadedType)
saveDownloads()
}
fun removeMedia(title: String, type: Download.Type) {
val subDirectory = if (type == Download.Type.MANGA) {
fun removeMedia(title: String, type: DownloadedType.Type) {
val subDirectory = if (type == DownloadedType.Type.MANGA) {
"Manga"
} else if (type == Download.Type.ANIME) {
} else if (type == DownloadedType.Type.ANIME) {
"Anime"
} else {
"Novel"
@ -76,16 +76,16 @@ class DownloadsManager(private val context: Context) {
}
private fun cleanDownloads() {
cleanDownload(Download.Type.MANGA)
cleanDownload(Download.Type.ANIME)
cleanDownload(Download.Type.NOVEL)
cleanDownload(DownloadedType.Type.MANGA)
cleanDownload(DownloadedType.Type.ANIME)
cleanDownload(DownloadedType.Type.NOVEL)
}
private fun cleanDownload(type: Download.Type) {
private fun cleanDownload(type: DownloadedType.Type) {
// remove all folders that are not in the downloads list
val subDirectory = if (type == Download.Type.MANGA) {
val subDirectory = if (type == DownloadedType.Type.MANGA) {
"Manga"
} else if (type == Download.Type.ANIME) {
} else if (type == DownloadedType.Type.ANIME) {
"Anime"
} else {
"Novel"
@ -94,18 +94,18 @@ class DownloadsManager(private val context: Context) {
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/$subDirectory"
)
val downloadsSubList = if (type == Download.Type.MANGA) {
mangaDownloads
} else if (type == Download.Type.ANIME) {
animeDownloads
val downloadsSubLists = if (type == DownloadedType.Type.MANGA) {
mangaDownloadedTypes
} else if (type == DownloadedType.Type.ANIME) {
animeDownloadedTypes
} else {
novelDownloads
novelDownloadedTypes
}
if (directory.exists()) {
val files = directory.listFiles()
if (files != null) {
for (file in files) {
if (!downloadsSubList.any { it.title == file.name }) {
if (!downloadsSubLists.any { it.title == file.name }) {
val deleted = file.deleteRecursively()
}
}
@ -122,7 +122,7 @@ class DownloadsManager(private val context: Context) {
}
}
fun saveDownloadsListToJSONFileInDownloadsFolder(downloadsList: List<Download>) //for debugging
fun saveDownloadsListToJSONFileInDownloadsFolder(downloadsList: List<DownloadedType>) //for debugging
{
val jsonString = gson.toJson(downloadsList)
val file = File(
@ -138,25 +138,33 @@ class DownloadsManager(private val context: Context) {
file.writeText(jsonString)
}
fun queryDownload(download: Download): Boolean {
return downloadsList.contains(download)
fun queryDownload(downloadedType: DownloadedType): Boolean {
return downloadsList.contains(downloadedType)
}
private fun removeDirectory(download: Download) {
val directory = if (download.type == Download.Type.MANGA) {
fun queryDownload(title: String, chapter: String, type: DownloadedType.Type? = null): Boolean {
return if (type == null) {
downloadsList.any { it.title == title && it.chapter == chapter }
} else {
downloadsList.any { it.title == title && it.chapter == chapter && it.type == type }
}
}
private fun removeDirectory(downloadedType: DownloadedType) {
val directory = if (downloadedType.type == DownloadedType.Type.MANGA) {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/Manga/${download.title}/${download.chapter}"
"Dantotsu/Manga/${downloadedType.title}/${downloadedType.chapter}"
)
} else if (download.type == Download.Type.ANIME) {
} else if (downloadedType.type == DownloadedType.Type.ANIME) {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/Anime/${download.title}/${download.chapter}"
"Dantotsu/Anime/${downloadedType.title}/${downloadedType.chapter}"
)
} else {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/Novel/${download.title}/${download.chapter}"
"Dantotsu/Novel/${downloadedType.title}/${downloadedType.chapter}"
)
}
@ -173,26 +181,26 @@ class DownloadsManager(private val context: Context) {
}
}
fun exportDownloads(download: Download) { //copies to the downloads folder available to the user
val directory = if (download.type == Download.Type.MANGA) {
fun exportDownloads(downloadedType: DownloadedType) { //copies to the downloads folder available to the user
val directory = if (downloadedType.type == DownloadedType.Type.MANGA) {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/Manga/${download.title}/${download.chapter}"
"Dantotsu/Manga/${downloadedType.title}/${downloadedType.chapter}"
)
} else if (download.type == Download.Type.ANIME) {
} else if (downloadedType.type == DownloadedType.Type.ANIME) {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/Anime/${download.title}/${download.chapter}"
"Dantotsu/Anime/${downloadedType.title}/${downloadedType.chapter}"
)
} else {
File(
context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/Novel/${download.title}/${download.chapter}"
"Dantotsu/Novel/${downloadedType.title}/${downloadedType.chapter}"
)
}
val destination = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/${download.title}/${download.chapter}"
"Dantotsu/${downloadedType.title}/${downloadedType.chapter}"
)
if (directory.exists()) {
val copied = directory.copyRecursively(destination, true)
@ -206,10 +214,10 @@ class DownloadsManager(private val context: Context) {
}
}
fun purgeDownloads(type: Download.Type) {
val directory = if (type == Download.Type.MANGA) {
fun purgeDownloads(type: DownloadedType.Type) {
val directory = if (type == DownloadedType.Type.MANGA) {
File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/Manga")
} else if (type == Download.Type.ANIME) {
} else if (type == DownloadedType.Type.ANIME) {
File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/Anime")
} else {
File(context.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS), "Dantotsu/Novel")
@ -237,7 +245,7 @@ class DownloadsManager(private val context: Context) {
}
data class Download(val title: String, val chapter: String, val type: Type) : Serializable {
data class DownloadedType(val title: String, val chapter: String, val type: Type) : Serializable {
enum class Type {
MANGA,
ANIME,

View file

@ -8,7 +8,6 @@ import android.content.Intent
import android.content.IntentFilter
import android.content.pm.PackageManager
import android.content.pm.ServiceInfo
import android.graphics.Bitmap
import android.os.Build
import android.os.Environment
import android.os.IBinder
@ -18,15 +17,15 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import androidx.media3.common.util.UnstableApi
import androidx.media3.exoplayer.offline.Download
import androidx.media3.exoplayer.offline.DownloadManager
import androidx.media3.exoplayer.offline.DownloadService
import ani.dantotsu.R
import ani.dantotsu.currActivity
import ani.dantotsu.download.Download
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.download.anime.AnimeDownloaderService
import ani.dantotsu.download.anime.AnimeServiceDataSingleton
import ani.dantotsu.download.video.Helper
import ani.dantotsu.download.video.MyDownloadService
import ani.dantotsu.download.video.ExoplayerDownloadService
import ani.dantotsu.logger
import ani.dantotsu.media.Media
import ani.dantotsu.media.anime.AnimeWatchFragment
@ -44,14 +43,11 @@ import eu.kanade.tachiyomi.data.notification.Notifications
import eu.kanade.tachiyomi.source.model.SChapter
import eu.kanade.tachiyomi.source.model.SChapterImpl
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Deferred
import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.Job
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.async
import kotlinx.coroutines.awaitAll
import kotlinx.coroutines.launch
import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
@ -161,7 +157,7 @@ class AnimeDownloaderService : Service() {
val url = AnimeServiceDataSingleton.downloadQueue.find { it.getTaskName() == taskName }?.video?.file?.url ?: ""
DownloadService.sendRemoveDownload(
this@AnimeDownloaderService,
MyDownloadService::class.java,
ExoplayerDownloadService::class.java,
url,
false
)
@ -220,16 +216,28 @@ class AnimeDownloaderService : Service() {
}
saveMediaInfo(task)
downloadsManager.addDownload(
Download(
task.title,
task.episode,
Download.Type.ANIME,
)
var continueDownload = false
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
launch {
kotlinx.coroutines.delay(30000)
continueDownload = true
}
// periodically check if the download is complete
while (downloadManager.downloadIndex.getDownload(task.video.file.url) != null) {
while (downloadManager.downloadIndex.getDownload(task.video.file.url) != null || continueDownload == false) {
val download = downloadManager.downloadIndex.getDownload(task.video.file.url)
if (download != null) {
if (download.state == androidx.media3.exoplayer.offline.Download.STATE_FAILED) {
@ -251,6 +259,13 @@ class AnimeDownloaderService : Service() {
task.getTaskName(),
task.video.file.url
).apply()
downloadsManager.addDownload(
DownloadedType(
task.title,
task.episode,
DownloadedType.Type.ANIME,
)
)
broadcastDownloadFinished(task.getTaskName())
break
}
@ -284,9 +299,11 @@ class AnimeDownloaderService : Service() {
GlobalScope.launch(Dispatchers.IO) {
val directory = File(
getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/Anime/${task.title}"
"${DownloadsManager.animeLocation}/${task.title}"
)
val episodeDirectory = File(directory, task.episode)
if (!directory.exists()) directory.mkdirs()
if (!episodeDirectory.exists()) episodeDirectory.mkdirs()
val file = File(directory, "media.json")
val gson = GsonBuilder()
@ -305,6 +322,9 @@ class AnimeDownloaderService : Service() {
if (media != null) {
media.cover = media.cover?.let { downloadImage(it, directory, "cover.jpg") }
media.banner = media.banner?.let { downloadImage(it, directory, "banner.jpg") }
if (task.episodeImage != null) {
downloadImage(task.episodeImage, episodeDirectory, "episodeImage.jpg")
}
val jsonString = gson.toJson(media)
withContext(Dispatchers.Main) {
@ -395,6 +415,7 @@ class AnimeDownloaderService : Service() {
val video: Video,
val subtitle: Subtitle? = null,
val sourceMedia: Media? = null,
val episodeImage: String? = null,
val retries: Int = 2,
val simultaneousDownloads: Int = 2,
) {

View file

@ -18,7 +18,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import ani.dantotsu.R
import ani.dantotsu.download.Download
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.logger
import ani.dantotsu.media.Media
@ -246,10 +246,10 @@ class MangaDownloaderService : Service() {
saveMediaInfo(task)
downloadsManager.addDownload(
Download(
DownloadedType(
task.title,
task.chapter,
Download.Type.MANGA
DownloadedType.Type.MANGA
)
)
broadcastDownloadFinished(task.chapter)

View file

@ -2,7 +2,6 @@ package ani.dantotsu.download.manga
import android.animation.ObjectAnimator
import android.content.Context
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.os.Build
@ -23,20 +22,16 @@ import android.widget.GridView
import android.widget.ImageView
import androidx.appcompat.app.AppCompatActivity
import androidx.cardview.widget.CardView
import androidx.core.app.ActivityCompat.recreate
import androidx.fragment.app.Fragment
import ani.dantotsu.R
import ani.dantotsu.Refresh
import ani.dantotsu.currActivity
import ani.dantotsu.currContext
import ani.dantotsu.download.Download
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.initActivity
import ani.dantotsu.logger
import ani.dantotsu.media.Media
import ani.dantotsu.media.MediaDetailsActivity
import ani.dantotsu.setSafeOnClickListener
import ani.dantotsu.settings.SettingsActivity
import ani.dantotsu.settings.SettingsDialogFragment
import ani.dantotsu.snackString
import ani.dantotsu.statusBarHeight
@ -168,8 +163,8 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
// Get the OfflineMangaModel that was clicked
val item = adapter.getItem(position) as OfflineMangaModel
val media =
downloadManager.mangaDownloads.firstOrNull { it.title == item.title }
?: downloadManager.novelDownloads.firstOrNull { it.title == item.title }
downloadManager.mangaDownloadedTypes.firstOrNull { it.title == item.title }
?: downloadManager.novelDownloadedTypes.firstOrNull { it.title == item.title }
media?.let {
startActivity(
Intent(requireContext(), MediaDetailsActivity::class.java)
@ -184,10 +179,10 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
gridView.setOnItemLongClickListener { parent, view, position, id ->
// Get the OfflineMangaModel that was clicked
val item = adapter.getItem(position) as OfflineMangaModel
val type: Download.Type = if (downloadManager.mangaDownloads.any { it.title == item.title }) {
Download.Type.MANGA
val type: DownloadedType.Type = if (downloadManager.mangaDownloadedTypes.any { it.title == item.title }) {
DownloadedType.Type.MANGA
} else {
Download.Type.NOVEL
DownloadedType.Type.NOVEL
}
// Alert dialog to confirm deletion
val builder = androidx.appcompat.app.AlertDialog.Builder(requireContext(), R.style.MyPopup)
@ -292,19 +287,19 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
private fun getDownloads() {
downloads = listOf()
val mangaTitles = downloadManager.mangaDownloads.map { it.title }.distinct()
val mangaTitles = downloadManager.mangaDownloadedTypes.map { it.title }.distinct()
val newMangaDownloads = mutableListOf<OfflineMangaModel>()
for (title in mangaTitles) {
val _downloads = downloadManager.mangaDownloads.filter { it.title == title }
val _downloads = downloadManager.mangaDownloadedTypes.filter { it.title == title }
val download = _downloads.first()
val offlineMangaModel = loadOfflineMangaModel(download)
newMangaDownloads += offlineMangaModel
}
downloads = newMangaDownloads
val novelTitles = downloadManager.novelDownloads.map { it.title }.distinct()
val novelTitles = downloadManager.novelDownloadedTypes.map { it.title }.distinct()
val newNovelDownloads = mutableListOf<OfflineMangaModel>()
for (title in novelTitles) {
val _downloads = downloadManager.novelDownloads.filter { it.title == title }
val _downloads = downloadManager.novelDownloadedTypes.filter { it.title == title }
val download = _downloads.first()
val offlineMangaModel = loadOfflineMangaModel(download)
newNovelDownloads += offlineMangaModel
@ -313,17 +308,17 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
}
private fun getMedia(download: Download): Media? {
val type = if (download.type == Download.Type.MANGA) {
private fun getMedia(downloadedType: DownloadedType): Media? {
val type = if (downloadedType.type == DownloadedType.Type.MANGA) {
"Manga"
} else if (download.type == Download.Type.ANIME) {
} else if (downloadedType.type == DownloadedType.Type.ANIME) {
"Anime"
} else {
"Novel"
}
val directory = File(
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/$type/${download.title}"
"Dantotsu/$type/${downloadedType.title}"
)
//load media.json and convert to media class with gson
return try {
@ -343,23 +338,23 @@ class OfflineMangaFragment : Fragment(), OfflineMangaSearchListener {
}
}
private fun loadOfflineMangaModel(download: Download): OfflineMangaModel {
val type = if (download.type == Download.Type.MANGA) {
private fun loadOfflineMangaModel(downloadedType: DownloadedType): OfflineMangaModel {
val type = if (downloadedType.type == DownloadedType.Type.MANGA) {
"Manga"
} else if (download.type == Download.Type.ANIME) {
} else if (downloadedType.type == DownloadedType.Type.ANIME) {
"Anime"
} else {
"Novel"
}
val directory = File(
currContext()?.getExternalFilesDir(Environment.DIRECTORY_DOWNLOADS),
"Dantotsu/$type/${download.title}"
"Dantotsu/$type/${downloadedType.title}"
)
//load media.json and convert to media class with gson
try {
val media = File(directory, "media.json")
val mediaJson = media.readText()
val mediaModel = getMedia(download)!!
val mediaModel = getMedia(downloadedType)!!
val cover = File(directory, "cover.jpg")
val coverUri: Uri? = if (cover.exists()) {
Uri.fromFile(cover)

View file

@ -17,7 +17,7 @@ import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import ani.dantotsu.R
import ani.dantotsu.download.Download
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.logger
import ani.dantotsu.media.Media
@ -330,10 +330,10 @@ class NovelDownloaderService : Service() {
saveMediaInfo(task)
downloadsManager.addDownload(
Download(
DownloadedType(
task.title,
task.chapter,
Download.Type.NOVEL
DownloadedType.Type.NOVEL
)
)
broadcastDownloadFinished(task.originalLink)

View file

@ -11,7 +11,7 @@ import androidx.media3.exoplayer.scheduler.Scheduler
import ani.dantotsu.R
@UnstableApi
class MyDownloadService : DownloadService(1, 2000, "download_service", R.string.downloads, 0) {
class ExoplayerDownloadService : DownloadService(1, 2000, "download_service", R.string.downloads, 0) {
companion object {
private const val JOB_ID = 1
private const val FOREGROUND_NOTIFICATION_ID = 1

View file

@ -3,6 +3,7 @@ package ani.dantotsu.download.video
import android.Manifest
import android.annotation.SuppressLint
import android.app.Activity
import android.app.AlertDialog
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
@ -12,6 +13,7 @@ import android.util.Log
import androidx.annotation.OptIn
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.core.content.ContextCompat.getString
import androidx.media3.common.C
import androidx.media3.common.MediaItem
import androidx.media3.common.MimeTypes
@ -32,6 +34,8 @@ import androidx.media3.exoplayer.scheduler.Requirements
import androidx.media3.ui.TrackSelectionDialogBuilder
import ani.dantotsu.R
import ani.dantotsu.defaultHeaders
import ani.dantotsu.download.DownloadedType
import ani.dantotsu.download.DownloadsManager
import ani.dantotsu.download.anime.AnimeDownloaderService
import ani.dantotsu.download.anime.AnimeServiceDataSingleton
import ani.dantotsu.logError
@ -50,7 +54,8 @@ import java.util.concurrent.*
object Helper {
var simpleCache: SimpleCache? = null
private var simpleCache: SimpleCache? = null
@SuppressLint("UnsafeOptInUsageError")
fun downloadVideo(context: Context, video: Video, subtitle: Subtitle?) {
val dataSourceFactory = DataSource.Factory {
@ -96,18 +101,18 @@ object Helper {
)
downloadHelper.prepare(object : DownloadHelper.Callback {
override fun onPrepared(helper: DownloadHelper) {
TrackSelectionDialogBuilder(
context, "Select thingy", helper.getTracks(0).groups
/*TrackSelectionDialogBuilder( TODO: use this for subtitles
context, "Select Source", helper.getTracks(0).groups
) { _, overrides ->
val params = TrackSelectionParameters.Builder(context)
overrides.forEach {
params.addOverride(it.value)
}
helper.addTrackSelection(0, params.build())
MyDownloadService
ExoplayerDownloadService
DownloadService.sendAddDownload(
context,
MyDownloadService::class.java,
ExoplayerDownloadService::class.java,
helper.getDownloadRequest(null),
false
)
@ -117,6 +122,14 @@ object Helper {
if (it.frameRate > 0f) it.height.toString() + "p" else it.height.toString() + "p (fps : N/A)"
}
build().show()
}*/
helper.getDownloadRequest(null).let {
DownloadService.sendAddDownload(
context,
ExoplayerDownloadService::class.java,
it,
false
)
}
}
@ -149,7 +162,7 @@ object Helper {
}
val threadPoolSize = Runtime.getRuntime().availableProcessors()
val executorService = Executors.newFixedThreadPool(threadPoolSize)
val downloadManager = DownloadManager(
val downloadManager = DownloadManager(
context,
database,
getSimpleCache(context),
@ -160,15 +173,15 @@ object Helper {
Requirements(Requirements.NETWORK or Requirements.DEVICE_STORAGE_NOT_LOW)
maxParallelDownloads = 3
}
downloadManager.addListener(
object : DownloadManager.Listener { // Override methods of interest here.
downloadManager.addListener( //for testing
object : DownloadManager.Listener {
override fun onDownloadChanged(
downloadManager: DownloadManager,
download: Download,
finalException: Exception?
) {
if (download.state == Download.STATE_COMPLETED) {
Log.e("Downloader", "Download Completed")
Log.e("Downloader", "Download Completed")
} else if (download.state == Download.STATE_FAILED) {
Log.e("Downloader", "Download Failed")
} else if (download.state == Download.STATE_STOPPED) {
@ -199,6 +212,7 @@ object Helper {
return downloadDirectory!!
}
@OptIn(UnstableApi::class)
fun startAnimeDownloadService(
context: Context,
title: String,
@ -224,16 +238,62 @@ object Helper {
subtitle,
sourceMedia
)
AnimeServiceDataSingleton.downloadQueue.offer(downloadTask)
if (!AnimeServiceDataSingleton.isServiceRunning) {
val intent = Intent(context, AnimeDownloaderService::class.java)
ContextCompat.startForegroundService(context, intent)
AnimeServiceDataSingleton.isServiceRunning = true
val downloadsManger = Injekt.get<DownloadsManager>()
val downloadCheck = downloadsManger
.queryDownload(title, episode, DownloadedType.Type.ANIME)
if (downloadCheck) {
AlertDialog.Builder(context)
.setTitle("Download Exists")
.setMessage("A download for this episode already exists. Do you want to overwrite it?")
.setPositiveButton("Yes") { _, _ ->
DownloadService.sendRemoveDownload(
context,
ExoplayerDownloadService::class.java,
context.getSharedPreferences(
getString(context, R.string.anime_downloads),
Context.MODE_PRIVATE
).getString(
downloadTask.getTaskName(),
""
) ?: "",
false
)
context.getSharedPreferences(
getString(context, R.string.anime_downloads),
Context.MODE_PRIVATE
).edit()
.remove(downloadTask.getTaskName())
.apply()
downloadsManger.removeDownload(
DownloadedType(
title,
episode,
DownloadedType.Type.ANIME
)
)
AnimeServiceDataSingleton.downloadQueue.offer(downloadTask)
if (!AnimeServiceDataSingleton.isServiceRunning) {
val intent = Intent(context, AnimeDownloaderService::class.java)
ContextCompat.startForegroundService(context, intent)
AnimeServiceDataSingleton.isServiceRunning = true
}
}
.setNegativeButton("No") { _, _ -> }
.show()
} else {
AnimeServiceDataSingleton.downloadQueue.offer(downloadTask)
if (!AnimeServiceDataSingleton.isServiceRunning) {
val intent = Intent(context, AnimeDownloaderService::class.java)
ContextCompat.startForegroundService(context, intent)
AnimeServiceDataSingleton.isServiceRunning = true
}
}
}
@OptIn(UnstableApi::class) private fun getSimpleCache(context: Context): SimpleCache {
@OptIn(UnstableApi::class)
fun getSimpleCache(context: Context): SimpleCache {
return if (simpleCache == null) {
val downloadDirectory = File(getDownloadDirectory(context), DOWNLOAD_CONTENT_DIRECTORY)
val database = Injekt.get<StandaloneDatabaseProvider>()