mirror of
https://github.com/tachiyomiorg/tachiyomi.git
synced 2024-12-24 14:01:53 +01:00
Add option to dump crash logs
To tachi-chan: Thank you for your service o7
This commit is contained in:
parent
c26c38ca39
commit
093018fd81
@ -244,6 +244,8 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
// Called to launch send intent.
|
// Called to launch send intent.
|
||||||
private const val ACTION_SHARE_BACKUP = "$ID.$NAME.SEND_BACKUP"
|
private const val ACTION_SHARE_BACKUP = "$ID.$NAME.SEND_BACKUP"
|
||||||
|
|
||||||
|
private const val ACTION_SHARE_CRASH_LOG = "$ID.$NAME.SEND_CRASH_LOG"
|
||||||
|
|
||||||
// Called to cancel library update.
|
// Called to cancel library update.
|
||||||
private const val ACTION_CANCEL_LIBRARY_UPDATE = "$ID.$NAME.CANCEL_LIBRARY_UPDATE"
|
private const val ACTION_CANCEL_LIBRARY_UPDATE = "$ID.$NAME.CANCEL_LIBRARY_UPDATE"
|
||||||
|
|
||||||
@ -563,6 +565,23 @@ class NotificationReceiver : BroadcastReceiver() {
|
|||||||
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns [PendingIntent] that starts a share activity for a crash log dump file.
|
||||||
|
*
|
||||||
|
* @param context context of application
|
||||||
|
* @param uri uri of file
|
||||||
|
* @param notificationId id of notification
|
||||||
|
* @return [PendingIntent]
|
||||||
|
*/
|
||||||
|
internal fun shareCrashLogPendingBroadcast(context: Context, uri: Uri, notificationId: Int): PendingIntent {
|
||||||
|
val intent = Intent(context, NotificationReceiver::class.java).apply {
|
||||||
|
action = ACTION_SHARE_CRASH_LOG
|
||||||
|
putExtra(EXTRA_URI, uri)
|
||||||
|
putExtra(EXTRA_NOTIFICATION_ID, notificationId)
|
||||||
|
}
|
||||||
|
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns [PendingIntent] that cancels a backup restore job.
|
* Returns [PendingIntent] that cancels a backup restore job.
|
||||||
*
|
*
|
||||||
|
@ -55,6 +55,12 @@ object Notifications {
|
|||||||
const val ID_BACKUP_PROGRESS = -502
|
const val ID_BACKUP_PROGRESS = -502
|
||||||
const val ID_BACKUP_COMPLETE = -503
|
const val ID_BACKUP_COMPLETE = -503
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Notification channel used for crash log file sharing.
|
||||||
|
*/
|
||||||
|
const val CHANNEL_CRASH_LOGS = "crash_logs_channel"
|
||||||
|
const val ID_CRASH_LOGS = -601
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates the notification channels introduced in Android Oreo.
|
* Creates the notification channels introduced in Android Oreo.
|
||||||
*
|
*
|
||||||
@ -113,7 +119,12 @@ object Notifications {
|
|||||||
group = GROUP_BACKUP_RESTORE
|
group = GROUP_BACKUP_RESTORE
|
||||||
setShowBadge(false)
|
setShowBadge(false)
|
||||||
setSound(null, null)
|
setSound(null, null)
|
||||||
}
|
},
|
||||||
|
NotificationChannel(
|
||||||
|
CHANNEL_CRASH_LOGS,
|
||||||
|
context.getString(R.string.crash_logs),
|
||||||
|
NotificationManager.IMPORTANCE_HIGH
|
||||||
|
)
|
||||||
)
|
)
|
||||||
context.notificationManager.createNotificationChannels(channels)
|
context.notificationManager.createNotificationChannels(channels)
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import eu.kanade.tachiyomi.data.preference.PreferenceKeys
|
|||||||
import eu.kanade.tachiyomi.network.NetworkHelper
|
import eu.kanade.tachiyomi.network.NetworkHelper
|
||||||
import eu.kanade.tachiyomi.source.SourceManager
|
import eu.kanade.tachiyomi.source.SourceManager
|
||||||
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
import eu.kanade.tachiyomi.ui.base.controller.DialogController
|
||||||
|
import eu.kanade.tachiyomi.util.CrashLogUtil
|
||||||
import eu.kanade.tachiyomi.util.system.launchUI
|
import eu.kanade.tachiyomi.util.system.launchUI
|
||||||
import eu.kanade.tachiyomi.util.system.toast
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
import kotlinx.coroutines.CoroutineStart
|
import kotlinx.coroutines.CoroutineStart
|
||||||
@ -59,6 +60,37 @@ class SettingsAdvancedController : SettingsController() {
|
|||||||
summaryRes = R.string.helps_fix_bugs
|
summaryRes = R.string.helps_fix_bugs
|
||||||
defaultValue = true
|
defaultValue = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
preference {
|
||||||
|
key = "dump_crash_logs"
|
||||||
|
titleRes = R.string.dump_crash_logs
|
||||||
|
summaryRes = R.string.saves_error_logs
|
||||||
|
|
||||||
|
onClick {
|
||||||
|
CrashLogUtil(context).dumpLogs()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
||||||
|
val pm = context.getSystemService(Context.POWER_SERVICE) as? PowerManager?
|
||||||
|
if (pm != null) preference {
|
||||||
|
key = "disable_batt_opt"
|
||||||
|
titleRes = R.string.disable_battery_optimization
|
||||||
|
summaryRes = R.string.disable_if_issues_with_updating
|
||||||
|
|
||||||
|
onClick {
|
||||||
|
val packageName: String = context.packageName
|
||||||
|
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
|
||||||
|
val intent = Intent().apply {
|
||||||
|
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
|
||||||
|
data = "package:$packageName".toUri()
|
||||||
|
}
|
||||||
|
startActivity(intent)
|
||||||
|
} else {
|
||||||
|
context.toast(R.string.battery_optimization_disabled)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
preferenceCategory {
|
preferenceCategory {
|
||||||
titleRes = R.string.data_management
|
titleRes = R.string.data_management
|
||||||
preference {
|
preference {
|
||||||
@ -158,30 +190,6 @@ class SettingsAdvancedController : SettingsController() {
|
|||||||
onClick { LibraryUpdateService.start(context, target = Target.TRACKING) }
|
onClick { LibraryUpdateService.start(context, target = Target.TRACKING) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
preferenceCategory {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
|
|
||||||
val pm = context.getSystemService(Context.POWER_SERVICE) as? PowerManager?
|
|
||||||
if (pm != null) preference {
|
|
||||||
key = "disable_batt_opt"
|
|
||||||
titleRes = R.string.disable_battery_optimization
|
|
||||||
summaryRes = R.string.disable_if_issues_with_updating
|
|
||||||
|
|
||||||
onClick {
|
|
||||||
val packageName: String = context.packageName
|
|
||||||
if (!pm.isIgnoringBatteryOptimizations(packageName)) {
|
|
||||||
val intent = Intent().apply {
|
|
||||||
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
|
|
||||||
data = "package:$packageName".toUri()
|
|
||||||
}
|
|
||||||
startActivity(intent)
|
|
||||||
} else {
|
|
||||||
context.toast(R.string.battery_optimization_disabled)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class CleanupDownloadsDialogController() : DialogController() {
|
class CleanupDownloadsDialogController() : DialogController() {
|
||||||
|
56
app/src/main/java/eu/kanade/tachiyomi/util/CrashLogUtil.kt
Normal file
56
app/src/main/java/eu/kanade/tachiyomi/util/CrashLogUtil.kt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
package eu.kanade.tachiyomi.util
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.net.Uri
|
||||||
|
import eu.kanade.tachiyomi.R
|
||||||
|
import eu.kanade.tachiyomi.data.notification.NotificationReceiver
|
||||||
|
import eu.kanade.tachiyomi.data.notification.Notifications
|
||||||
|
import eu.kanade.tachiyomi.util.storage.getUriCompat
|
||||||
|
import eu.kanade.tachiyomi.util.system.createFileInCacheDir
|
||||||
|
import eu.kanade.tachiyomi.util.system.notificationBuilder
|
||||||
|
import eu.kanade.tachiyomi.util.system.notificationManager
|
||||||
|
import eu.kanade.tachiyomi.util.system.toast
|
||||||
|
import java.io.IOException
|
||||||
|
|
||||||
|
class CrashLogUtil(private val context: Context) {
|
||||||
|
|
||||||
|
private val notificationBuilder = context.notificationBuilder(Notifications.CHANNEL_CRASH_LOGS) {
|
||||||
|
setSmallIcon(R.drawable.ic_tachi)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun dumpLogs() {
|
||||||
|
try {
|
||||||
|
val file = context.createFileInCacheDir("tachiyomi_crash_logs.txt")
|
||||||
|
Runtime.getRuntime().exec("logcat *:E -d -f ${file.absolutePath}")
|
||||||
|
|
||||||
|
showNotification(file.getUriCompat(context))
|
||||||
|
} catch (e: IOException) {
|
||||||
|
context.toast("Failed to get logs")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showNotification(uri: Uri) {
|
||||||
|
context.notificationManager.cancel(Notifications.ID_CRASH_LOGS)
|
||||||
|
|
||||||
|
with(notificationBuilder) {
|
||||||
|
setContentTitle(context.getString(R.string.crash_log_saved))
|
||||||
|
|
||||||
|
// Clear old actions if they exist
|
||||||
|
clearActions()
|
||||||
|
|
||||||
|
addAction(
|
||||||
|
R.drawable.ic_bug_report_24dp,
|
||||||
|
context.getString(R.string.open_log),
|
||||||
|
NotificationReceiver.openErrorLogPendingActivity(context, uri)
|
||||||
|
)
|
||||||
|
|
||||||
|
addAction(
|
||||||
|
R.drawable.ic_share_24dp,
|
||||||
|
context.getString(R.string.share),
|
||||||
|
NotificationReceiver.shareCrashLogPendingBroadcast(context, uri, Notifications.ID_CRASH_LOGS)
|
||||||
|
)
|
||||||
|
|
||||||
|
context.notificationManager.notify(Notifications.ID_CRASH_LOGS, build())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -601,6 +601,10 @@
|
|||||||
<!-- Advanced section -->
|
<!-- Advanced section -->
|
||||||
<string name="clear_chapter_cache">Clear chapter cache</string>
|
<string name="clear_chapter_cache">Clear chapter cache</string>
|
||||||
<string name="data_management">Data Management</string>
|
<string name="data_management">Data Management</string>
|
||||||
|
<string name="crash_logs">Crash logs</string>
|
||||||
|
<string name="dump_crash_logs">Dump crash logs</string>
|
||||||
|
<string name="saves_error_logs">Saves error logs to a file for sharing with the developers</string>
|
||||||
|
<string name="crash_log_saved">Crash logs saved</string>
|
||||||
<string name="network">Network</string>
|
<string name="network">Network</string>
|
||||||
<string name="dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string>
|
<string name="dns_over_https" translatable="false">DNS over HTTPS (Cloudflare)</string>
|
||||||
<string name="requires_app_restart">Requires app restart to take effect</string>
|
<string name="requires_app_restart">Requires app restart to take effect</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user