Merge branch 'main' into crowd_reliability

This commit is contained in:
Matthias Urhahn
2023-02-02 14:57:04 +01:00
committed by GitHub
28 changed files with 166 additions and 70 deletions
+6 -1
View File
@@ -21,6 +21,10 @@ android {
buildConfigField("String", "APPLICATION_ID", "\"${ProjectConfig.packageName}\"")
buildConfigField("String", "GITSHA", "\"${lastCommitHash()}\"")
buildConfigField("String", "BUILDTIME", "\"${buildTime()}\"")
manifestPlaceholders["bugsnagApiKey"] = getBugSnagApiKey(
File(System.getProperty("user.home"), ".appconfig/${ProjectConfig.packageName}/bugsnag.properties")
) ?: "bugsnag_apikey_placeholder"
}
buildFeatures {
@@ -95,6 +99,7 @@ dependencies {
addTesting()
implementation("com.bugsnag:bugsnag-android:5.9.2")
"gplayImplementation"("com.bugsnag:bugsnag-android:5.9.2")
"gplayImplementation"("com.getkeepsafe.relinker:relinker:1.4.3")
}
+4
View File
@@ -0,0 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest>
</manifest>
@@ -0,0 +1,17 @@
package eu.darken.capod.debug.autoreport
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import eu.darken.capod.common.debug.autoreport.AutomaticBugReporter
import eu.darken.capod.debug.autoreport.FossAutoReporting
import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@Module
abstract class AutoReportingModule {
@Binds
@Singleton
abstract fun autoreporting(foss: FossAutoReporting): AutomaticBugReporter
}
@@ -0,0 +1,17 @@
package eu.darken.capod.debug.autoreport
import android.app.Application
import eu.darken.capod.common.debug.autoreport.AutomaticBugReporter
import javax.inject.Inject
import javax.inject.Singleton
@Singleton
class FossAutoReporting @Inject constructor() : AutomaticBugReporter {
override fun setup(application: Application) {
// NOOP
}
override fun notify(throwable: Throwable) {
throw IllegalStateException("Who initliazed this? Without setup no calls to here!")
}
}
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<application>
<meta-data
android:name="com.bugsnag.android.API_KEY"
android:value="${bugsnagApiKey}" />
</application>
</manifest>
@@ -0,0 +1,16 @@
package eu.darken.capod.debug.autoreport
import dagger.Binds
import dagger.Module
import dagger.hilt.InstallIn
import dagger.hilt.components.SingletonComponent
import eu.darken.capod.common.debug.autoreport.AutomaticBugReporter
import javax.inject.Singleton
@InstallIn(SingletonComponent::class)
@Module
abstract class AutoReportingModule {
@Binds
@Singleton
abstract fun autoreporting(foss: GplayAutoReporting): AutomaticBugReporter
}
@@ -1,4 +1,4 @@
package eu.darken.capod.common.debug.autoreport.bugsnag
package eu.darken.capod.debug.autoreport
import android.annotation.SuppressLint
import android.content.Context
@@ -7,7 +7,7 @@ import com.bugsnag.android.Event
import com.bugsnag.android.OnErrorCallback
import dagger.hilt.android.qualifiers.ApplicationContext
import eu.darken.capod.common.BuildConfigWrap
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.DebugSettings
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
import eu.darken.capod.common.debug.logging.asLog
import eu.darken.capod.common.debug.logging.log
@@ -1,4 +1,4 @@
package eu.darken.capod.common.debug.autoreport.bugsnag
package eu.darken.capod.debug.autoreport
import com.bugsnag.android.Event
import eu.darken.capod.common.debug.logging.Logging
@@ -1,15 +1,16 @@
package eu.darken.capod.common.debug.autoreport
package eu.darken.capod.debug.autoreport
import android.app.Application
import android.content.Context
import com.bugsnag.android.Bugsnag
import com.bugsnag.android.Configuration
import com.getkeepsafe.relinker.ReLinker
import dagger.hilt.android.qualifiers.ApplicationContext
import eu.darken.capod.common.BuildConfigWrap
import eu.darken.capod.common.InstallId
import eu.darken.capod.common.debug.Bugs
import eu.darken.capod.common.debug.autoreport.bugsnag.BugsnagErrorHandler
import eu.darken.capod.common.debug.autoreport.bugsnag.BugsnagLogger
import eu.darken.capod.common.debug.autoreport.bugsnag.NOPBugsnagErrorHandler
import eu.darken.capod.common.debug.DebugSettings
import eu.darken.capod.common.debug.autoreport.AutomaticBugReporter
import eu.darken.capod.common.debug.logging.Logging
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.debug.logging.logTag
@@ -18,19 +19,25 @@ import javax.inject.Provider
import javax.inject.Singleton
@Singleton
class AutoReporting @Inject constructor(
class GplayAutoReporting @Inject constructor(
@ApplicationContext private val context: Context,
private val debugSettings: DebugSettings,
private val installId: InstallId,
private val bugsnagLogger: Provider<BugsnagLogger>,
private val bugsnagErrorHandler: Provider<BugsnagErrorHandler>,
private val nopBugsnagErrorHandler: Provider<NOPBugsnagErrorHandler>,
) {
) : AutomaticBugReporter {
fun setup() {
override fun setup(application: Application) {
val isEnabled = debugSettings.isAutoReportingEnabled.value
log(TAG) { "setup(): isEnabled=$isEnabled" }
if (!isEnabled) return
ReLinker
.log { message -> log(TAG) { "ReLinker: $message" } }
.loadLibrary(application, "bugsnag-plugin-android-anr")
try {
val bugsnagConfig = Configuration.load(context).apply {
if (debugSettings.isAutoReportingEnabled.value) {
@@ -48,13 +55,18 @@ class AutoReporting @Inject constructor(
}
Bugsnag.start(context, bugsnagConfig)
Bugs.ready = true
Bugs.reporter = this
} catch (e: IllegalStateException) {
log(TAG) { "Bugsnag API Key not configured." }
}
}
override fun notify(throwable: Throwable) {
Bugsnag.notify(throwable)
}
companion object {
private val TAG = logTag("Debug", "AutoReport")
}
}
@@ -1,4 +1,4 @@
package eu.darken.capod.common.debug.autoreport.bugsnag
package eu.darken.capod.debug.autoreport
import com.bugsnag.android.Event
import com.bugsnag.android.OnErrorCallback
@@ -2,7 +2,7 @@ package eu.darken.capod.common.bluetooth
import dagger.Reusable
import eu.darken.capod.common.SystemClockWrap
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.DebugSettings
import java.time.Instant
import javax.inject.Inject
import kotlin.random.Random
@@ -1,13 +1,13 @@
package eu.darken.capod.common.debug
import com.bugsnag.android.Bugsnag
import eu.darken.capod.common.debug.autoreport.AutomaticBugReporter
import eu.darken.capod.common.debug.logging.Logging.Priority.*
import eu.darken.capod.common.debug.logging.asLog
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.debug.logging.logTag
object Bugs {
var ready = false
var reporter: AutomaticBugReporter? = null
fun report(
tag: String,
message: String,
@@ -16,11 +16,9 @@ object Bugs {
log(TAG, VERBOSE) { "Reporting $exception" }
log(tag, ERROR) { "$message\n${exception.asLog()}" }
if (!ready) {
reporter?.notify(exception) ?: run {
log(TAG, WARN) { "Bug tracking not initialized yet." }
return
}
Bugsnag.notify(exception)
}
private val TAG = logTag("Bugs")
@@ -1,4 +1,4 @@
package eu.darken.capod.common.debug.autoreport
package eu.darken.capod.common.debug
import android.content.Context
import android.content.SharedPreferences
@@ -0,0 +1,10 @@
package eu.darken.capod.common.debug.autoreport
import android.app.Application
interface AutomaticBugReporter {
fun setup(application: Application)
fun notify(throwable: Throwable)
}
@@ -6,7 +6,7 @@ import androidx.preference.PreferenceDataStore
import com.squareup.moshi.Moshi
import dagger.hilt.android.qualifiers.ApplicationContext
import eu.darken.capod.common.bluetooth.ScannerMode
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.DebugSettings
import eu.darken.capod.common.preferences.PreferenceStoreMapper
import eu.darken.capod.common.preferences.Settings
import eu.darken.capod.common.preferences.createFlowPreference
@@ -6,7 +6,7 @@ import eu.darken.capod.common.bluetooth.BleScanner
import eu.darken.capod.common.bluetooth.BluetoothManager2
import eu.darken.capod.common.bluetooth.ScannerMode
import eu.darken.capod.common.coroutine.AppScope
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.DebugSettings
import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
import eu.darken.capod.common.debug.logging.Logging.Priority.WARN
import eu.darken.capod.common.debug.logging.asLog
+7 -9
View File
@@ -6,7 +6,6 @@ plugins {
}
apply(plugin = "dagger.hilt.android.plugin")
apply(plugin = "androidx.navigation.safeargs.kotlin")
apply(plugin = "com.bugsnag.android.gradle")
android {
compileSdk = ProjectConfig.compileSdk
@@ -24,10 +23,6 @@ android {
buildConfigField("String", "GITSHA", "\"${lastCommitHash()}\"")
buildConfigField("String", "BUILDTIME", "\"${buildTime()}\"")
manifestPlaceholders["bugsnagApiKey"] = getBugSnagApiKey(
File(System.getProperty("user.home"), ".appconfig/${ProjectConfig.packageName}/bugsnag.properties")
) ?: "fake"
}
signingConfigs {
@@ -49,9 +44,12 @@ android {
create("gplay") {
dimension = "version"
signingConfig = signingConfigs["releaseGplay"]
extra["useBugsnag"] = true
}
}
setupBugsnagPlugin()
buildTypes {
val customProguardRules = fileTree(File("../proguard")) {
include("*.pro")
@@ -92,7 +90,7 @@ android {
if (listOf("release", "beta").any { variantName.toLowerCase().contains(it) }) {
val outputFileName = ProjectConfig.packageName + "-WEAROS" +
"-v${defaultConfig.versionName}-${defaultConfig.versionCode}" +
"-${variantName.toUpperCase()}-${lastCommitHash()}.apk"
"-${variantName.toUpperCase()}.apk"
variantOutputImpl.outputFileName = outputFileName
}
@@ -138,9 +136,9 @@ dependencies {
addTesting()
implementation("com.bugsnag:bugsnag-android:5.9.2")
implementation("com.getkeepsafe.relinker:relinker:1.4.3")
implementation("androidx.wear:wear:1.2.0")
implementation("androidx.wear.tiles:tiles-material:1.1.0")
"gplayImplementation"("com.bugsnag:bugsnag-android:5.9.2")
"gplayImplementation"("com.getkeepsafe.relinker:relinker:1.4.3")
}
-4
View File
@@ -39,10 +39,6 @@
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
<meta-data
android:name="com.bugsnag.android.API_KEY"
android:value="${bugsnagApiKey}" />
</application>
</manifest>
@@ -3,11 +3,10 @@ package eu.darken.capod
import android.app.Application
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.*
import com.getkeepsafe.relinker.ReLinker
import dagger.hilt.android.HiltAndroidApp
import eu.darken.capod.common.BuildConfigWrap
import eu.darken.capod.common.coroutine.AppScope
import eu.darken.capod.common.debug.autoreport.AutoReporting
import eu.darken.capod.common.debug.autoreport.AutomaticBugReporter
import eu.darken.capod.common.debug.logging.*
import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
import eu.darken.capod.main.core.GeneralSettings
@@ -20,7 +19,7 @@ import javax.inject.Inject
open class App : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
@Inject lateinit var autoReporting: AutoReporting
@Inject lateinit var autoReporting: AutomaticBugReporter
@Inject lateinit var generalSettings: GeneralSettings
@Inject lateinit var workManager: WorkManager
@Inject @AppScope lateinit var appScope: CoroutineScope
@@ -29,11 +28,7 @@ open class App : Application(), Configuration.Provider {
super.onCreate()
if (BuildConfig.DEBUG) Logging.install(LogCatLogger())
ReLinker
.log { message -> log(TAG) { "ReLinker: $message" } }
.loadLibrary(this, "bugsnag-plugin-android-anr")
autoReporting.setup()
autoReporting.setup(this)
setupWorker()
@@ -5,7 +5,7 @@ import androidx.lifecycle.SavedStateHandle
import dagger.hilt.android.lifecycle.HiltViewModel
import eu.darken.capod.common.bluetooth.BluetoothManager2
import eu.darken.capod.common.coroutine.DispatcherProvider
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.DebugSettings
import eu.darken.capod.common.debug.logging.Logging.Priority.VERBOSE
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.flow.combine
+7 -9
View File
@@ -6,7 +6,6 @@ plugins {
}
apply(plugin = "dagger.hilt.android.plugin")
apply(plugin = "androidx.navigation.safeargs.kotlin")
apply(plugin = "com.bugsnag.android.gradle")
android {
@@ -22,10 +21,6 @@ android {
versionName = ProjectConfig.Version.name
testInstrumentationRunner = "eu.darken.capod.HiltTestRunner"
manifestPlaceholders["bugsnagApiKey"] = getBugSnagApiKey(
File(System.getProperty("user.home"), ".appconfig/${ProjectConfig.packageName}/bugsnag.properties")
) ?: "fake"
}
signingConfigs {
@@ -47,9 +42,12 @@ android {
create("gplay") {
dimension = "version"
signingConfig = signingConfigs["releaseGplay"]
extra["useBugsnag"] = true
}
}
setupBugsnagPlugin()
buildTypes {
val customProguardRules = fileTree(File(projectDir, "proguard")) {
include("*.pro")
@@ -90,7 +88,7 @@ android {
if (listOf("release", "beta").any { variantName.toLowerCase().contains(it) }) {
val outputFileName = ProjectConfig.packageName +
"-v${defaultConfig.versionName}-${defaultConfig.versionCode}" +
"-${variantName.toUpperCase()}-${lastCommitHash()}.apk"
"-${variantName.toUpperCase()}.apk"
variantOutputImpl.outputFileName = outputFileName
}
@@ -148,8 +146,8 @@ dependencies {
addTesting()
implementation("com.bugsnag:bugsnag-android:5.9.2")
implementation("com.getkeepsafe.relinker:relinker:1.4.3")
"gplayImplementation"("com.android.billingclient:billing:4.0.0")
"gplayImplementation"("com.bugsnag:bugsnag-android:5.9.2")
"gplayImplementation"("com.getkeepsafe.relinker:relinker:1.4.3")
}
-4
View File
@@ -86,10 +86,6 @@
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
tools:node="remove" />
<meta-data
android:name="com.bugsnag.android.API_KEY"
android:value="${bugsnagApiKey}" />
</application>
</manifest>
+3 -8
View File
@@ -3,10 +3,9 @@ package eu.darken.capod
import android.app.Application
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import com.getkeepsafe.relinker.ReLinker
import dagger.hilt.android.HiltAndroidApp
import eu.darken.capod.common.coroutine.AppScope
import eu.darken.capod.common.debug.autoreport.AutoReporting
import eu.darken.capod.common.debug.autoreport.AutomaticBugReporter
import eu.darken.capod.common.debug.logging.*
import eu.darken.capod.common.flow.throttleLatest
import eu.darken.capod.common.upgrade.UpgradeRepo
@@ -25,7 +24,7 @@ import javax.inject.Inject
open class App : Application(), Configuration.Provider {
@Inject lateinit var workerFactory: HiltWorkerFactory
@Inject lateinit var autoReporting: AutoReporting
@Inject lateinit var autoReporting: AutomaticBugReporter
@Inject lateinit var monitorControl: MonitorControl
@Inject lateinit var podMonitor: PodMonitor
@Inject lateinit var widgetManager: WidgetManager
@@ -36,11 +35,7 @@ open class App : Application(), Configuration.Provider {
super.onCreate()
if (BuildConfig.DEBUG) Logging.install(LogCatLogger())
ReLinker
.log { message -> log(TAG) { "ReLinker: $message" } }
.loadLibrary(this, "bugsnag-plugin-android-anr")
autoReporting.setup()
autoReporting.setup(this)
log(TAG) { "onCreate() done! ${Exception().asLog()}" }
@@ -6,7 +6,7 @@ import androidx.lifecycle.SavedStateHandle
import dagger.hilt.android.lifecycle.HiltViewModel
import eu.darken.capod.common.bluetooth.BluetoothManager2
import eu.darken.capod.common.coroutine.DispatcherProvider
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.DebugSettings
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.flow.combine
import eu.darken.capod.common.flow.throttleLatest
@@ -7,7 +7,7 @@ import androidx.fragment.app.viewModels
import androidx.preference.Preference
import dagger.hilt.android.AndroidEntryPoint
import eu.darken.capod.R
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.DebugSettings
import eu.darken.capod.common.observe2
import eu.darken.capod.common.uix.PreferenceFragment3
import javax.inject.Inject
@@ -3,7 +3,7 @@ package eu.darken.capod.main.ui.settings.general.debug
import androidx.lifecycle.SavedStateHandle
import dagger.hilt.android.lifecycle.HiltViewModel
import eu.darken.capod.common.coroutine.DispatcherProvider
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.DebugSettings
import eu.darken.capod.common.debug.logging.log
import eu.darken.capod.common.debug.logging.logTag
import eu.darken.capod.common.debug.recording.core.RecorderModule
@@ -8,7 +8,7 @@ import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.view.isInvisible
import dagger.hilt.android.qualifiers.ApplicationContext
import eu.darken.capod.R
import eu.darken.capod.common.debug.autoreport.DebugSettings
import eu.darken.capod.common.debug.DebugSettings
import eu.darken.capod.databinding.PopupNotificationDualPodsBinding
import eu.darken.capod.databinding.PopupNotificationSinglePodsBinding
import eu.darken.capod.pods.core.*
+30 -1
View File
@@ -1,6 +1,9 @@
import com.android.build.gradle.LibraryExtension
import org.gradle.api.Action
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.extra
import java.io.File
import java.io.FileInputStream
import java.time.Instant
@@ -122,4 +125,30 @@ fun getBugSnagApiKey(
}
return System.getenv("BUGSNAG_API_KEY") ?: bugsnagProps.getProperty("bugsnag.apikey")
}
}
/**
* Use extra["useBugsnag"] = true per flavor to enable
*/
fun <T> T.setupBugsnagPlugin() where T : Project {
fun Project.`android`(configure: Action<com.android.build.gradle.internal.dsl.BaseAppModuleExtension>): Unit =
(this as org.gradle.api.plugins.ExtensionAware).extensions.configure("android", configure)
val key = "useBugsnag"
android {
productFlavors {
forEach {
val paramString = gradle.startParameter.taskRequests.toString().toLowerCase(Locale.ROOT)
val useBugsnag = if (it.extra.has(key)) it.extra[key] as Boolean else false
if (paramString.contains(it.name) && useBugsnag) {
println("Bugsnag plugin (com.bugsnag.android.gradle) applied to ${it.name} ($paramString)")
apply(plugin = "com.bugsnag.android.gradle")
} else {
println("Bugsnag plugin (com.bugsnag.android.gradle) NOT applied to ${it.name} ($paramString)")
}
}
}
}
}