Skip to content
Closed
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
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,6 @@ build/
*.keystore
# Generated i18n resources (regenerated from i18n/*.json at build)
app/src/main/res/values*/strings.xml

# Sentry auth token (mapping upload) — secret, never commit
sentry.properties
23 changes: 23 additions & 0 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ plugins {
// kapt is already on the classpath via the Kotlin Gradle plugin — apply it
// without a version (declaring one conflicts: "already on the classpath").
id("org.jetbrains.kotlin.kapt")
alias(libs.plugins.sentry)
}

// ---------------------------------------------------------------------------
Expand Down Expand Up @@ -243,6 +244,28 @@ androidComponents {
}
}

// ---------------------------------------------------------------------------
// Sentry — crash reporting + ProGuard/R8 mapping upload (so release stack traces
// deobfuscate). The DSN is a public ingest endpoint and lives in source; the AUTH
// TOKEN (used only to UPLOAD mappings) is a secret and is read from the env or a
// git-ignored sentry.properties — never committed. Mapping upload is skipped (with
// a warning, not a failure) when no auth token is present, so CI/contributor builds
// without the secret still succeed.
// ---------------------------------------------------------------------------
sentry {
org.set("fabiodalez")
projectName.set("android")
authToken.set(System.getenv("SENTRY_AUTH_TOKEN"))
// Upload R8 mapping files so crash stack traces are readable in Sentry.
includeProguardMapping.set(true)
autoUploadProguardMapping.set(!System.getenv("SENTRY_AUTH_TOKEN").isNullOrBlank())
// We call SentryAndroid.init() ourselves in PinakesApplication, so let the SDK's
// auto-install add the dependency but keep our explicit init in control.
autoInstallation { enabled.set(true) }
// Don't phone home build telemetry from this repo's builds.
telemetry.set(false)
}

dependencies {
implementation(libs.androidx.core.ktx)
implementation(libs.androidx.lifecycle.runtime.ktx)
Expand Down
5 changes: 5 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,11 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.Pinakes">

<!-- Sentry is initialized manually in PinakesApplication.onCreate() (so we
control DSN/environment/PII), so disable the SDK's auto-init ContentProvider. -->
<meta-data android:name="io.sentry.auto-init" android:value="false" />

<activity
android:name=".MainActivity"
android:exported="true"
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/com/pinakes/app/PinakesApplication.kt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import coil.ImageLoaderFactory
import coil.disk.DiskCache
import com.pinakes.app.data.sync.CatalogSyncWorker
import com.pinakes.app.di.ServiceLocator
import io.sentry.android.core.SentryAndroid
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
Expand All @@ -24,6 +25,20 @@ class PinakesApplication : Application(), ImageLoaderFactory {

override fun onCreate() {
super.onCreate()

// Crash reporting (Sentry — vendor-neutral, not a Google service). Init as
// early as possible so failures during the rest of onCreate() are captured.
// The DSN is a public ingest endpoint; no PII or perf tracing is sent.
SentryAndroid.init(this) { options ->
options.dsn =
"https://a51e7537271cdf25767251d18d2e4ffa@o4511654498926592.ingest.de.sentry.io/4511654504300624"
options.environment = if (BuildConfig.DEBUG) "debug" else "production"
options.release = "${BuildConfig.APPLICATION_ID}@${BuildConfig.VERSION_NAME}+${BuildConfig.VERSION_CODE}"
options.isDebug = false
options.isSendDefaultPii = false // no IP / user data attached by default
options.tracesSampleRate = 0.0 // crash reporting only — no performance tracing
}

services = ServiceLocator(this)

// Refresh the cached catalog every time the app comes to the foreground, so the
Expand Down
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ plugins {
alias(libs.plugins.kotlin.android) apply false
alias(libs.plugins.kotlin.compose) apply false
alias(libs.plugins.kotlin.serialization) apply false
alias(libs.plugins.sentry) apply false
}
2 changes: 2 additions & 0 deletions gradle/libs.versions.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ appcompat = "1.7.0"
media3 = "1.4.1"
room = "2.6.1"
work = "2.9.1"
sentry = "4.14.1"
junit = "4.13.2"
coroutinesTest = "1.8.1"
robolectric = "4.13"
Expand Down Expand Up @@ -63,3 +64,4 @@ android-application = { id = "com.android.application", version.ref = "agp" }
kotlin-android = { id = "org.jetbrains.kotlin.android", version.ref = "kotlin" }
kotlin-compose = { id = "org.jetbrains.kotlin.plugin.compose", version.ref = "kotlin" }
kotlin-serialization = { id = "org.jetbrains.kotlin.plugin.serialization", version.ref = "kotlin" }
sentry = { id = "io.sentry.android.gradle", version.ref = "sentry" }
Loading