diff --git a/.github/workflows/release-tag.yml b/.github/workflows/release-tag.yml index 51589fa3..56fbc337 100644 --- a/.github/workflows/release-tag.yml +++ b/.github/workflows/release-tag.yml @@ -48,7 +48,6 @@ jobs: STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }} KEY_ALIAS: ${{ secrets.KEY_ALIAS }} KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - BUGSNAG_API_KEY: ${{ secrets.BUGSNAG_API_KEY }} - name: Assemble production APK if: "!contains(steps.tagger.outputs.tag, '-beta')" @@ -58,7 +57,6 @@ jobs: STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }} KEY_ALIAS: ${{ secrets.KEY_ALIAS }} KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - BUGSNAG_API_KEY: ${{ secrets.BUGSNAG_API_KEY }} - name: Create pre-release if: contains(steps.tagger.outputs.tag, '-beta') @@ -145,7 +143,6 @@ jobs: # STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }} # KEY_ALIAS: ${{ secrets.KEY_ALIAS }} # KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - # BUGSNAG_API_KEY: ${{ secrets.BUGSNAG_API_KEY }} - name: Assemble beta and upload to Google Play if: contains(steps.tagger.outputs.tag, '-beta') @@ -154,7 +151,6 @@ jobs: STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }} KEY_ALIAS: ${{ secrets.KEY_ALIAS }} KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - BUGSNAG_API_KEY: ${{ secrets.BUGSNAG_API_KEY }} # - name: Assemble WearOS production and upload to Google Play # if: "!contains(steps.tagger.outputs.tag, '-beta')" @@ -163,7 +159,6 @@ jobs: # STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }} # KEY_ALIAS: ${{ secrets.KEY_ALIAS }} # KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - # BUGSNAG_API_KEY: ${{ secrets.BUGSNAG_API_KEY }} - name: Assemble production and upload to Google Play if: "!contains(steps.tagger.outputs.tag, '-beta')" @@ -171,5 +166,4 @@ jobs: env: STORE_PASSWORD: ${{ secrets.STORE_PASSWORD }} KEY_ALIAS: ${{ secrets.KEY_ALIAS }} - KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} - BUGSNAG_API_KEY: ${{ secrets.BUGSNAG_API_KEY }} \ No newline at end of file + KEY_PASSWORD: ${{ secrets.KEY_PASSWORD }} \ No newline at end of file diff --git a/PRIVACY_POLICY.md b/PRIVACY_POLICY.md index 921c4722..4e64325d 100644 --- a/PRIVACY_POLICY.md +++ b/PRIVACY_POLICY.md @@ -20,15 +20,21 @@ On Android 12+ the newer and more fine grained `BLUETOOTH_SCAN` permission is us Bluetooth Low Energy is a technology that devices like AirPods use to communicate their status to nearby devices. CAPod requests location permissions because these permissions are required to work with Bluetooth Low Energy data. -This is a privacy measure on Android's side because you could determine someones location by scanning for Bluetooth devices: -If you know the physical location of a Bluetooth device (e.g. AirTags) you could use Bluetooth data to calculate your position. +This is a privacy measure on Android's side because you could determine someones location by scanning for Bluetooth +devices: +If you know the physical location of a Bluetooth device (e.g. AirTags) you could use Bluetooth data to calculate your +position. ### Location access in the background -CAPod uses the "location access in the background" permission (`ACCESS_BACKGROUND_LOCATION`) on Android 11 and older to receive Bluetooth Low Energy data while the app is in the background. This permission enables the "Show popup" and "Autoconnect" features and allows CAPod to react to nearby devices whil the app is closed. +CAPod uses the "location access in the background" permission (`ACCESS_BACKGROUND_LOCATION`) on Android 11 and older to +receive Bluetooth Low Energy data while the app is in the background. This permission enables the "Show popup" and " +Autoconnect" features and allows CAPod to react to nearby devices whil the app is closed. ## Automatic error reports +*This was removed in v2.11.0+* + If an error occurs, an automated report may be sent to help me fix the issue. This is optional and you can opt out of this in the settings. diff --git a/app-common/build.gradle.kts b/app-common/build.gradle.kts index add0b9c8..aa04ed2e 100644 --- a/app-common/build.gradle.kts +++ b/app-common/build.gradle.kts @@ -22,10 +22,6 @@ 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 { @@ -100,7 +96,4 @@ dependencies { addTesting() - "gplayImplementation"("com.bugsnag:bugsnag-android:5.9.2") - "gplayImplementation"("com.getkeepsafe.relinker:relinker:1.4.3") - } \ No newline at end of file diff --git a/app-common/src/gplay/AndroidManifest.xml b/app-common/src/gplay/AndroidManifest.xml index c3f9dea0..1fb42b0a 100644 --- a/app-common/src/gplay/AndroidManifest.xml +++ b/app-common/src/gplay/AndroidManifest.xml @@ -1,10 +1,8 @@ - + - + \ No newline at end of file diff --git a/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/BugsnagErrorHandler.kt b/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/BugsnagErrorHandler.kt deleted file mode 100644 index 82bf717a..00000000 --- a/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/BugsnagErrorHandler.kt +++ /dev/null @@ -1,58 +0,0 @@ -package eu.darken.capod.debug.autoreport - -import android.annotation.SuppressLint -import android.content.Context -import android.content.pm.PackageManager -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.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 -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class BugsnagErrorHandler @Inject constructor( - @ApplicationContext private val context: Context, - private val bugsnagLogger: BugsnagLogger, - private val debugSettings: DebugSettings, -) : OnErrorCallback { - - override fun onError(event: Event): Boolean { - bugsnagLogger.injectLog(event) - - TAB_APP.also { tab -> - event.addMetadata(tab, "gitSha", BuildConfigWrap.GIT_SHA) - event.addMetadata(tab, "buildTime", BuildConfigWrap.BUILDTIME) - - context.tryFormattedSignature()?.let { event.addMetadata(tab, "signatures", it) } - } - - return debugSettings.isAutoReportingEnabled.value && !eu.darken.capod.common.BuildConfigWrap.DEBUG - } - - companion object { - private const val TAB_APP = "app" - - @Suppress("DEPRECATION") - @SuppressLint("PackageManagerGetSignatures") - fun Context.tryFormattedSignature(): String? = try { - packageManager.getPackageInfo(packageName, PackageManager.GET_SIGNATURES).signatures?.let { sigs -> - val sb = StringBuilder("[") - for (i in sigs.indices) { - sb.append(sigs[i].hashCode()) - if (i + 1 != sigs.size) sb.append(", ") - } - sb.append("]") - sb.toString() - } - } catch (e: Exception) { - log(WARN) { e.asLog() } - null - } - } - -} \ No newline at end of file diff --git a/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/BugsnagLogger.kt b/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/BugsnagLogger.kt deleted file mode 100644 index 3577a1bc..00000000 --- a/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/BugsnagLogger.kt +++ /dev/null @@ -1,47 +0,0 @@ -package eu.darken.capod.debug.autoreport - -import com.bugsnag.android.Event -import eu.darken.capod.common.debug.logging.Logging -import eu.darken.capod.common.debug.logging.asLog -import java.lang.String.format -import java.util.* -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class BugsnagLogger @Inject constructor() : Logging.Logger { - - // Adding one to the initial size accounts for the add before remove. - private val buffer: Deque = ArrayDeque(BUFFER_SIZE + 1) - - override fun log(priority: Logging.Priority, tag: String, message: String, metaData: Map?) { - val line = "${System.currentTimeMillis()} ${priority.toLabel()}/$tag: $message" - synchronized(buffer) { - buffer.addLast(line) - if (buffer.size > BUFFER_SIZE) { - buffer.removeFirst() - } - } - } - - fun injectLog(event: Event) { - synchronized(buffer) { - var i = 100 - buffer.forEach { event.addMetadata("Log", format(Locale.ROOT, "%03d", i++), it) } - event.addMetadata("Log", format(Locale.ROOT, "%03d", i), event.originalError?.asLog()) - } - } - - companion object { - private const val BUFFER_SIZE = 200 - - private fun Logging.Priority.toLabel(): String = when (this) { - Logging.Priority.VERBOSE -> "V" - Logging.Priority.DEBUG -> "D" - Logging.Priority.INFO -> "I" - Logging.Priority.WARN -> "W" - Logging.Priority.ERROR -> "E" - Logging.Priority.ASSERT -> "WTF" - } - } -} diff --git a/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/GplayAutoReporting.kt b/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/GplayAutoReporting.kt index f9026225..7b9ad882 100644 --- a/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/GplayAutoReporting.kt +++ b/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/GplayAutoReporting.kt @@ -2,20 +2,15 @@ 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.DebugSettings import eu.darken.capod.common.debug.autoreport.AutomaticBugReporter -import eu.darken.capod.common.debug.logging.Logging +import eu.darken.capod.common.debug.logging.Logging.Priority.WARN import eu.darken.capod.common.debug.logging.log import eu.darken.capod.common.debug.logging.logTag import javax.inject.Inject -import javax.inject.Provider import javax.inject.Singleton @Singleton @@ -23,9 +18,6 @@ class GplayAutoReporting @Inject constructor( @ApplicationContext private val context: Context, private val debugSettings: DebugSettings, private val installId: InstallId, - private val bugsnagLogger: Provider, - private val bugsnagErrorHandler: Provider, - private val nopBugsnagErrorHandler: Provider, ) : AutomaticBugReporter { override fun setup(application: Application) { @@ -34,35 +26,13 @@ class GplayAutoReporting @Inject constructor( if (!isEnabled) return - ReLinker - .log { message -> log(TAG) { "ReLinker: $message" } } - .loadLibrary(application, "bugsnag-plugin-android-anr") + // Currently no 3rd party bug tracking - try { - val bugsnagConfig = Configuration.load(context).apply { - if (debugSettings.isAutoReportingEnabled.value) { - Logging.install(bugsnagLogger.get()) - setUser(installId.id, null, null) - autoTrackSessions = true - addOnError(bugsnagErrorHandler.get()) - addMetadata("App", "buildFlavor", BuildConfigWrap.FLAVOR) - log(TAG) { "Bugsnag setup done!" } - } else { - autoTrackSessions = false - addOnError(nopBugsnagErrorHandler.get()) - log(TAG) { "Installing Bugsnag NOP error handler due to user opt-out!" } - } - } - - Bugsnag.start(context, bugsnagConfig) - Bugs.reporter = this - } catch (e: IllegalStateException) { - log(TAG) { "Bugsnag API Key not configured." } - } + Bugs.reporter = this } override fun notify(throwable: Throwable) { - Bugsnag.notify(throwable) + log(TAG, WARN) { "notify($throwable)" } } companion object { diff --git a/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/NOPBugsnagErrorHandler.kt b/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/NOPBugsnagErrorHandler.kt deleted file mode 100644 index cec7bca2..00000000 --- a/app-common/src/gplay/java/eu/darken/capod/debug/autoreport/NOPBugsnagErrorHandler.kt +++ /dev/null @@ -1,19 +0,0 @@ -package eu.darken.capod.debug.autoreport - -import com.bugsnag.android.Event -import com.bugsnag.android.OnErrorCallback -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 -import javax.inject.Inject -import javax.inject.Singleton - -@Singleton -class NOPBugsnagErrorHandler @Inject constructor() : OnErrorCallback { - - override fun onError(event: Event): Boolean { - log(WARN) { "Error, but skipping bugsnag due to user opt-out: ${event.originalError?.asLog()}" } - return false - } - -} \ No newline at end of file diff --git a/app-wear/build.gradle.kts b/app-wear/build.gradle.kts index 672a39d3..0b54187e 100644 --- a/app-wear/build.gradle.kts +++ b/app-wear/build.gradle.kts @@ -45,12 +45,9 @@ android { create("gplay") { dimension = "version" signingConfig = signingConfigs["releaseGplay"] - extra["useBugsnag"] = true } } - setupBugsnagPlugin() - buildTypes { val customProguardRules = fileTree(File("../proguard")) { include("*.pro") @@ -141,7 +138,4 @@ dependencies { 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") } \ No newline at end of file diff --git a/app/build.gradle.kts b/app/build.gradle.kts index ef23b25e..098d0e16 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -42,12 +42,9 @@ android { create("gplay") { dimension = "version" signingConfig = signingConfigs["releaseGplay"] - extra["useBugsnag"] = true } } - setupBugsnagPlugin() - buildTypes { val customProguardRules = fileTree(File(projectDir, "proguard")) { include("*.pro") @@ -150,7 +147,4 @@ dependencies { "gplayImplementation"("com.android.billingclient:billing:5.1.0") "gplayImplementation"("com.android.billingclient:billing-ktx:5.1.0") - - "gplayImplementation"("com.bugsnag:bugsnag-android:5.9.2") - "gplayImplementation"("com.getkeepsafe.relinker:relinker:1.4.3") } \ No newline at end of file diff --git a/app/src/main/res/xml/preferences_acknowledgements.xml b/app/src/main/res/xml/preferences_acknowledgements.xml index c9a05028..5129c75b 100644 --- a/app/src/main/res/xml/preferences_acknowledgements.xml +++ b/app/src/main/res/xml/preferences_acknowledgements.xml @@ -45,15 +45,6 @@ - - - T.setupBugsnagPlugin() where T : Project { - fun Project.`android`(configure: Action): 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)") - } - } - } - } -}