8 Commits

39 changed files with 286 additions and 363 deletions

3
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,3 @@
<!--
Thanks for your Pull Request, Please provide the related Issue using "Fix #0" or describe the change(s) you made.
-->

45
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,45 @@
# To get started with Dependabot version updates, you'll need to specify which
# package ecosystems to update and where the package manifests are located.
# Please see the documentation for all configuration options:
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
version: 2
updates:
- package-ecosystem: gradle
directory: "/"
schedule:
interval: daily
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-minor", "version-update:semver-patch"]
- package-ecosystem: gradle
directory: "/library"
schedule:
interval: daily
commit-message:
prefix: build
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-minor", "version-update:semver-patch"]
- package-ecosystem: gradle
directory: "/sample"
schedule:
interval: daily
commit-message:
prefix: build
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-minor", "version-update:semver-patch"]
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "daily"
commit-message:
prefix: build
ignore:
- dependency-name: "*"
update-types: ["version-update:semver-minor", "version-update:semver-patch"]

37
.github/scripts/gradlew_recursive.sh vendored Normal file
View File

@ -0,0 +1,37 @@
#!/bin/bash
# Copyright (C) 2020 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -xe
# Default Gradle settings are not optimal for Android builds, override them
# here to make the most out of the GitHub Actions build servers
GRADLE_OPTS="$GRADLE_OPTS -Xms4g -Xmx4g"
GRADLE_OPTS="$GRADLE_OPTS -XX:+HeapDumpOnOutOfMemoryError"
GRADLE_OPTS="$GRADLE_OPTS -Dorg.gradle.daemon=false"
GRADLE_OPTS="$GRADLE_OPTS -Dorg.gradle.workers.max=2"
GRADLE_OPTS="$GRADLE_OPTS -Dkotlin.incremental=false"
GRADLE_OPTS="$GRADLE_OPTS -Dkotlin.compiler.execution.strategy=in-process"
GRADLE_OPTS="$GRADLE_OPTS -Dfile.encoding=UTF-8"
export GRADLE_OPTS
# Crawl all gradlew files which indicate an Android project
# You may edit this if your repo has a different project structure
for GRADLEW in `find . -name "gradlew"` ; do
SAMPLE=$(dirname "${GRADLEW}")
# Tell Gradle that this is a CI environment and disable parallel compilation
bash "$GRADLEW" -p "$SAMPLE" -Pci --no-parallel --stacktrace $@
done

52
.github/workflows/build.yml vendored Normal file
View File

@ -0,0 +1,52 @@
# Copyright (C) 2020 The Android Open Source Project
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
name: Android CI
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'adopt'
cache: gradle
- name: Build project
run: |
chmod +x .github/scripts/gradlew_recursive.sh
.github/scripts/gradlew_recursive.sh assembleDebug
- name: Zip artifacts
run: zip -r assemble.zip . -i '**/build/*.apk' '**/build/*.aab' '**/build/*.aar' '**/build/*.so'
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: assemble
path: assemble.zip
- name: ktlint
uses: ScaCap/action-ktlint@master
with:
github_token: ${{ secrets.github_token }}
android: true
reporter: github-pr-review # Change reporter

View File

@ -4,7 +4,7 @@ buildscript {
mavenCentral() mavenCentral()
} }
dependencies { dependencies {
classpath("com.android.tools.build:gradle:7.2.2") classpath("com.android.tools.build:gradle:7.4.2")
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
@ -12,8 +12,8 @@ buildscript {
} }
plugins { plugins {
id("com.android.application") version "7.2.2" apply false id("com.android.application") version "7.4.2" apply false
id("com.android.library") version "7.2.2" apply false id("com.android.library") version "7.4.2" apply false
id("org.jetbrains.kotlin.android") version "1.7.0" apply false id("org.jetbrains.kotlin.android") version "1.7.0" apply false
} }

View File

@ -24,7 +24,7 @@ publishing {
} }
android { android {
namespace = "com.dzeio.crashhandler" namespace = "$group.$artifact"
compileSdk = 33 compileSdk = 33
buildToolsVersion = "33.0.0" buildToolsVersion = "33.0.0"
@ -35,7 +35,6 @@ android {
minCompileSdk = 21 minCompileSdk = 21
} }
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles("consumer-rules.pro") consumerProguardFiles("consumer-rules.pro")
} }
@ -77,5 +76,5 @@ android {
dependencies { dependencies {
// Necessary for the Activity (well to make it pretty :D) // Necessary for the Activity (well to make it pretty :D)
implementation("com.google.android.material:material:1.6.1") implementation("com.google.android.material:material:1.8.0")
} }

View File

@ -35,7 +35,7 @@ class CrashHandler private constructor(
/** /**
* Builder for the crash handler * Builder for the crash handler
*/ */
class Builder() { class Builder {
private var application: Application? = null private var application: Application? = null
private var prefs: SharedPreferences? = null private var prefs: SharedPreferences? = null
private var prefsKey: String? = null private var prefsKey: String? = null
@ -49,7 +49,7 @@ class CrashHandler private constructor(
* *
* note: you can get the backtrace text by using `intent.getStringExtra("error")` * note: you can get the backtrace text by using `intent.getStringExtra("error")`
* *
* @param activity the activity class to use * @param context the context class to use
*/ */
fun withContext(context: Context): Builder { fun withContext(context: Context): Builder {
this.application = context.applicationContext as Application? this.application = context.applicationContext as Application?
@ -80,7 +80,6 @@ class CrashHandler private constructor(
return this return this
} }
/** /**
* the key of the [SharedPreferences] you want to let the library handle * the key of the [SharedPreferences] you want to let the library handle
* *
@ -129,11 +128,19 @@ class CrashHandler private constructor(
* build the Crash Handler * build the Crash Handler
*/ */
fun build(): CrashHandler { fun build(): CrashHandler {
return CrashHandler(application, activity!!, prefs, prefsKey, errorReporterCrashKey, prefix, suffix) return CrashHandler(
application,
activity!!,
prefs,
prefsKey,
errorReporterCrashKey,
prefix,
suffix
)
} }
} }
private var oldHandler: Thread.UncaughtExceptionHandler? = null private var oldHandler: Thread.UncaughtExceptionHandler? = null
fun setup() { fun setup() {
if (application != null) { if (application != null) {
@ -180,16 +187,19 @@ class CrashHandler private constructor(
// add device informations // add device informations
val deviceToReport = val deviceToReport =
if (Build.DEVICE.contains(Build.MANUFACTURER)) Build.DEVICE else "${Build.MANUFACTURER} ${Build.DEVICE}" if (Build.DEVICE.contains(Build.MANUFACTURER)) {
data += "\n\non $deviceToReport (${Build.MODEL}) running Android ${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})" Build.DEVICE
} else {
"${Build.MANUFACTURER} ${Build.DEVICE}"
}
data += "\n\non $deviceToReport (${Build.MODEL}) running Android ${Build.VERSION.RELEASE} (${Build.VERSION.SDK_INT})"
// add the current time to it // add the current time to it
data += "\n\nCrash happened at ${Date(now)}" data += "\n\nCrash happened at ${Date(now)}"
// if lib as access to the preferences store // if lib as access to the preferences store
if (prefs != null && prefsKey != null) { if (prefs != null && prefsKey != null) {
// get the last Crash // get the last Crash
val lastCrash = prefs.getLong(prefsKey, 0L) val lastCrash = prefs.getLong(prefsKey, 0L)
@ -198,7 +208,6 @@ class CrashHandler private constructor(
// if a crash already happened just before it means the Error Activity crashed lul // if a crash already happened just before it means the Error Activity crashed lul
if (lastCrash >= now - 1000) { if (lastCrash >= now - 1000) {
// log it :D // log it :D
Log.e( Log.e(
TAG, TAG,
@ -218,7 +227,7 @@ class CrashHandler private constructor(
} }
// update the store // update the store
prefs.edit().putLong(prefsKey, now).apply() prefs.edit().putLong(prefsKey, now).commit()
} }
Log.i(TAG, "Collecting Error") Log.i(TAG, "Collecting Error")
@ -237,7 +246,12 @@ class CrashHandler private constructor(
val intent = Intent(application, activity) val intent = Intent(application, activity)
// add flags so that it don't use the current Application context // add flags so that it don't use the current Application context
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) 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 // add the Data String
intent.putExtra("error", data) intent.putExtra("error", data)
@ -251,6 +265,4 @@ class CrashHandler private constructor(
exitProcess(10) exitProcess(10)
} }
} }
}
}

View File

@ -20,7 +20,10 @@ android {
buildTypes { buildTypes {
release { release {
isMinifyEnabled = true isMinifyEnabled = true
proguardFiles(getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
)
} }
} }
@ -31,7 +34,7 @@ android {
kotlinOptions { kotlinOptions {
jvmTarget = "11" jvmTarget = "11"
} }
buildFeatures { buildFeatures {
viewBinding = true viewBinding = true
} }
@ -40,10 +43,13 @@ android {
dependencies { dependencies {
implementation(project(":library")) implementation(project(":library"))
// Material Design // Material Design
implementation("com.google.android.material:material:1.6.1") implementation("com.google.android.material:material:1.8.0")
// Navigation because I don't want to maintain basic transactions and shit // Navigation because I don't want to maintain basic transactions and shit
implementation("androidx.navigation:navigation-fragment-ktx:2.5.1") implementation("androidx.navigation:navigation-fragment-ktx:2.5.3")
}
// preferences
implementation("androidx.preference:preference-ktx:1.2.0")
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@ -1,5 +1,6 @@
package com.dzeio.crashhandlertest package com.dzeio.crashhandlertest
import androidx.preference.PreferenceManager
import com.dzeio.crashhandler.CrashHandler import com.dzeio.crashhandler.CrashHandler
import com.dzeio.crashhandlertest.ui.ErrorActivity import com.dzeio.crashhandlertest.ui.ErrorActivity
@ -7,15 +8,25 @@ class Application : android.app.Application() {
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
// get the device Preference store
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
// create the Crash Handler
CrashHandler.Builder() CrashHandler.Builder()
.withActivity(ErrorActivity::class.java) // need the application context to run
.withContext(this) .withContext(this)
.withPrefix("Pouet :D") // define a custom activity to use
.withActivity(ErrorActivity::class.java)
// define the preferenceManager to be able to handle crash in a custom Activity and to have the previous crash date in the logs
.withPrefs(prefs)
.withPrefsKey("com.dzeio.crashhandler.key")
// a Prefix to add at the beginning the crash message
.withPrefix(
"POKEMON"
)
// a Suffix to add at the end of the crash message
.withSuffix("WHYYYYY") .withSuffix("WHYYYYY")
// build & start the module
.build().setup() .build().setup()
} }
}
companion object {
const val TAG = "CrashHandlerTest"
}
}

View File

@ -3,46 +3,38 @@ package com.dzeio.crashhandlertest.ui
import android.content.ActivityNotFoundException import android.content.ActivityNotFoundException
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Process import android.os.Process
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import com.dzeio.crashhandlertest.Application
import com.dzeio.crashhandlertest.databinding.ActivityErrorBinding import com.dzeio.crashhandlertest.databinding.ActivityErrorBinding
import kotlin.system.exitProcess import kotlin.system.exitProcess
/**
* Example Activity for a custom ErrorActivity
*
* note: try to keep the complexity of this class as low as possible
* to make sure this will always load
*/
class ErrorActivity : AppCompatActivity() { class ErrorActivity : AppCompatActivity() {
companion object { // the view binding
const val TAG = "${Application.TAG}/ErrorActivity"
}
private lateinit var binding: ActivityErrorBinding private lateinit var binding: ActivityErrorBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
WindowCompat.setDecorFitsSystemWindows(window, false) WindowCompat.setDecorFitsSystemWindows(window, false)
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// inflate the view
binding = ActivityErrorBinding.inflate(layoutInflater) binding = ActivityErrorBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
// get the error string from the library
val data = intent.getStringExtra("error") 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 // put it in the textView
binding.errorText.text = reportText binding.errorText.text = data
// Handle the Quit button // Handle the Quit button
binding.errorQuit.setOnClickListener { binding.errorQuit.setOnClickListener {
@ -52,15 +44,14 @@ class ErrorActivity : AppCompatActivity() {
// Handle the Email Button // Handle the Email Button
binding.errorSubmitEmail.setOnClickListener { binding.errorSubmitEmail.setOnClickListener {
// Create Intent // Create Intent
val intent = Intent(Intent.ACTION_SEND) val intent = Intent(Intent.ACTION_SEND)
intent.data = Uri.parse("mailto:") intent.setDataAndType(Uri.parse("mailto:"), "text/plain")
intent.type = "text/plain"
intent.putExtra(Intent.EXTRA_EMAIL, arrayOf("report.openhealth@dzeio.com")) intent.putExtra(Intent.EXTRA_EMAIL, arrayOf("report.openhealth@dzeio.com"))
intent.putExtra(Intent.EXTRA_SUBJECT, "Error report for application crash") intent.putExtra(Intent.EXTRA_SUBJECT, "Error report for application crash")
intent.putExtra(Intent.EXTRA_TEXT, "Send Report Email\n$reportText") intent.putExtra(Intent.EXTRA_TEXT, "Send Report Email\n$data")
// send intent
try { try {
startActivity(Intent.createChooser(intent, "Send Report Email...")) startActivity(Intent.createChooser(intent, "Send Report Email..."))
} catch (e: ActivityNotFoundException) { } catch (e: ActivityNotFoundException) {
@ -70,10 +61,11 @@ class ErrorActivity : AppCompatActivity() {
// Handle the GitHub Button // Handle the GitHub Button
binding.errorSubmitGithub.setOnClickListener { binding.errorSubmitGithub.setOnClickListener {
// Build URL // Build URL
val url = "https://github.com/dzeiocom/OpenHealth/issues/new?title=Application Error&body=$reportText" val title = "Application Error"
val url = "https://github.com/dzeiocom/OpenHealth/issues/new?title=$title&body=$data"
// send intent
try { try {
startActivity( startActivity(
Intent(Intent.ACTION_VIEW, Uri.parse(url)) Intent(Intent.ACTION_VIEW, Uri.parse(url))

View File

@ -3,8 +3,12 @@ package com.dzeio.crashhandlertest.ui
import android.os.Bundle import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.WindowCompat import androidx.core.view.WindowCompat
import com.dzeio.crashhandlertest.R
import com.dzeio.crashhandlertest.databinding.ActivityMainBinding import com.dzeio.crashhandlertest.databinding.ActivityMainBinding
/**
*
*/
class MainActivity : AppCompatActivity() { class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding private lateinit var binding: ActivityMainBinding
@ -15,5 +19,10 @@ class MainActivity : AppCompatActivity() {
binding = ActivityMainBinding.inflate(layoutInflater) binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
binding.buttonFirst.setOnClickListener {
// DIE
throw Exception(getString(R.string.error_message))
}
} }
} }

View File

@ -1,44 +0,0 @@
package com.dzeio.crashhandlertest.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import com.dzeio.crashhandlertest.databinding.FragmentMainBinding
/**
* A simple [Fragment] subclass as the default destination in the navigation.
*/
class MainFragment : Fragment() {
private var _binding: FragmentMainBinding? = null
// This property is only valid between onCreateView and
// onDestroyView.
private val binding get() = _binding!!
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
_binding = FragmentMainBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.buttonFirst.setOnClickListener {
// DIE
throw Exception("POKÉMON :D")
}
}
override fun onDestroyView() {
super.onDestroyView()
_binding = null
}
}

View File

@ -1,30 +0,0 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

View File

@ -1,170 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

View File

@ -0,0 +1,23 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="48"
android:viewportHeight="48"
android:autoMirrored="true">
<group android:scaleX="0.96130437"
android:scaleY="0.96130437"
android:translateX="0.9286957"
android:translateY="0.9286957">
<group android:scaleX="0.99"
android:scaleY="0.99"
android:translateX="0.24"
android:translateY="0.24">
<group android:scaleX="0.495"
android:scaleY="0.495"
android:translateX="12.12"
android:translateY="12.12">
<path android:fillColor="#FF4CAF50" android:pathData="M13.05,31.9q0.6,0 1.05,-0.45 0.45,-0.45 0.45,-1.05 0,-0.6 -0.45,-1.05 -0.45,-0.45 -1.05,-0.45 -0.6,0 -1.05,0.45 -0.45,0.45 -0.45,1.05 0,0.6 0.45,1.05 0.45,0.45 1.05,0.45ZM11.55,25.4h3v-9.55h-3ZM20.5,29.4h15.95v-3L20.5,26.4ZM20.5,20.85h15.95v-3L20.5,17.85ZM6.6,40q-1.2,0 -2.1,-0.9 -0.9,-0.9 -0.9,-2.1L3.6,11q0,-1.2 0.9,-2.1 0.9,-0.9 2.1,-0.9h34.8q1.2,0 2.1,0.9 0.9,0.9 0.9,2.1v26q0,1.2 -0.9,2.1 -0.9,0.9 -2.1,0.9Z"/>
</group>
</group>
</group>
</vector>

View File

@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
android:id="@+id/linearLayout2" android:id="@+id/linearLayout2"
android:layout_width="match_parent" android:layout_width="match_parent"
@ -12,7 +11,8 @@
style="?textAppearanceHeadline5" style="?textAppearanceHeadline5"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="blablabla" android:textAlignment="center"
android:text="@string/crash_handler_page_title"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
@ -22,7 +22,8 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:text="blablabla2" android:textAlignment="center"
android:text="@string/crash_handler_page_subtitle"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView3" /> app:layout_constraintTop_toBottomOf="@+id/textView3" />
@ -42,7 +43,8 @@
android:id="@+id/error_text" android:id="@+id/error_text"
android:layout_width="match_parent" android:layout_width="match_parent"
style="?textAppearanceCaption" style="?textAppearanceCaption"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
android:textIsSelectable="true" />
</ScrollView> </ScrollView>
@ -52,7 +54,7 @@
android:id="@+id/error_submit_github" android:id="@+id/error_submit_github"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:text="Github" android:text="@string/github"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
app:layout_constraintBaseline_toBaselineOf="@+id/error_submit_email" app:layout_constraintBaseline_toBaselineOf="@+id/error_submit_email"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />
@ -63,7 +65,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginEnd="16dp" android:layout_marginEnd="16dp"
android:text="E-Mail" android:text="@string/e_mail"
app:layout_constraintBottom_toTopOf="@+id/error_quit" app:layout_constraintBottom_toTopOf="@+id/error_quit"
app:layout_constraintEnd_toEndOf="parent" /> app:layout_constraintEnd_toEndOf="parent" />
@ -72,7 +74,7 @@
android:id="@+id/error_quit" android:id="@+id/error_quit"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="0dp" android:layout_height="0dp"
android:text="Quit" android:text="@string/quit"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />

View File

@ -1,23 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
tools:context=".ui.MainActivity"> tools:context=".ui.MainActivity"
android:padding="16dp">
<androidx.fragment.app.FragmentContainerView <Button
android:id="@+id/fragment" android:id="@+id/button_first"
android:name="androidx.navigation.fragment.NavHostFragment" android:layout_width="wrap_content"
android:layout_marginTop="?attr/actionBarSize" android:layout_height="wrap_content"
android:layout_width="match_parent" android:text="@string/crash_app"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent" />
app:navGraph="@navigation/nav_graph" />
</androidx.coordinatorlayout.widget.CoordinatorLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,21 +0,0 @@
<?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:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ui.MainFragment"
android:padding="16dp">
<Button
android:id="@+id/button_first"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/crash_app"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android"> <adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" /> <background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground" /> <foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon> </adaptive-icon>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@color/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 830 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation 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:id="@+id/nav_graph"
app:startDestination="@id/MainFragment">
<fragment
android:id="@+id/MainFragment"
android:name="com.dzeio.crashhandlertest.ui.MainFragment"
android:label="@string/first_fragment_label"
tools:layout="@layout/fragment_main"/>
</navigation>

View File

@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="ic_launcher_background">#FFFFFF</color>
</resources>

View File

@ -1,9 +1,10 @@
<resources> <resources>
<string name="app_name" translatable="false">Crash Handler</string> <string name="app_name" translatable="false">Crash Handler</string>
<string name="title_activity_main" translatable="false">MainActivity</string>
<!-- Strings used for fragments for navigation -->
<string name="first_fragment_label" translatable="false">First Fragment</string>
<string name="second_fragment_label" translatable="false">Second Fragment</string>
<string name="crash_app" translatable="false">Crash app</string> <string name="crash_app" translatable="false">Crash app</string>
<string name="error_message" translatable="false">I am an error</string>
<string name="crash_handler_page_title" translatable="false">Crash Handler page title</string>
<string name="crash_handler_page_subtitle" translatable="false">crash handler page subtitle</string>
<string name="github" translatable="false">Github</string>
<string name="e_mail" translatable="false">E-Mail</string>
<string name="quit" translatable="false">Quit</string>
</resources> </resources>