[Android] Crash reporter: include the crash logcat as well and allow forcing a crash
Nicolas Pomepuy
git at videolan.org
Thu Sep 23 11:01:20 UTC 2021
vlc-android | branch: master | Nicolas Pomepuy <nicolas at videolabs.io> | Thu Sep 23 11:25:37 2021 +0200| [d01b401a63584d543bf32ade9c09301bce0fd61a] | committer: Nicolas Pomepuy
Crash reporter: include the crash logcat as well and allow forcing a crash
> https://code.videolan.org/videolan/vlc-android/commit/d01b401a63584d543bf32ade9c09301bce0fd61a
---
.../org/videolan/resources/util/VLCCrashHandler.kt | 150 ++++++++++++---------
.../src/org/videolan/vlc/PlaybackService.kt | 2 +
.../src/org/videolan/vlc/gui/SendCrashActivity.kt | 2 +-
3 files changed, 90 insertions(+), 64 deletions(-)
diff --git a/application/resources/src/main/java/org/videolan/resources/util/VLCCrashHandler.kt b/application/resources/src/main/java/org/videolan/resources/util/VLCCrashHandler.kt
index 05f016ca6..22a3b5ad6 100644
--- a/application/resources/src/main/java/org/videolan/resources/util/VLCCrashHandler.kt
+++ b/application/resources/src/main/java/org/videolan/resources/util/VLCCrashHandler.kt
@@ -38,76 +38,100 @@ class VLCCrashHandler : UncaughtExceptionHandler {
private val defaultUEH: UncaughtExceptionHandler = Thread.getDefaultUncaughtExceptionHandler()
override fun uncaughtException(thread: Thread, ex: Throwable) {
-
- val result = StringWriter()
- val printWriter = PrintWriter(result)
-
- // Inject some info about android version and the device, since google can't provide them in the developer console
- val trace = ex.stackTrace
- val trace2 = arrayOfNulls<StackTraceElement>(trace.size + 3)
- System.arraycopy(trace, 0, trace2, 0, trace.size)
- trace2[trace.size + 0] = StackTraceElement("Android", "MODEL", android.os.Build.MODEL, -1)
- trace2[trace.size + 1] = StackTraceElement("Android", "VERSION", android.os.Build.VERSION.RELEASE, -1)
- trace2[trace.size + 2] = StackTraceElement("Android", "FINGERPRINT", android.os.Build.FINGERPRINT, -1)
- ex.stackTrace = trace2
-
- ex.printStackTrace(printWriter)
- val stacktrace = result.toString()
- printWriter.close()
- Log.e(TAG, stacktrace)
-
- // Save the log on SD card if available
- if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
- writeLog(stacktrace, AppContextProvider.appContext.getExternalFilesDir(null)!!.absolutePath + "/vlc_crash")
- writeLogcat(AppContextProvider.appContext.getExternalFilesDir(null)!!.absolutePath + "/vlc_logcat")
- }
-
- defaultUEH.uncaughtException(thread, ex)
+ defaultUEH.uncaughtException(thread, saveLog(ex))
}
-
- private fun writeLog(log: String, name: String) {
- val timestamp = DateFormat.format("yyyyMMdd_kkmmss", System.currentTimeMillis())
- val filename = name + "_" + timestamp + ".log"
-
- val stream: FileOutputStream
- try {
- stream = FileOutputStream(filename)
- } catch (e: FileNotFoundException) {
- e.printStackTrace()
- return
+ companion object {
+ /**
+ * Saves a [Throwable] stack trace in a crash file after having some useful info appended.
+ * Also save a logcat file besides it
+ * /!\ Will trigger the crash reporter in beta!
+ * It's called by the [UncaughtExceptionHandler] but is useful in case we want to workaround a crash
+ * but still get the trace in the crash reporter
+ *
+ * @param ex: the [Throwable] to log
+ * @return the [Throwable] with versions appended
+ */
+ fun saveLog(ex: Throwable):Throwable {
+ val result = StringWriter()
+ val printWriter = PrintWriter(result)
+
+ // Inject some info about android version and the device, since google can't provide them in the developer console
+ val trace = ex.stackTrace
+ val trace2 = arrayOfNulls<StackTraceElement>(trace.size + 3)
+ System.arraycopy(trace, 0, trace2, 0, trace.size)
+ trace2[trace.size + 0] = StackTraceElement("Android", "MODEL", android.os.Build.MODEL, -1)
+ trace2[trace.size + 1] = StackTraceElement("Android", "VERSION", android.os.Build.VERSION.RELEASE, -1)
+ trace2[trace.size + 2] = StackTraceElement("Android", "FINGERPRINT", android.os.Build.FINGERPRINT, -1)
+ ex.stackTrace = trace2
+
+ ex.printStackTrace(printWriter)
+ val stacktrace = result.toString()
+ printWriter.close()
+ Log.e(TAG, stacktrace)
+
+ // Save the log on SD card if available
+ if (Environment.getExternalStorageState() == Environment.MEDIA_MOUNTED) {
+ writeLog(stacktrace, AppContextProvider.appContext.getExternalFilesDir(null)!!.absolutePath + "/vlc_crash")
+ writeLogcat(AppContextProvider.appContext.getExternalFilesDir(null)!!.absolutePath + "/vlc_logcat")
+ }
+ return ex
}
- val output = OutputStreamWriter(stream)
- val bw = BufferedWriter(output)
-
- val version = try {
- val pInfo: PackageInfo = AppContextProvider.appContext.packageManager.getPackageInfo(AppContextProvider.appContext.getPackageName(), 0)
- pInfo.versionName
- } catch (e: PackageManager.NameNotFoundException) {
- e.printStackTrace()
+ /**
+ * Writes a log in a file
+ *
+ * @param log: the log string to write
+ * @param name: the file name to write into
+ */
+ private fun writeLog(log: String, name: String) {
+ val timestamp = DateFormat.format("yyyyMMdd_kkmmss", System.currentTimeMillis())
+ val filename = name + "_" + timestamp + ".log"
+
+ val stream: FileOutputStream
+ try {
+ stream = FileOutputStream(filename)
+ } catch (e: FileNotFoundException) {
+ e.printStackTrace()
+ return
+ }
+
+ val output = OutputStreamWriter(stream)
+ val bw = BufferedWriter(output)
+
+ val version = try {
+ val pInfo: PackageInfo = AppContextProvider.appContext.packageManager.getPackageInfo(AppContextProvider.appContext.getPackageName(), 0)
+ pInfo.versionName
+ } catch (e: PackageManager.NameNotFoundException) {
+ e.printStackTrace()
+ }
+
+ try {
+ bw.write("App version: $version\r\n")
+ bw.write(log)
+ bw.newLine()
+ } catch (e: IOException) {
+ e.printStackTrace()
+ } finally {
+ CloseableUtils.close(bw)
+ CloseableUtils.close(output)
+ }
}
- try {
- bw.write("App version: $version\r\n")
- bw.write(log)
- bw.newLine()
- } catch (e: IOException) {
- e.printStackTrace()
- } finally {
- CloseableUtils.close(bw)
- CloseableUtils.close(output)
- }
- }
+ /**
+ * Write the current log in a file
+ *
+ * @param name: the file name to use to save the logcat
+ */
+ private fun writeLogcat(name: String) {
+ val timestamp = DateFormat.format("yyyyMMdd_kkmmss", System.currentTimeMillis())
+ val filename = name + "_" + timestamp + ".log"
+ try {
+ Logcat.writeLogcat(filename)
+ } catch (e: IOException) {
+ Log.e(TAG, "Cannot write logcat to disk")
+ }
- private fun writeLogcat(name: String) {
- val timestamp = DateFormat.format("yyyyMMdd_kkmmss", System.currentTimeMillis())
- val filename = name + "_" + timestamp + ".log"
- try {
- Logcat.writeLogcat(filename)
- } catch (e: IOException) {
- Log.e(TAG, "Cannot write logcat to disk")
}
-
}
}
diff --git a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
index a91f3eee1..307a29b93 100644
--- a/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
+++ b/application/vlc-android/src/org/videolan/vlc/PlaybackService.kt
@@ -66,6 +66,7 @@ import org.videolan.libvlc.util.AndroidUtil
import org.videolan.medialibrary.interfaces.Medialibrary
import org.videolan.medialibrary.interfaces.media.MediaWrapper
import org.videolan.resources.*
+import org.videolan.resources.util.VLCCrashHandler
import org.videolan.resources.util.getFromMl
import org.videolan.resources.util.launchForeground
import org.videolan.tools.*
@@ -1188,6 +1189,7 @@ class PlaybackService : MediaBrowserServiceCompat(), LifecycleOwner {
}
} catch (e: java.lang.NullPointerException) {
Log.e("PlaybackService", "Caught NullPointerException", e)
+ VLCCrashHandler.saveLog(e)
}
}
artworkToUriCache.clear()
diff --git a/application/vlc-android/src/org/videolan/vlc/gui/SendCrashActivity.kt b/application/vlc-android/src/org/videolan/vlc/gui/SendCrashActivity.kt
index d1059c7a9..e0b1bb735 100644
--- a/application/vlc-android/src/org/videolan/vlc/gui/SendCrashActivity.kt
+++ b/application/vlc-android/src/org/videolan/vlc/gui/SendCrashActivity.kt
@@ -99,7 +99,7 @@ class SendCrashActivity : AppCompatActivity(), DebugLogService.Client.Callback {
try {
val folder = AppContextProvider.appContext.getExternalFilesDir(null)?.absolutePath
File(folder).listFiles().forEach {
- if (it.isFile && it.name.contains("crash")) filesToAdd.add(it.path)
+ if (it.isFile && (it.name.contains("crash") || it.name.contains("logcat"))) filesToAdd.add(it.path)
}
} catch (exception: IOException) {
More information about the Android
mailing list