From 6ec02775e6aef9d93895084aa6739e31baa938f2 Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Wed, 30 Sep 2026 11:45:29 +0200 Subject: [PATCH 1/2] fix(car): stop spending the template quota on every refresh The host treats a new pane as a free refresh only while the template title, row count and row titles stay the same. The reading and its age were row titles, so every poll spent one of the five template steps and a few minutes in the foreground while driving ended in the host's "can't do this while driving" error. Row titles are now fixed labels and the live values sit in the row texts. Without tabs, switching sources in place renamed the template, costing a step per switch, and the numbered buttons exceeded the pane's two-action strip limit for three or four sources. Switching now always goes through SourceSelectScreen, whose back operation restores the quota. Co-Authored-By: Claude Opus 5.5 (1M context) --- CHANGELOG.md | 5 ++ .../java/de/autosugar/car/GlucoseScreen.kt | 86 ++++++++----------- app/src/main/res/values-ar/strings.xml | 2 + app/src/main/res/values-de/strings.xml | 2 + app/src/main/res/values-es/strings.xml | 2 + app/src/main/res/values-fr/strings.xml | 2 + app/src/main/res/values-hi/strings.xml | 2 + app/src/main/res/values-it/strings.xml | 2 + app/src/main/res/values-ja/strings.xml | 2 + app/src/main/res/values-nl/strings.xml | 2 + app/src/main/res/values-pt/strings.xml | 2 + app/src/main/res/values-zh/strings.xml | 2 + app/src/main/res/values/strings.xml | 2 + 13 files changed, 61 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a04232a..ae4dc36 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +### Fixed + +- The glucose screen no longer ends in "This task can't be done while driving" after a few minutes in the foreground. Android Auto allows an app only a handful of screen changes per task and counts an update as free only while the screen's titles stay the same, but the reading and its age were shown as titles, so every refresh used one up. The titles are now fixed labels ("Glucose", "Status") and the reading, delta and timestamps sit beneath them +- Switching sources on cars without tabs no longer uses up the same allowance, and no longer fails with three or four sources. The numbered source buttons changed the screen's title on every switch and were more buttons than that screen permits; sources are now switched through the "Switch source" list, as they already were for five or more + ## [1.2.10] - 2026-09-12 ### Fixed diff --git a/app/src/main/java/de/autosugar/car/GlucoseScreen.kt b/app/src/main/java/de/autosugar/car/GlucoseScreen.kt index 079c351..ed8b293 100644 --- a/app/src/main/java/de/autosugar/car/GlucoseScreen.kt +++ b/app/src/main/java/de/autosugar/car/GlucoseScreen.kt @@ -1,10 +1,5 @@ package de.autosugar.car -import android.graphics.Bitmap -import android.graphics.Canvas -import android.graphics.Color -import android.graphics.Paint -import android.graphics.Typeface import androidx.car.app.CarContext import androidx.car.app.Screen import androidx.car.app.annotations.RequiresCarApi @@ -113,7 +108,6 @@ class GlucoseScreen( // onGetTemplate can fire frequently; cache the small generated bitmaps so they are // not re-rendered on the main thread on every rebuild. private val trendIconCache = mutableMapOf() - private val numberIconCache = mutableMapOf, CarIcon>() // A reading older than this is considered stale (≥2 missed 5-min CGM readings) and is // labelled as such in the UI. Alerting itself is handled by BackgroundAlertMonitor. @@ -233,7 +227,7 @@ class GlucoseScreen( // endregion - // region PaneTemplate (fallback: 1 profile, >5 profiles, or CarApi < 6) + // region PaneTemplate (fallback: 1 profile, >4 profiles, or CarApi < 6) private fun buildPaneTemplate(): Template { val activeProfile = profiles.find { it.id == activeProfileId } @@ -246,53 +240,33 @@ class GlucoseScreen( .build() } + /** + * Without tabs, switching sources goes through [SourceSelectScreen] for any number of + * profiles rather than switching in place. + * + * Switching in place changes the template title to the new profile's name, which the host + * never treats as a refresh: every switch spent a step of the five-template quota, and a + * handful of switches while driving ended in the host's "can't do this while driving" + * error. Popping back from the picker hands the quota back, and a back operation may + * change the contents of a same-type template freely, so the renamed pane costs nothing. + * + * It also replaces the numbered profile buttons this used for 2–4 profiles: the pane's + * action strip takes at most two actions, so three or four buttons failed validation. + */ private fun buildActionStrip(): ActionStrip { - val builder = ActionStrip.Builder() - return when { - profiles.size > 4 -> builder.addAction( - Action.Builder() - .setTitle(carContext.getString(R.string.action_switch_source)) - .setOnClickListener { - screenManager.push( - SourceSelectScreen(carContext, repository) { id -> switchTo(id) } - ) - } - .build() - ).build() - profiles.size in 2..5 -> { - // Numbered icon fallback when TabTemplate is unavailable (CarApi < 6). - // The upper bound of 5 here is unreachable in practice since the ">4" - // branch above already matches size 5 — this only ever runs for 2..4. - profiles.forEachIndexed { index, profile -> - val active = profile.id == activeProfileId - builder.addAction( - Action.Builder() - .setIcon(numberIconCache.getOrPut(index + 1 to active) { - profileNumberIcon(index + 1, active) - }) - .setOnClickListener { switchTo(profile.id) } - .build() + val action = if (profiles.size >= 2) { + Action.Builder() + .setTitle(carContext.getString(R.string.action_switch_source)) + .setOnClickListener { + screenManager.push( + SourceSelectScreen(carContext, repository) { id -> switchTo(id) } ) } - builder.build() - } - else -> builder.addAction(Action.APP_ICON).build() - } - } - - private fun profileNumberIcon(number: Int, active: Boolean): CarIcon { - val size = 96 - val bmp = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888) - val c = Canvas(bmp) - val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { - color = if (active) Color.WHITE else Color.argb(150, 200, 200, 200) - textSize = size * 0.65f - textAlign = Paint.Align.CENTER - typeface = Typeface.DEFAULT_BOLD + .build() + } else { + Action.APP_ICON } - val textY = size / 2f - (paint.fontMetrics.ascent + paint.fontMetrics.descent) / 2f - c.drawText(number.toString(), size / 2f, textY, paint) - return CarIcon.Builder(IconCompat.createWithBitmap(bmp)).build() + return ActionStrip.Builder().addAction(action).build() } // endregion @@ -318,11 +292,18 @@ class GlucoseScreen( .build() else -> { + // Row titles must never carry live data. The host treats a new Pane as a refresh + // (free) only while the template title, the row count and every row title stay + // the same; anything else counts as a new step against the five-template quota. + // With the reading and its age in the titles, every poll spent a step, and a few + // minutes on screen while driving ended in the host's "can't do this while + // driving" error. Everything that changes goes into the row texts instead. val e = entry!! val now = System.currentTimeMillis() val stale = errorMessage != null || now - e.dateMs > staleAfterMs val statsRow = Row.Builder() - .setTitle( + .setTitle(carContext.getString(R.string.label_status)) + .addText( if (stale) carContext.getString(R.string.label_stale_reading, ageString(now - e.dateMs)) else @@ -334,7 +315,8 @@ class GlucoseScreen( statsRow.addText(carContext.getString(R.string.label_received, ageString(now - lastFetchedMs))) } val valueRow = Row.Builder() - .setTitle("${e.displayValue(unit)} ${unitLabel(unit)}") + .setTitle(carContext.getString(R.string.label_glucose)) + .addText("${e.displayValue(unit)} ${unitLabel(unit)}") .addText("${e.displayDelta(unit) ?: "-"} ${unitLabel(unit)}") if (TREND_ARROW_ENABLED) { valueRow.setImage( diff --git a/app/src/main/res/values-ar/strings.xml b/app/src/main/res/values-ar/strings.xml index f5f684e..4174ed6 100644 --- a/app/src/main/res/values-ar/strings.xml +++ b/app/src/main/res/values-ar/strings.xml @@ -19,6 +19,8 @@ ⚠️ القراءة: %s القراءة: %s تم الاستقبال: %s + الجلوكوز + الحالة الإعدادات diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index be18f6c..56c21ce 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -19,6 +19,8 @@ ⚠️ Messung: %s Messung: %s Empfangen: %s + Blutzucker + Status Einstellungen diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 40ee377..9b2c60e 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -19,6 +19,8 @@ ⚠️ Lectura: %s Lectura: %s Recibido: %s + Glucosa + Estado Ajustes diff --git a/app/src/main/res/values-fr/strings.xml b/app/src/main/res/values-fr/strings.xml index 2edeb60..edb3cfb 100644 --- a/app/src/main/res/values-fr/strings.xml +++ b/app/src/main/res/values-fr/strings.xml @@ -19,6 +19,8 @@ ⚠️ Lecture : %s Lecture : %s Reçu : %s + Glycémie + État Paramètres diff --git a/app/src/main/res/values-hi/strings.xml b/app/src/main/res/values-hi/strings.xml index 6d52c24..702b25a 100644 --- a/app/src/main/res/values-hi/strings.xml +++ b/app/src/main/res/values-hi/strings.xml @@ -19,6 +19,8 @@ ⚠️ रीडिंग: %s रीडिंग: %s प्राप्त: %s + ग्लूकोज़ + स्थिति सेटिंग्स diff --git a/app/src/main/res/values-it/strings.xml b/app/src/main/res/values-it/strings.xml index 006d9c0..8521466 100644 --- a/app/src/main/res/values-it/strings.xml +++ b/app/src/main/res/values-it/strings.xml @@ -19,6 +19,8 @@ ⚠️ Lettura: %s Lettura: %s Ricevuto: %s + Glicemia + Stato Impostazioni diff --git a/app/src/main/res/values-ja/strings.xml b/app/src/main/res/values-ja/strings.xml index 6239a8d..e5132e6 100644 --- a/app/src/main/res/values-ja/strings.xml +++ b/app/src/main/res/values-ja/strings.xml @@ -19,6 +19,8 @@ ⚠️ 測定値: %s 測定値: %s 受信: %s + 血糖値 + ステータス 設定 diff --git a/app/src/main/res/values-nl/strings.xml b/app/src/main/res/values-nl/strings.xml index 252d899..c79c737 100644 --- a/app/src/main/res/values-nl/strings.xml +++ b/app/src/main/res/values-nl/strings.xml @@ -19,6 +19,8 @@ ⚠️ Meting: %s Meting: %s Ontvangen: %s + Glucose + Status Instellingen diff --git a/app/src/main/res/values-pt/strings.xml b/app/src/main/res/values-pt/strings.xml index b54539b..db26485 100644 --- a/app/src/main/res/values-pt/strings.xml +++ b/app/src/main/res/values-pt/strings.xml @@ -19,6 +19,8 @@ ⚠️ Leitura: %s Leitura: %s Recebido: %s + Glicose + Estado Configurações diff --git a/app/src/main/res/values-zh/strings.xml b/app/src/main/res/values-zh/strings.xml index 3b1eb5c..06e6f97 100644 --- a/app/src/main/res/values-zh/strings.xml +++ b/app/src/main/res/values-zh/strings.xml @@ -19,6 +19,8 @@ ⚠️ 读数:%s 读数:%s 已接收:%s + 血糖 + 状态 设置 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 77b5fb4..c07b6aa 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -37,6 +37,8 @@ Reading: %s ⚠️ Reading: %s Received: %s + Glucose + Status Glucose alerts From f82f50f25004e27f0f923d6139c2975a4686f202 Mon Sep 17 00:00:00 2001 From: Nico Wiedemann Date: Wed, 30 Sep 2026 11:46:18 +0200 Subject: [PATCH 2/2] chore(release): bump version to 1.2.11 Co-Authored-By: Claude Opus 5.5 (1M context) --- CHANGELOG.md | 2 ++ app/build.gradle.kts | 4 ++-- docs/whatsnew/1.2.11-ar | 1 + docs/whatsnew/1.2.11-de-DE | 1 + docs/whatsnew/1.2.11-en-US | 1 + docs/whatsnew/1.2.11-es-ES | 1 + docs/whatsnew/1.2.11-fr-FR | 1 + docs/whatsnew/1.2.11-hi-IN | 1 + docs/whatsnew/1.2.11-it-IT | 1 + docs/whatsnew/1.2.11-ja-JP | 1 + docs/whatsnew/1.2.11-nl-NL | 1 + docs/whatsnew/1.2.11-pt-PT | 1 + docs/whatsnew/1.2.11-zh-CN | 1 + 13 files changed, 15 insertions(+), 2 deletions(-) create mode 100644 docs/whatsnew/1.2.11-ar create mode 100644 docs/whatsnew/1.2.11-de-DE create mode 100644 docs/whatsnew/1.2.11-en-US create mode 100644 docs/whatsnew/1.2.11-es-ES create mode 100644 docs/whatsnew/1.2.11-fr-FR create mode 100644 docs/whatsnew/1.2.11-hi-IN create mode 100644 docs/whatsnew/1.2.11-it-IT create mode 100644 docs/whatsnew/1.2.11-ja-JP create mode 100644 docs/whatsnew/1.2.11-nl-NL create mode 100644 docs/whatsnew/1.2.11-pt-PT create mode 100644 docs/whatsnew/1.2.11-zh-CN diff --git a/CHANGELOG.md b/CHANGELOG.md index ae4dc36..a04ffc1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,8 @@ Format based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/). ## [Unreleased] +## [1.2.11] - 2026-09-30 + ### Fixed - The glucose screen no longer ends in "This task can't be done while driving" after a few minutes in the foreground. Android Auto allows an app only a handful of screen changes per task and counts an update as free only while the screen's titles stay the same, but the reading and its age were shown as titles, so every refresh used one up. The titles are now fixed labels ("Glucose", "Status") and the reading, delta and timestamps sit beneath them diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 42962bc..958b101 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -14,8 +14,8 @@ android { applicationId = "de.autosugar" minSdk = 26 targetSdk = 37 - versionCode = 15 - versionName = "1.2.10" + versionCode = 16 + versionName = "1.2.11" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } diff --git a/docs/whatsnew/1.2.11-ar b/docs/whatsnew/1.2.11-ar new file mode 100644 index 0000000..2ebf6a9 --- /dev/null +++ b/docs/whatsnew/1.2.11-ar @@ -0,0 +1 @@ +إصلاح خطأ "لا يمكن تنفيذ هذه المهمة أثناء القيادة" الذي كان يظهر بعد بضع دقائق على شاشة الجلوكوز. تظهر القراءة الآن أسفل التسمية الثابتة "الجلوكوز". في السيارات بدون علامات تبويب، بدّل المصدر عبر "تبديل المصدر"؛ ويعمل ذلك الآن مع ثلاثة أو أربعة مصادر أيضًا. diff --git a/docs/whatsnew/1.2.11-de-DE b/docs/whatsnew/1.2.11-de-DE new file mode 100644 index 0000000..1ac807a --- /dev/null +++ b/docs/whatsnew/1.2.11-de-DE @@ -0,0 +1 @@ +Behebt den Fehler „kann nicht während der Fahrt erledigt werden“, der nach einigen Minuten auf dem Glukosebildschirm erschien. Der Wert steht jetzt unter der festen Beschriftung „Blutzucker“. In Autos ohne Tabs wechselst du Quellen über „Quelle wechseln“; das klappt jetzt auch mit drei oder vier Quellen. diff --git a/docs/whatsnew/1.2.11-en-US b/docs/whatsnew/1.2.11-en-US new file mode 100644 index 0000000..fa0473e --- /dev/null +++ b/docs/whatsnew/1.2.11-en-US @@ -0,0 +1 @@ +Fixes the "can't be done while driving" error that appeared after a few minutes on the glucose screen. The reading now sits under a fixed "Glucose" label. On cars without tabs, switch sources via "Switch Source"; this also works with three or four sources now. diff --git a/docs/whatsnew/1.2.11-es-ES b/docs/whatsnew/1.2.11-es-ES new file mode 100644 index 0000000..0e6329b --- /dev/null +++ b/docs/whatsnew/1.2.11-es-ES @@ -0,0 +1 @@ +Corrige el error «no se puede hacer mientras conduces» que aparecía tras unos minutos en la pantalla de glucosa. La lectura aparece ahora bajo la etiqueta fija «Glucosa». En coches sin pestañas, cambia de fuente con «Cambiar fuente»; ahora también funciona con tres o cuatro fuentes. diff --git a/docs/whatsnew/1.2.11-fr-FR b/docs/whatsnew/1.2.11-fr-FR new file mode 100644 index 0000000..2ab9df3 --- /dev/null +++ b/docs/whatsnew/1.2.11-fr-FR @@ -0,0 +1 @@ +Corrige l’erreur « impossible pendant la conduite » qui apparaissait après quelques minutes sur l’écran de glycémie. La valeur s’affiche désormais sous le libellé fixe « Glycémie ». Sur les voitures sans onglets, changez de source via « Changer de source » ; cela fonctionne aussi avec trois ou quatre sources. diff --git a/docs/whatsnew/1.2.11-hi-IN b/docs/whatsnew/1.2.11-hi-IN new file mode 100644 index 0000000..8c8e0b5 --- /dev/null +++ b/docs/whatsnew/1.2.11-hi-IN @@ -0,0 +1 @@ +ग्लूकोज़ स्क्रीन पर कुछ मिनट बाद दिखने वाली "ड्राइविंग के दौरान यह नहीं किया जा सकता" त्रुटि ठीक की गई। रीडिंग अब स्थायी "ग्लूकोज़" लेबल के नीचे दिखती है। बिना टैब वाली कारों में "स्रोत बदलें" से स्रोत बदलें; अब यह तीन या चार स्रोतों के साथ भी काम करता है। diff --git a/docs/whatsnew/1.2.11-it-IT b/docs/whatsnew/1.2.11-it-IT new file mode 100644 index 0000000..304b587 --- /dev/null +++ b/docs/whatsnew/1.2.11-it-IT @@ -0,0 +1 @@ +Corregge l’errore «non è possibile durante la guida» che compariva dopo alcuni minuti sulla schermata della glicemia. Il valore appare ora sotto l’etichetta fissa «Glicemia». Sulle auto senza schede, cambia sorgente con «Cambia sorgente»; ora funziona anche con tre o quattro sorgenti. diff --git a/docs/whatsnew/1.2.11-ja-JP b/docs/whatsnew/1.2.11-ja-JP new file mode 100644 index 0000000..adf4f8a --- /dev/null +++ b/docs/whatsnew/1.2.11-ja-JP @@ -0,0 +1 @@ +血糖値画面を数分表示すると「運転中はこの操作を行えません」と表示される問題を修正しました。測定値は固定ラベル「血糖値」の下に表示されます。タブのない車では「ソース切替」から切り替えます。3〜4個のソースでも動作するようになりました。 diff --git a/docs/whatsnew/1.2.11-nl-NL b/docs/whatsnew/1.2.11-nl-NL new file mode 100644 index 0000000..d9d084f --- /dev/null +++ b/docs/whatsnew/1.2.11-nl-NL @@ -0,0 +1 @@ +Verhelpt de fout ‘kan niet tijdens het rijden’ die na een paar minuten op het glucosescherm verscheen. De meting staat nu onder het vaste label ‘Glucose’. In auto’s zonder tabbladen wissel je van bron via ‘Bron wisselen’; dat werkt nu ook met drie of vier bronnen. diff --git a/docs/whatsnew/1.2.11-pt-PT b/docs/whatsnew/1.2.11-pt-PT new file mode 100644 index 0000000..91b2d7d --- /dev/null +++ b/docs/whatsnew/1.2.11-pt-PT @@ -0,0 +1 @@ +Corrige o erro «não pode ser feito durante a condução» que surgia após alguns minutos no ecrã de glicose. A leitura aparece agora sob a etiqueta fixa «Glicose». Em carros sem separadores, troque de fonte com «Trocar fonte»; agora também funciona com três ou quatro fontes. diff --git a/docs/whatsnew/1.2.11-zh-CN b/docs/whatsnew/1.2.11-zh-CN new file mode 100644 index 0000000..363eaba --- /dev/null +++ b/docs/whatsnew/1.2.11-zh-CN @@ -0,0 +1 @@ +修复了血糖界面显示几分钟后出现“驾驶时无法执行此操作”错误的问题。读数现在显示在固定标签“血糖”下方。在不支持标签页的车辆上,请通过“切换来源”切换;现在三个或四个来源也能正常使用。