diff --git a/app/src/main/java/com/github/apognu/otter/Otter.kt b/app/src/main/java/com/github/apognu/otter/Otter.kt index a117af0..c1e5b10 100644 --- a/app/src/main/java/com/github/apognu/otter/Otter.kt +++ b/app/src/main/java/com/github/apognu/otter/Otter.kt @@ -2,13 +2,14 @@ package com.github.apognu.otter import android.app.Application import androidx.appcompat.app.AppCompatDelegate -import com.github.apognu.otter.utils.Command -import com.github.apognu.otter.utils.Event -import com.github.apognu.otter.utils.Request +import com.github.apognu.otter.utils.* import com.preference.PowerPreference import kotlinx.coroutines.channels.BroadcastChannel import kotlinx.coroutines.channels.Channel import kotlinx.coroutines.channels.ConflatedBroadcastChannel +import java.text.SimpleDateFormat +import java.time.format.DateTimeFormatter +import java.util.* class Otter : Application() { companion object { @@ -17,6 +18,8 @@ class Otter : Application() { fun get(): Otter = instance } + var defaultExceptionHandler: Thread.UncaughtExceptionHandler? = null + val eventBus: BroadcastChannel = BroadcastChannel(10) val commandBus: Channel = Channel(10) val requestBus: BroadcastChannel = BroadcastChannel(10) @@ -25,6 +28,10 @@ class Otter : Application() { override fun onCreate() { super.onCreate() + defaultExceptionHandler = Thread.getDefaultUncaughtExceptionHandler() + + Thread.setDefaultUncaughtExceptionHandler(CrashReportHandler()) + instance = this when (PowerPreference.getDefaultFile().getString("night_mode")) { @@ -33,4 +40,27 @@ class Otter : Application() { else -> AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM) } } + + inner class CrashReportHandler : Thread.UncaughtExceptionHandler { + override fun uncaughtException(t: Thread, e: Throwable) { + val now = Date(Date().time - (5 * 60 * 1000)) + val formatter = SimpleDateFormat("MM-dd kk:mm:ss.000", Locale.US) + + Runtime.getRuntime().exec(listOf("logcat", "-d", "-T", formatter.format(now)).toTypedArray()).also { + it.inputStream.bufferedReader().also { reader -> + val builder = StringBuilder() + + while (true) { + builder.appendln(reader.readLine() ?: break) + } + + builder.appendln(e.toString()) + + Cache.set(this@Otter, "crashdump", builder.toString().toByteArray()) + } + } + + defaultExceptionHandler?.uncaughtException(t, e) + } + } } \ No newline at end of file diff --git a/app/src/main/java/com/github/apognu/otter/activities/MainActivity.kt b/app/src/main/java/com/github/apognu/otter/activities/MainActivity.kt index 3360c5d..b53dec4 100644 --- a/app/src/main/java/com/github/apognu/otter/activities/MainActivity.kt +++ b/app/src/main/java/com/github/apognu/otter/activities/MainActivity.kt @@ -79,6 +79,7 @@ class MainActivity : AppCompatActivity() { now_playing_toggle.setOnClickListener { CommandBus.send(Command.ToggleState) + throw Exception("coucou") } now_playing_next.setOnClickListener { diff --git a/app/src/main/java/com/github/apognu/otter/activities/SettingsActivity.kt b/app/src/main/java/com/github/apognu/otter/activities/SettingsActivity.kt index f28f11c..5a13d5c 100644 --- a/app/src/main/java/com/github/apognu/otter/activities/SettingsActivity.kt +++ b/app/src/main/java/com/github/apognu/otter/activities/SettingsActivity.kt @@ -1,8 +1,8 @@ package com.github.apognu.otter.activities -import android.content.Intent -import android.content.SharedPreferences +import android.content.* import android.os.Bundle +import android.widget.Toast import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate @@ -12,9 +12,7 @@ import androidx.preference.PreferenceFragmentCompat import androidx.preference.SeekBarPreference import com.github.apognu.otter.BuildConfig import com.github.apognu.otter.R -import com.github.apognu.otter.utils.AppContext -import com.github.apognu.otter.utils.Command -import com.github.apognu.otter.utils.CommandBus +import com.github.apognu.otter.utils.* import com.preference.PowerPreference class SettingsActivity : AppCompatActivity() { @@ -62,6 +60,18 @@ class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedP } } + "crash" -> { + activity?.let { activity -> + (activity.getSystemService(Context.CLIPBOARD_SERVICE) as? ClipboardManager)?.also { clip -> + Cache.get(activity, "crashdump")?.readLines()?.joinToString("\n").also { + clip.setPrimaryClip(ClipData.newPlainText("Otter logs", it)) + + Toast.makeText(activity, activity.getString(R.string.settings_crash_report_copied), Toast.LENGTH_SHORT).show() + } + } + } + } + "logout" -> { context?.let { context -> AlertDialog.Builder(context) diff --git a/app/src/main/res/drawable/bug.xml b/app/src/main/res/drawable/bug.xml new file mode 100644 index 0000000..4d83902 --- /dev/null +++ b/app/src/main/res/drawable/bug.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 8daf21a..0a8bb23 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -41,6 +41,9 @@ Version Licence Licence MIT + Copier les journaux de crash + Seuls les journaux d`Otter des 5 dernières minutes jusqu\'au crash seront collectés + Les journaux d\'événements ont été copiés dans votre presse-papier Déconnexion Artistes Albums diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b74bdb3..4a321c9 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -48,6 +48,9 @@ Version License MIT license + Copy crash logs + Only Otter\'s logs from the last 5 minutes up until the crash will be collected + Last crash report was copied to your clipboard Sign out Artists diff --git a/app/src/main/res/xml/settings.xml b/app/src/main/res/xml/settings.xml index c2d2373..800f906 100644 --- a/app/src/main/res/xml/settings.xml +++ b/app/src/main/res/xml/settings.xml @@ -40,6 +40,12 @@ android:summary="@string/settings_experiments_description" android:title="@string/settings_experiments" /> + +