debug builds send usage notes too, marked debug so the server keeps them out of the stats; call them debug builds everywhere instead of dev

This commit is contained in:
Seb3thehacker committed 2026-10-14 12:25:45 -07:00
1 parent 10dfb46a96
commit 3c9603175e
10 files changed
+20 -20

No files matched your search

+2 -2
View File
@@ -58,13 +58,13 @@ android {
release { release {
signingConfig = signingConfigs.findByName("release") signingConfig = signingConfigs.findByName("release")
} }
// Its own package, so a dev build installs beside the release one instead of over it. // Its own package, so a debug build installs beside the release one instead of over it.
// Signed with the release key when it's here: both builds declare the car template // Signed with the release key when it's here: both builds declare the car template
// permission, and Android refuses a second app declaring it under a different key. // permission, and Android refuses a second app declaring it under a different key.
debug { debug {
applicationIdSuffix = ".dev" applicationIdSuffix = ".dev"
signingConfigs.findByName("release")?.let { signingConfig = it } signingConfigs.findByName("release")?.let { signingConfig = it }
manifestPlaceholders["appLabel"] = "Gearslip Dev" manifestPlaceholders["appLabel"] = "Gearslip Debug"
} }
} }
@@ -265,7 +265,7 @@ fun CarUi() {
// something in the top-right (settings, search, a Liked Songs // something in the top-right (settings, search, a Liked Songs
// shortcut) and this badge used to sit right on top of it, hiding // shortcut) and this badge used to sit right on top of it, hiding
// whatever the screen drew there. // whatever the screen drew there.
DevBuildBadge(Modifier.align(Alignment.BottomEnd)) DebugBuildBadge(Modifier.align(Alignment.BottomEnd))
} }
} }
// The keyboard takes the nav bar's row instead of squeezing in above it - // The keyboard takes the nav bar's row instead of squeezing in above it -
@@ -382,7 +382,7 @@ private fun AppWontStart(app: String, onBack: () -> Unit) {
* that matters while driving, since a debug build is slower and less tested than what ships. * that matters while driving, since a debug build is slower and less tested than what ships.
*/ */
@Composable @Composable
private fun DevBuildBadge(modifier: Modifier = Modifier) { private fun DebugBuildBadge(modifier: Modifier = Modifier) {
Surface( Surface(
modifier = modifier.padding(6.dp), modifier = modifier.padding(6.dp),
color = MaterialTheme.colorScheme.error, color = MaterialTheme.colorScheme.error,
@@ -390,7 +390,7 @@ private fun DevBuildBadge(modifier: Modifier = Modifier) {
shape = MaterialTheme.shapes.small, shape = MaterialTheme.shapes.small,
) { ) {
Text( Text(
"DEV BUILD", "DEBUG BUILD",
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp), modifier = Modifier.padding(horizontal = 8.dp, vertical = 3.dp),
@@ -30,7 +30,7 @@ class GearslipNotificationListener : NotificationListenerService() {
override fun onNotificationRemoved(sbn: StatusBarNotification) = CarNotifications.gone(sbn.key) override fun onNotificationRemoved(sbn: StatusBarNotification) = CarNotifications.gone(sbn.key)
private fun ingest(sbn: StatusBarNotification, quiet: Boolean) { private fun ingest(sbn: StatusBarNotification, quiet: Boolean) {
// Gearslip's own notifications are skipped, except a dev build's test message. // Gearslip's own notifications are skipped, except a debug build's test message.
if (sbn.packageName == packageName && if (sbn.packageName == packageName &&
!(app.seb3thehacker.gearslip.BuildConfig.DEBUG && sbn.notification.channelId == TestMessage.CHANNEL) !(app.seb3thehacker.gearslip.BuildConfig.DEBUG && sbn.notification.channelId == TestMessage.CHANNEL)
) return ) return
@@ -13,7 +13,7 @@ import androidx.core.app.RemoteInput
import app.seb3thehacker.gearslip.GearslipLog import app.seb3thehacker.gearslip.GearslipLog
/** /**
* Dev builds only: posts a chat message from Gearslip to itself, shaped like Signal's or * Debug builds only: posts a chat message from Gearslip to itself, shaped like Signal's or
* WhatsApp's (MessagingStyle, a Reply action, a Mark as read action), so popups and voice reply * WhatsApp's (MessagingStyle, a Reply action, a Mark as read action), so popups and voice reply
* can be tried without asking someone to text you. The listener lets these through only in a * can be tried without asking someone to text you. The listener lets these through only in a
* debug build; everything else Gearslip posts is still ignored. * debug build; everything else Gearslip posts is still ignored.
@@ -59,10 +59,10 @@ object UsageStats {
private fun prefs(context: Context) = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE) private fun prefs(context: Context) = context.getSharedPreferences(PREFS, Context.MODE_PRIVATE)
/** /**
* Dev builds show every switch and screen, so they can be tested, but never send anything: * Debug builds send too, marked "debug". The server keeps those notes apart, so testing never
* testing mustn't muddy the numbers. * muddies the numbers.
*/ */
val sends: Boolean get() = !BuildConfig.DEBUG && BuildConfig.STATS_URL.isNotBlank() val sends: Boolean get() = BuildConfig.STATS_URL.isNotBlank()
fun enabled(context: Context): Boolean = prefs(context).getBoolean(KEY_ENABLED, false) fun enabled(context: Context): Boolean = prefs(context).getBoolean(KEY_ENABLED, false)
@@ -262,7 +262,7 @@ object UsageStats {
.put("id", installId(context)) .put("id", installId(context))
.put("version", BuildConfig.VERSION_NAME) .put("version", BuildConfig.VERSION_NAME)
.put("code", BuildConfig.VERSION_CODE) .put("code", BuildConfig.VERSION_CODE)
.put("build", if (BuildConfig.DEBUG) "dev" else "release") .put("build", if (BuildConfig.DEBUG) "debug" else "release")
// Which boxes are ticked, so the server knows what this phone shares and can drop // Which boxes are ticked, so the server knows what this phone shares and can drop
// anything it kept from a box since unticked. // anything it kept from a box since unticked.
.put("shares", JSONArray().apply { .put("shares", JSONArray().apply {
@@ -101,7 +101,7 @@ fun GearslipApp(onDisconnect: () -> Unit, onRequestCallScreening: () -> Unit) {
.windowInsetsPadding(WindowInsets.statusBars) .windowInsetsPadding(WindowInsets.statusBars)
.consumeWindowInsets(WindowInsets.statusBars), .consumeWindowInsets(WindowInsets.statusBars),
) { ) {
if (BuildConfig.DEBUG && screen != Screen.CAR_PREVIEW && screen != Screen.INTRO) DevBuildBanner() if (BuildConfig.DEBUG && screen != Screen.CAR_PREVIEW && screen != Screen.INTRO) DebugBuildBanner()
Column(Modifier.weight(1f)) { Column(Modifier.weight(1f)) {
when (screen) { when (screen) {
@@ -160,7 +160,7 @@ fun GearslipApp(onDisconnect: () -> Unit, onRequestCallScreening: () -> Unit) {
* never mistaken for a release one. * never mistaken for a release one.
*/ */
@Composable @Composable
private fun DevBuildBanner() { private fun DebugBuildBanner() {
Surface( Surface(
modifier = Modifier.fillMaxWidth().height(28.dp), modifier = Modifier.fillMaxWidth().height(28.dp),
color = Color(0xFFF5C518), color = Color(0xFFF5C518),
@@ -168,7 +168,7 @@ private fun DevBuildBanner() {
) { ) {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) { Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Text( Text(
"DEV BUILD", "DEBUG BUILD",
style = MaterialTheme.typography.labelSmall, style = MaterialTheme.typography.labelSmall,
fontWeight = FontWeight.Bold, fontWeight = FontWeight.Bold,
) )
@@ -237,7 +237,7 @@ private fun HelpSection(onOpenHelp: () -> Unit, onOpenCarPreview: () -> Unit, on
SettingsRow( SettingsRow(
"Send a test message", "Send a test message",
Modifier.clickable { TestMessage.post(context) }, Modifier.clickable { TestMessage.post(context) },
subtitle = "Dev builds only. Posts a message notification to read on the car", subtitle = "Debug builds only. Posts a message notification to read on the car",
icon = Icons.AutoMirrored.Filled.Send, icon = Icons.AutoMirrored.Filled.Send,
) )
} }
@@ -107,7 +107,7 @@ fun UpdateCard() {
/** What the update check found, in a line. */ /** What the update check found, in a line. */
private fun statusLine(state: State): String = when (state) { private fun statusLine(state: State): String = when (state) {
State.Idle -> if (BuildConfig.DEBUG) "Dev builds check only when you tap Check now" else "Gearslip checks once a day" State.Idle -> if (BuildConfig.DEBUG) "Debug builds check only when you tap Check now" else "Gearslip checks once a day"
State.Checking -> "Checking…" State.Checking -> "Checking…"
State.UpToDate -> "You have the latest version" State.UpToDate -> "You have the latest version"
is State.Available -> "Version ${state.release.version} is out" is State.Available -> "Version ${state.release.version} is out"
@@ -220,7 +220,7 @@ private fun UpdateDialog(
Column(Modifier.weight(1f)) { Column(Modifier.weight(1f)) {
Text("Check automatically", style = MaterialTheme.typography.bodyLarge) Text("Check automatically", style = MaterialTheme.typography.bodyLarge)
Text( Text(
if (BuildConfig.DEBUG) "Dev builds check only when you tap Check now" else "Once a day", if (BuildConfig.DEBUG) "Debug builds check only when you tap Check now" else "Once a day",
style = MaterialTheme.typography.bodyMedium, style = MaterialTheme.typography.bodyMedium,
color = MaterialTheme.colorScheme.onSurfaceVariant, color = MaterialTheme.colorScheme.onSurfaceVariant,
) )
@@ -172,10 +172,10 @@ private fun notePreview(context: Context): String {
return preview.toString(2) + example return preview.toString(2) + example
} }
/** Why this build sends nothing, when it doesn't; null for a normal release. */ /** What's different about where this build's notes go; null for a normal release. */
private fun buildNote(): String? = when { private fun buildNote(): String? = when {
BuildConfig.DEBUG -> "Dev build: nothing is ever sent"
BuildConfig.STATS_URL.isBlank() -> "This build has no stats server, so it sends nothing" BuildConfig.STATS_URL.isBlank() -> "This build has no stats server, so it sends nothing"
BuildConfig.DEBUG -> "Debug build: notes are kept apart and never counted in the stats"
else -> null else -> null
} }
@@ -40,7 +40,7 @@ import java.security.MessageDigest
* a notification, once per version, since the driver is parked and the app is likely closed. The * a notification, once per version, since the driver is parked and the app is likely closed. The
* car screen shows the same news once per version, at plug-in and only while parked. * car screen shows the same news once per version, at plug-in and only while parked.
* Nothing runs in the background otherwise, and nothing else is sent: the request is the same one * Nothing runs in the background otherwise, and nothing else is sent: the request is the same one
* a browser makes for the release page. Dev builds never check on their own. * a browser makes for the release page. Debug builds never check on their own.
* *
* The APK is checked against the size and SHA-256 GitHub lists for it, and Android refuses an * The APK is checked against the size and SHA-256 GitHub lists for it, and Android refuses an
* update signed with a different key, so a bad download can't replace the app. * update signed with a different key, so a bad download can't replace the app.