Skip to content

Commit

Permalink
fix: some download optimizations
Browse files Browse the repository at this point in the history
  • Loading branch information
rebelonion committed May 27, 2024
1 parent b300478 commit 5800dcf
Show file tree
Hide file tree
Showing 6 changed files with 107 additions and 63 deletions.
4 changes: 2 additions & 2 deletions app/src/main/java/ani/dantotsu/download/DownloadCompat.kt
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ class DownloadCompat {
Logger.log(e)
Injekt.get<CrashlyticsInterface>().logException(e)
return OfflineAnimeModel(
"unknown",
downloadedType.titleName,
"0",
"??",
"??",
Expand Down Expand Up @@ -188,7 +188,7 @@ class DownloadCompat {
Logger.log(e)
Injekt.get<CrashlyticsInterface>().logException(e)
return OfflineMangaModel(
"unknown",
downloadedType.titleName,
"0",
"??",
"??",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ class AnimeDownloaderService : Service() {
}

private fun updateNotification() {
// Update the notification to reflect the current state of the queue
val pendingDownloads = AnimeServiceDataSingleton.downloadQueue.size
val text = if (pendingDownloads > 0) {
"Pending downloads: $pendingDownloads"
Expand All @@ -201,7 +200,7 @@ class AnimeDownloaderService : Service() {

@androidx.annotation.OptIn(UnstableApi::class)
suspend fun download(task: AnimeDownloadTask) {
withContext(Dispatchers.Main) {
withContext(Dispatchers.IO) {
try {
val notifi = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.checkSelfPermission(
Expand All @@ -214,13 +213,21 @@ class AnimeDownloaderService : Service() {

builder.setContentText("Downloading ${getTaskName(task.title, task.episode)}")
if (notifi) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
withContext(Dispatchers.Main) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}

val outputDir = getSubDirectory(
val baseOutputDir = getSubDirectory(
this@AnimeDownloaderService,
MediaType.ANIME,
false,
task.title
) ?: throw Exception("Failed to create output directory")
val outputDir = getSubDirectory(
this@AnimeDownloaderService,
MediaType.ANIME,
true,
task.title,
task.episode
) ?: throw Exception("Failed to create output directory")
Expand Down Expand Up @@ -277,7 +284,7 @@ class AnimeDownloaderService : Service() {
currentTasks.find { it.getTaskName() == task.getTaskName() }?.sessionId =
ffTask

saveMediaInfo(task)
saveMediaInfo(task, baseOutputDir)

// periodically check if the download is complete
while (ffExtension.getState(ffTask) != "COMPLETED") {
Expand All @@ -291,7 +298,11 @@ class AnimeDownloaderService : Service() {
)
} Download failed"
)
notificationManager.notify(NOTIFICATION_ID, builder.build())
if (notifi) {
withContext(Dispatchers.Main) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}
toast("${getTaskName(task.title, task.episode)} Download failed")
Logger.log("Download failed: ${ffExtension.getStackTrace(ffTask)}")
downloadsManager.removeDownload(
Expand Down Expand Up @@ -324,7 +335,9 @@ class AnimeDownloaderService : Service() {
percent.coerceAtMost(99)
)
if (notifi) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
withContext(Dispatchers.Main) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}
kotlinx.coroutines.delay(2000)
}
Expand All @@ -339,7 +352,11 @@ class AnimeDownloaderService : Service() {
)
} Download failed"
)
notificationManager.notify(NOTIFICATION_ID, builder.build())
if (notifi) {
withContext(Dispatchers.Main) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}
snackString("${getTaskName(task.title, task.episode)} Download failed")
downloadsManager.removeDownload(
DownloadedType(
Expand Down Expand Up @@ -371,7 +388,11 @@ class AnimeDownloaderService : Service() {
)
} Download completed"
)
notificationManager.notify(NOTIFICATION_ID, builder.build())
if (notifi) {
withContext(Dispatchers.Main) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}
snackString("${getTaskName(task.title, task.episode)} Download completed")
PrefManager.getAnimeDownloadPreferences().edit().putString(
task.getTaskName(),
Expand Down Expand Up @@ -401,11 +422,8 @@ class AnimeDownloaderService : Service() {
}
}

private fun saveMediaInfo(task: AnimeDownloadTask) {
private fun saveMediaInfo(task: AnimeDownloadTask, directory: DocumentFile) {
CoroutineScope(Dispatchers.IO).launch {
val directory =
getSubDirectory(this@AnimeDownloaderService, MediaType.ANIME, false, task.title)
?: throw Exception("Directory not found")
directory.findFile("media.json")?.forceDelete(this@AnimeDownloaderService)
val file = directory.createFile("application/json", "media.json")
?: throw Exception("File not created")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import ani.dantotsu.bottomBar
import ani.dantotsu.connections.crashlytics.CrashlyticsInterface
import ani.dantotsu.currActivity
import ani.dantotsu.currContext
import ani.dantotsu.download.DownloadCompat
import ani.dantotsu.download.DownloadCompat.Companion.loadMediaCompat
import ani.dantotsu.download.DownloadCompat.Companion.loadOfflineAnimeModelCompat
import ani.dantotsu.download.DownloadedType
Expand Down Expand Up @@ -319,17 +320,20 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
)
val gson = GsonBuilder()
.registerTypeAdapter(SChapter::class.java, InstanceCreator<SChapter> {
SChapterImpl() // Provide an instance of SChapterImpl
SChapterImpl()
})
.registerTypeAdapter(SAnime::class.java, InstanceCreator<SAnime> {
SAnimeImpl() // Provide an instance of SAnimeImpl
SAnimeImpl()
})
.registerTypeAdapter(SEpisode::class.java, InstanceCreator<SEpisode> {
SEpisodeImpl() // Provide an instance of SEpisodeImpl
SEpisodeImpl()
})
.create()
val media = directory?.findFile("media.json")
?: return loadMediaCompat(downloadedType)
if (media == null) {
Logger.log("No media.json found at ${directory?.uri?.path}")
return loadMediaCompat(downloadedType)
}
val mediaJson =
media.openInputStream(context ?: currContext()!!)?.bufferedReader().use {
it?.readText()
Expand Down Expand Up @@ -394,14 +398,15 @@ class OfflineAnimeFragment : Fragment(), OfflineAnimeSearchListener {
bannerUri
)
} catch (e: Exception) {
Logger.log(e)
return try {
loadOfflineAnimeModelCompat(downloadedType)
} catch (e: Exception) {
Logger.log("Error loading media.json: ${e.message}")
Logger.log(e)
Injekt.get<CrashlyticsInterface>().logException(e)
OfflineAnimeModel(
"unknown",
downloadedType.titleName,
"0",
"??",
"??",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -134,15 +134,15 @@ class MangaDownloaderService : Service() {
mutex.withLock {
downloadJobs[task.chapter] = job
}
job.join() // Wait for the job to complete before continuing to the next task
job.join()
mutex.withLock {
downloadJobs.remove(task.chapter)
}
updateNotification() // Update the notification after each task is completed
updateNotification()
}
if (MangaServiceDataSingleton.downloadQueue.isEmpty()) {
withContext(Dispatchers.Main) {
stopSelf() // Stop the service when the queue is empty
stopSelf()
}
}
}
Expand Down Expand Up @@ -181,7 +181,7 @@ class MangaDownloaderService : Service() {

suspend fun download(task: DownloadTask) {
try {
withContext(Dispatchers.Main) {
withContext(Dispatchers.IO) {
val notifi = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
ContextCompat.checkSelfPermission(
this@MangaDownloaderService,
Expand All @@ -194,18 +194,27 @@ class MangaDownloaderService : Service() {
val deferredMap = mutableMapOf<Int, Deferred<Bitmap?>>()
builder.setContentText("Downloading ${task.title} - ${task.chapter}")
if (notifi) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
withContext(Dispatchers.Main) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}

getSubDirectory(
val baseOutputDir = getSubDirectory(
this@MangaDownloaderService,
MediaType.MANGA,
false,
task.title
) ?: throw Exception("Base output directory not found")
val outputDir = getSubDirectory(
this@MangaDownloaderService,
MediaType.MANGA,
false,
task.title,
task.chapter
)?.deleteRecursively(this@MangaDownloaderService)
) ?: throw Exception("Output directory not found")

outputDir.deleteRecursively(this@MangaDownloaderService, true)

// Loop through each ImageData object from the task
var farthest = 0
for ((index, image) in task.imageData.withIndex()) {
if (deferredMap.size >= task.simultaneousDownloads) {
Expand All @@ -226,30 +235,36 @@ class MangaDownloaderService : Service() {
}

if (bitmap != null) {
saveToDisk("$index.jpg", bitmap, task.title, task.chapter)
saveToDisk("$index.jpg", outputDir, bitmap)
}
farthest++

builder.setProgress(task.imageData.size, farthest, false)

broadcastDownloadProgress(
task.chapter,
farthest * 100 / task.imageData.size
)
if (notifi) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
withContext(Dispatchers.Main) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}

bitmap
}
}

// Wait for any remaining deferred to complete
deferredMap.values.awaitAll()

builder.setContentText("${task.title} - ${task.chapter} Download complete")
.setProgress(0, 0, false)
notificationManager.notify(NOTIFICATION_ID, builder.build())
withContext(Dispatchers.Main) {
builder.setContentText("${task.title} - ${task.chapter} Download complete")
.setProgress(0, 0, false)
if (notifi) {
notificationManager.notify(NOTIFICATION_ID, builder.build())
}
}

saveMediaInfo(task)
saveMediaInfo(task, baseOutputDir)
downloadsManager.addDownload(
DownloadedType(
task.title,
Expand All @@ -269,17 +284,16 @@ class MangaDownloaderService : Service() {
}


private fun saveToDisk(fileName: String, bitmap: Bitmap, title: String, chapter: String) {
private fun saveToDisk(
fileName: String,
directory: DocumentFile,
bitmap: Bitmap
) {
try {
// Define the directory within the private external storage space
val directory = getSubDirectory(this, MediaType.MANGA, false, title, chapter)
?: throw Exception("Directory not found")
directory.findFile(fileName)?.forceDelete(this)
// Create a file reference within that directory for the image
val file =
directory.createFile("image/jpeg", fileName) ?: throw Exception("File not created")

// Use a FileOutputStream to write the bitmap to the file
file.openOutputStream(this, false).use { outputStream ->
if (outputStream == null) throw Exception("Output stream is null")
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, outputStream)
Expand All @@ -292,11 +306,8 @@ class MangaDownloaderService : Service() {
}

@OptIn(DelicateCoroutinesApi::class)
private fun saveMediaInfo(task: DownloadTask) {
private fun saveMediaInfo(task: DownloadTask, directory: DocumentFile) {
launchIO {
val directory =
getSubDirectory(this@MangaDownloaderService, MediaType.MANGA, false, task.title)
?: throw Exception("Directory not found")
directory.findFile("media.json")?.forceDelete(this@MangaDownloaderService)
val file = directory.createFile("application/json", "media.json")
?: throw Exception("File not created")
Expand Down
Loading

0 comments on commit 5800dcf

Please sign in to comment.