Skip to content

Commit

Permalink
feat: report crashes to Crashlytics
Browse files Browse the repository at this point in the history
  • Loading branch information
ianatha committed Oct 30, 2023
1 parent 468188a commit 27da6ba
Show file tree
Hide file tree
Showing 5 changed files with 51 additions and 122 deletions.
9 changes: 9 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id("com.google.gms.google-services")
id("com.google.firebase.crashlytics")
}

android {
Expand Down Expand Up @@ -50,6 +52,12 @@ android {
}

dependencies {
implementation(platform("com.google.firebase:firebase-bom:32.4.1"))
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.firebase:firebase-crashlytics")
implementation("com.google.firebase:firebase-analytics")
implementation("com.google.android.gms:play-services-tagmanager:18.0.4")

implementation("org.antlr:antlr4-runtime:4.13.1")
implementation("com.google.guava:guava:29.0-jre")
implementation("it.unimi.dsi:fastutil:8.4.0")
Expand Down Expand Up @@ -77,6 +85,7 @@ dependencies {
implementation("androidx.compose.ui:ui-graphics")
implementation("androidx.compose.ui:ui-tooling-preview")
implementation("androidx.compose.material3:material3")
implementation("com.google.android.gms:play-services-measurement-api:21.4.0")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
Expand Down
29 changes: 29 additions & 0 deletions app/google-services.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
{
"project_info": {
"project_number": "458627144363",
"project_id": "bababasic-c2bc3",
"storage_bucket": "bababasic-c2bc3.appspot.com"
},
"client": [
{
"client_info": {
"mobilesdk_app_id": "1:458627144363:android:5ff36b4b952a95e80df5ee",
"android_client_info": {
"package_name": "io.atha.quickbasic"
}
},
"oauth_client": [],
"api_key": [
{
"current_key": "AIzaSyC0Tr1knhq1PLNE3NPoPxiBKydmCdjlHRs"
}
],
"services": {
"appinvite_service": {
"other_platform_oauth_client": []
}
}
}
],
"configuration_version": "1"
}
127 changes: 5 additions & 122 deletions app/src/main/java/io/atha/quickbasic/CrashHandler.kt
Original file line number Diff line number Diff line change
@@ -1,61 +1,25 @@
/*
* sora-editor - the awesome code editor for Android
* https://github.com/Rosemoe/sora-editor
* Copyright (C) 2020-2023 Rosemoe
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
* USA
*
* Please contact Rosemoe by email [email protected] if you need
* additional information or have any questions
*/
package io.atha.quickbasic

import android.annotation.SuppressLint
import android.content.Context
import android.content.pm.PackageManager
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.util.Log
import android.widget.Toast
import java.io.PrintWriter
import java.io.StringWriter
import java.io.Writer
import java.text.SimpleDateFormat
import java.util.Arrays
import java.util.Date
import com.google.firebase.crashlytics.ktx.crashlytics
import com.google.firebase.ktx.Firebase

/**
* CrashHandler handles uncaught exceptions
* And force the main thread continue to work
*
* @author Rosemoe
*/
class CrashHandler private constructor() : Thread.UncaughtExceptionHandler {
private val handler = Handler(Looper.getMainLooper())
private var context: Context? = null
private val info: MutableMap<String, String> = HashMap()

fun init(context: Context) {
this.context = context.applicationContext
collectDeviceInfo(this.context)
Thread.setDefaultUncaughtExceptionHandler(this)
}

override fun uncaughtException(thread: Thread, ex: Throwable) {
saveCrashInfo(thread.name, ex)
Firebase.crashlytics.recordException(ex)

handler.post {
Toast.makeText(
context,
Expand All @@ -70,7 +34,6 @@ class CrashHandler private constructor() : Thread.UncaughtExceptionHandler {
Looper.loop()
return // Quit loop if no exception
} catch (t: Throwable) {
saveCrashInfo(thread.name, t)
handler.post {
Toast.makeText(
context,
Expand All @@ -83,87 +46,7 @@ class CrashHandler private constructor() : Thread.UncaughtExceptionHandler {
}
}

fun collectDeviceInfo(ctx: Context?) {
try {
val pm = ctx!!.packageManager
val pi = pm.getPackageInfo(ctx.packageName, PackageManager.GET_ACTIVITIES)
if (pi != null) {
val versionName = if (pi.versionName == null) "null" else pi.versionName
@Suppress("DEPRECATION") val versionCode = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
pi.longVersionCode.toString()
} else {
pi.versionCode.toString()
}
info["versionName"] = versionName
info["versionCode"] = versionCode
}
} catch (e: PackageManager.NameNotFoundException) {
Log.e(LOG_TAG, "an error occurred while collecting package info", e)
}
var fields = Build::class.java.declaredFields
for (field in fields) {
try {
field.isAccessible = true
val obj = field[null]
if (obj is Array<*> && obj.isArrayOf<String>()) {
info[field.name] = Arrays.toString(obj as Array<String?>)
} else {
info[field.name] = obj.toString()
}
} catch (e: Exception) {
Log.e(LOG_TAG, "an error occurred while collecting crash info", e)
}
}
fields = Build.VERSION::class.java.declaredFields
for (field in fields) {
try {
field.isAccessible = true
val obj = field[null]
if (obj is Array<*> && obj.isArrayOf<String>()) {
info[field.name] = Arrays.toString(obj as Array<String?>)
} else {
info[field.name] = obj.toString()
}
} catch (e: Exception) {
Log.e(LOG_TAG, "an error occurred while collecting crash info", e)
}
}
}

private fun saveCrashInfo(threadName: String, ex: Throwable) {
val sb = StringBuilder()
val timestamp = System.currentTimeMillis()
sb.append("Crash at ").append(timestamp).append("(timestamp) in thread named '")
.append(threadName).append("'\n")
sb.append("Local date and time:")
.append(SimpleDateFormat.getDateTimeInstance().format(Date(timestamp))).append('\n')
info.forEach { (key, value) ->
sb.append(key).append("=").append(value).append("\n")
}
val writer: Writer = StringWriter()
val printWriter = PrintWriter(writer)
ex.printStackTrace(printWriter)
var cause = ex.cause
while (cause != null) {
cause.printStackTrace(printWriter)
cause = cause.cause
}
printWriter.close()
val result = writer.toString()
sb.append(result).append('\n')
try {
Log.e(LOG_TAG, sb.toString())
val fos = context!!.openFileOutput("crash-journal.log", Context.MODE_APPEND)
fos.write(sb.toString().toByteArray())
fos.close()
} catch (e: Exception) {
Log.e(LOG_TAG, "an error occurred while writing file...", e)
}
}

companion object {
const val LOG_TAG = "CrashHandler"

@SuppressLint("StaticFieldLeak")
val INSTANCE = CrashHandler()
}
Expand Down
6 changes: 6 additions & 0 deletions app/src/main/java/io/atha/quickbasic/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts.GetContent
import androidx.annotation.RequiresApi
import androidx.appcompat.app.AppCompatActivity
import com.google.firebase.analytics.FirebaseAnalytics
import com.google.firebase.analytics.ktx.analytics
import com.google.firebase.analytics.ktx.logEvent
import com.google.firebase.ktx.Firebase
import io.atha.quickbasic.databinding.ActivityMainBinding
import io.github.rosemoe.sora.event.ContentChangeEvent
import io.github.rosemoe.sora.event.EditorKeyEvent
Expand Down Expand Up @@ -98,6 +102,7 @@ import java.util.stream.Collectors


class MainActivity : AppCompatActivity() {
private lateinit var firebaseAnalytics: FirebaseAnalytics
private lateinit var binding: ActivityMainBinding
private lateinit var searchMenu: PopupMenu
private var searchOptions = SearchOptions(false, false)
Expand All @@ -106,6 +111,7 @@ class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
firebaseAnalytics = Firebase.analytics
CrashHandler.INSTANCE.init(this)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
Expand Down
2 changes: 2 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,6 @@
plugins {
id("com.android.application") version "8.1.2" apply false
id("org.jetbrains.kotlin.android") version "1.8.10" apply false
id("com.google.gms.google-services") version "4.4.0" apply false
id("com.google.firebase.crashlytics") version "2.9.9" apply false
}

0 comments on commit 27da6ba

Please sign in to comment.