Show notification with error log on update failures

This commit is contained in:
Eugene Cheung 2020-05-13 22:28:15 -04:00
parent ccc198e081
commit fc4e290c49
4 changed files with 71 additions and 5 deletions

View File

@ -6,6 +6,7 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.BitmapFactory import android.graphics.BitmapFactory
import android.net.Uri
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationManagerCompat
import com.bumptech.glide.Glide import com.bumptech.glide.Glide
@ -80,6 +81,39 @@ class LibraryUpdateNotifier(private val context: Context) {
) )
} }
/**
* Shows notification containing update entries that failed with action to open full log.
*
* @param errors List of entry titles that failed to update.
* @param uri Uri for error log file containing all titles that failed.
*/
fun showUpdateErrorNotification(errors: List<String>, uri: Uri) {
if (errors.isEmpty()) {
return
}
context.notificationManager.notify(
Notifications.ID_LIBRARY_ERROR,
context.notificationBuilder(Notifications.CHANNEL_LIBRARY) {
setContentTitle(context.resources.getQuantityString(R.plurals.notification_update_error, errors.size, errors.size))
setStyle(
NotificationCompat.BigTextStyle().bigText(
errors.joinToString("\n") {
it.chop(NOTIF_TITLE_MAX_LEN)
}
)
)
setSmallIcon(R.drawable.ic_tachi)
addAction(
R.drawable.nnf_ic_file_folder,
context.getString(R.string.action_open_log),
NotificationReceiver.openErrorLogPendingActivity(context, uri)
)
}
.build()
)
}
/** /**
* Shows the notification containing the result of the update done by the service. * Shows the notification containing the result of the update done by the service.
* *

View File

@ -23,8 +23,10 @@ import eu.kanade.tachiyomi.source.SourceManager
import eu.kanade.tachiyomi.source.model.SManga import eu.kanade.tachiyomi.source.model.SManga
import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource import eu.kanade.tachiyomi.util.chapter.syncChaptersWithSource
import eu.kanade.tachiyomi.util.prepUpdateCover import eu.kanade.tachiyomi.util.prepUpdateCover
import eu.kanade.tachiyomi.util.storage.getUriCompat
import eu.kanade.tachiyomi.util.system.acquireWakeLock import eu.kanade.tachiyomi.util.system.acquireWakeLock
import eu.kanade.tachiyomi.util.system.isServiceRunning import eu.kanade.tachiyomi.util.system.isServiceRunning
import java.io.File
import java.util.ArrayList import java.util.ArrayList
import java.util.concurrent.atomic.AtomicInteger import java.util.concurrent.atomic.AtomicInteger
import rx.Observable import rx.Observable
@ -253,7 +255,7 @@ class LibraryUpdateService(
// List containing new updates // List containing new updates
val newUpdates = ArrayList<Pair<LibraryManga, Array<Chapter>>>() val newUpdates = ArrayList<Pair<LibraryManga, Array<Chapter>>>()
// List containing failed updates // List containing failed updates
val failedUpdates = ArrayList<Manga>() val failedUpdates = ArrayList<Pair<Manga, String?>>()
// List containing categories that get included in downloads. // List containing categories that get included in downloads.
val categoriesToDownload = preferences.downloadNewCategories().get().map(String::toInt) val categoriesToDownload = preferences.downloadNewCategories().get().map(String::toInt)
// Boolean to determine if user wants to automatically download new chapters. // Boolean to determine if user wants to automatically download new chapters.
@ -270,7 +272,7 @@ class LibraryUpdateService(
updateManga(manga) updateManga(manga)
// If there's any error, return empty update and continue. // If there's any error, return empty update and continue.
.onErrorReturn { .onErrorReturn {
failedUpdates.add(manga) failedUpdates.add(Pair(manga, it.message))
Pair(emptyList(), emptyList()) Pair(emptyList(), emptyList())
} }
// Filter out mangas without new chapters (or failed). // Filter out mangas without new chapters (or failed).
@ -303,6 +305,8 @@ class LibraryUpdateService(
} }
// Notify result of the overall update. // Notify result of the overall update.
.doOnCompleted { .doOnCompleted {
notifier.cancelProgressNotification()
if (newUpdates.isNotEmpty()) { if (newUpdates.isNotEmpty()) {
notifier.showUpdateNotifications(newUpdates) notifier.showUpdateNotifications(newUpdates)
if (downloadNew && hasDownloads) { if (downloadNew && hasDownloads) {
@ -311,10 +315,12 @@ class LibraryUpdateService(
} }
if (failedUpdates.isNotEmpty()) { if (failedUpdates.isNotEmpty()) {
Timber.e("Failed updating: ${failedUpdates.map { it.title }}") val errorFile = writeErrorFile(failedUpdates)
notifier.showUpdateErrorNotification(
failedUpdates.map { it.first.title },
errorFile.getUriCompat(this)
)
} }
notifier.cancelProgressNotification()
} }
.map { manga -> manga.first } .map { manga -> manga.first }
} }
@ -417,4 +423,25 @@ class LibraryUpdateService(
notifier.cancelProgressNotification() notifier.cancelProgressNotification()
} }
} }
/**
* Writes basic file of update errors to cache dir.
*/
private fun writeErrorFile(errors: List<Pair<Manga, String?>>): File {
try {
if (errors.isNotEmpty()) {
val destFile = File(externalCacheDir, "tachiyomi_update_errors.txt")
destFile.bufferedWriter().use { out ->
errors.forEach { (manga, error) ->
out.write("${manga.title}: $error\n")
}
}
return destFile
}
} catch (e: Exception) {
// Empty
}
return File("")
}
} }

View File

@ -25,6 +25,7 @@ object Notifications {
*/ */
const val CHANNEL_LIBRARY = "library_channel" const val CHANNEL_LIBRARY = "library_channel"
const val ID_LIBRARY_PROGRESS = -101 const val ID_LIBRARY_PROGRESS = -101
const val ID_LIBRARY_ERROR = -102
/** /**
* Notification channel and ids used by the downloader. * Notification channel and ids used by the downloader.

View File

@ -579,6 +579,10 @@
<item quantity="one">Chapters %1$s and 1 more</item> <item quantity="one">Chapters %1$s and 1 more</item>
<item quantity="other">Chapters %1$s and %2$d more</item> <item quantity="other">Chapters %1$s and %2$d more</item>
</plurals> </plurals>
<plurals name="notification_update_error">
<item quantity="one">1 update failed</item>
<item quantity="other">%1$d updates failed</item>
</plurals>
<string name="notification_cover_update_failed">Failed to update cover</string> <string name="notification_cover_update_failed">Failed to update cover</string>
<string name="notification_first_add_to_library">Please add the manga to your library before doing this</string> <string name="notification_first_add_to_library">Please add the manga to your library before doing this</string>
<string name="notification_not_connected_to_ac_title">Sync canceled</string> <string name="notification_not_connected_to_ac_title">Sync canceled</string>