Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: Missing required view #1

Merged
merged 3 commits into from
Aug 9, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.dzeio.crashhandler

import android.app.Application
import android.content.Context
import android.content.Intent
import android.content.SharedPreferences
import android.os.Build
Expand All @@ -17,13 +18,14 @@ import kotlin.system.exitProcess
* the Crash Handler class, you can get an instance by using it's [Builder]
*/
class CrashHandler private constructor(
private val activity: Any,
private val application: Application?,
private val activity: Class<*>,
private val prefs: SharedPreferences?,
private val prefsKey: String?,
@StringRes
private val errorReporterCrashKey: Int?,
private var prefix: String? = null,
private var suffix: String? = null
private val prefix: String? = null,
private val suffix: String? = null
) {

private companion object {
Expand All @@ -34,10 +36,11 @@ class CrashHandler private constructor(
* Builder for the crash handler
*/
class Builder() {
private var application: Application? = null
private var prefs: SharedPreferences? = null
private var prefsKey: String? = null
private var errorReporterCrashKey: Int? = null
private var activity: Any? = ErrorActivity::class.java
private var activity: Class<*>? = ErrorActivity::class.java
private var prefix: String? = null
private var suffix: String? = null

Expand All @@ -48,7 +51,19 @@ class CrashHandler private constructor(
*
* @param activity the activity class to use
*/
fun withActivity(activity: Any): Builder {
fun withContext(context: Context): Builder {
this.application = context.applicationContext as Application?
return this
}

/**
* Change the Crash activity to with your own
*
* note: you can get the backtrace text by using `intent.getStringExtra("error")`
*
* @param activity the activity class to use
*/
fun withActivity(activity: Class<*>): Builder {
this.activity = activity
return this
}
Expand Down Expand Up @@ -114,7 +129,24 @@ class CrashHandler private constructor(
* build the Crash Handler
*/
fun build(): CrashHandler {
return CrashHandler(activity!!, prefs, prefsKey, errorReporterCrashKey, prefix, suffix)
return CrashHandler(application, activity!!, prefs, prefsKey, errorReporterCrashKey, prefix, suffix)
}
}

private var oldHandler: Thread.UncaughtExceptionHandler? = null

fun setup() {
if (application != null) {
this.setup(application)
}
}

/**
* Destroy the handler
*/
fun destroy() {
if (oldHandler != null) {
Thread.setDefaultUncaughtExceptionHandler(oldHandler)
}
}

Expand All @@ -126,7 +158,7 @@ class CrashHandler private constructor(
*/
fun setup(application: Application) {
// Application Error Handling
val oldHandler = Thread.getDefaultUncaughtExceptionHandler()
oldHandler = Thread.getDefaultUncaughtExceptionHandler()
Thread.setDefaultUncaughtExceptionHandler { paramThread, paramThrowable ->

// Log error to logcat if it wasn't done before has it can not be logged depending on the version
Expand Down Expand Up @@ -199,13 +231,13 @@ class CrashHandler private constructor(

data += suffix ?: ""

Log.i(TAG, "Starting ${(activity as Class<*>).name}")
Log.i(TAG, "Starting ${activity.name}")

// prepare the activity
val intent = Intent(application.applicationContext, activity)
val intent = Intent(application, activity)

// add flags so that it don't use the current Application context
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS)

// add the Data String
intent.putExtra("error", data)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,24 +5,26 @@ import android.content.ClipboardManager
import android.content.Context
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.dzeio.crashhandler.databinding.ActivityErrorBinding
import com.dzeio.crashhandler.databinding.CrashHandlerActivityErrorBinding

class ErrorActivity : AppCompatActivity() {

private lateinit var binding: ActivityErrorBinding
private lateinit var binding: CrashHandlerActivityErrorBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

binding = ActivityErrorBinding.inflate(layoutInflater)
binding = CrashHandlerActivityErrorBinding.inflate(layoutInflater)

setContentView(binding.root)

val data = intent.getStringExtra("error")

// put it in the textView
binding.errorText.text = data
binding.errorText.setTextIsSelectable(true)
binding.errorText.apply {
text = data
setTextIsSelectable(true)
}

// Handle the Quit button
binding.errorQuit.setOnClickListener {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"

tools:context=".ui.ErrorActivity"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">

Expand Down
File renamed without changes.
4 changes: 2 additions & 2 deletions app/build.gradle.kts → sample/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,8 @@ android {

dependencies {

implementation(project(":crashhandler"))

implementation(project(":library"))
// Material Design
implementation("com.google.android.material:material:1.6.1")

Expand Down
File renamed without changes.
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<activity android:name=".ui.ErrorActivity"
android:theme="@style/Theme.CrashHandler"
android:exported="false" />
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
package com.dzeio.crashhandlertest

import com.dzeio.crashhandler.CrashHandler
import com.dzeio.crashhandlertest.ui.ErrorActivity

class Application : android.app.Application() {
override fun onCreate() {
super.onCreate()

CrashHandler.Builder()
.withActivity(ErrorActivity::class.java)
.withContext(this)
.withPrefix("Pouet :D")
.withSuffix("WHYYYYY")
.build().setup(this)
.build().setup()
}

companion object {
const val TAG = "CrashHandlerTest"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.dzeio.crashhandlertest.ui

import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Process
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat
import com.dzeio.crashhandlertest.Application
import com.dzeio.crashhandlertest.databinding.ActivityErrorBinding
import kotlin.system.exitProcess

class ErrorActivity : AppCompatActivity() {

companion object {
const val TAG = "${Application.TAG}/ErrorActivity"
}

private lateinit var binding: ActivityErrorBinding

override fun onCreate(savedInstanceState: Bundle?) {
WindowCompat.setDecorFitsSystemWindows(window, false)
super.onCreate(savedInstanceState)

binding = ActivityErrorBinding.inflate(layoutInflater)
setContentView(binding.root)

val data = intent.getStringExtra("error")

// Get Application datas
val deviceToReport = if (Build.DEVICE.contains(Build.MANUFACTURER)) Build.DEVICE else "${Build.MANUFACTURER} ${Build.DEVICE}"

val reportText = """
Crash Report (Thread: ${intent?.getLongExtra("threadId", -1) ?: "unknown"})
on $deviceToReport (${Build.MODEL}) running Android ${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})

backtrace:

""".trimIndent() + data

// put it in the textView
binding.errorText.text = reportText

// Handle the Quit button
binding.errorQuit.setOnClickListener {
Process.killProcess(Process.myPid())
exitProcess(10)
}

// Handle the Email Button
binding.errorSubmitEmail.setOnClickListener {

// Create Intent
val intent = Intent(Intent.ACTION_SEND)
intent.data = Uri.parse("mailto:")
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_EMAIL, arrayOf("report.openhealth@dzeio.com"))
intent.putExtra(Intent.EXTRA_SUBJECT, "Error report for application crash")
intent.putExtra(Intent.EXTRA_TEXT, "Send Report Email\n$reportText")

try {
startActivity(Intent.createChooser(intent, "Send Report Email..."))
} catch (e: ActivityNotFoundException) {
Toast.makeText(this, "Not Email client found :(", Toast.LENGTH_LONG).show()
}
}

// Handle the GitHub Button
binding.errorSubmitGithub.setOnClickListener {

// Build URL
val url = "https://github.com/dzeiocom/OpenHealth/issues/new?title=Application Error&body=$reportText"

try {
startActivity(
Intent(Intent.ACTION_VIEW, Uri.parse(url))
)
} catch (e: ActivityNotFoundException) {
Toast.makeText(this, "No Web Browser found :(", Toast.LENGTH_LONG).show()
}
}
}
}
80 changes: 80 additions & 0 deletions sample/src/main/res/layout/activity_error.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"
android:id="@+id/linearLayout2"
android:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
android:id="@+id/textView3"
style="?textAppearanceHeadline5"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="blablabla"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/textView4"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="16dp"
android:text="blablabla2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" />

<ScrollView
android:id="@+id/scrollView2"
android:layout_width="0dp"
android:layout_height="0dp"
android:layout_marginTop="16dp"
android:layout_marginBottom="16dp"
app:layout_constraintBottom_toTopOf="@+id/error_submit_email"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView4">

<TextView
android:id="@+id/error_text"
android:layout_width="match_parent"
style="?textAppearanceCaption"
android:layout_height="wrap_content" />

</ScrollView>



<Button
android:id="@+id/error_submit_github"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Github"
android:layout_marginStart="16dp"
app:layout_constraintBaseline_toBaselineOf="@+id/error_submit_email"
app:layout_constraintStart_toStartOf="parent" />

<Button
android:id="@+id/error_submit_email"
android:layout_marginBottom="16dp"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:text="E-Mail"
app:layout_constraintBottom_toTopOf="@+id/error_quit"
app:layout_constraintEnd_toEndOf="parent" />


<Button
android:id="@+id/error_quit"
android:layout_width="wrap_content"
android:layout_height="0dp"
android:text="Quit"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
4 changes: 2 additions & 2 deletions settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -15,5 +15,5 @@ dependencyResolutionManagement {

rootProject.name = "Crash Handler"

include ':app'
include ':crashhandler'
include ':sample'
include ':library'