From 74835149a05ca0a4df02c8fb790bb8917dac9048 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Wed, 5 Jun 2024 12:34:49 +0200 Subject: [PATCH 01/26] GDA: allow foreground mode --- auto/build.gradle | 6 +-- auto/src/main/AndroidManifest.xml | 2 +- .../glucodataauto/GlucoDataServiceAuto.kt | 48 +++++++++++-------- .../glucodataauto/MainActivity.kt | 7 +-- .../preferences/SettingsFragment.kt | 38 ++++++++++++++- .../main/res/layout-land/activity_main.xml | 2 +- auto/src/main/res/layout/activity_main.xml | 2 +- auto/src/main/res/xml/preferences.xml | 6 +++ .../glucodatahandler/common/Constants.kt | 2 +- common/src/main/res/values-de/strings.xml | 4 +- common/src/main/res/values-es/strings.xml | 3 ++ common/src/main/res/values-pl/strings.xml | 3 ++ common/src/main/res/values-pt/strings.xml | 3 ++ common/src/main/res/values/strings.xml | 3 ++ 14 files changed, 98 insertions(+), 31 deletions(-) diff --git a/auto/build.gradle b/auto/build.gradle index 490c2650..cec29032 100644 --- a/auto/build.gradle +++ b/auto/build.gradle @@ -14,7 +14,7 @@ android { minSdk rootProject.minSdk targetSdk rootProject.targetSdk versionCode 1025 - versionName "1.0-beta1" + versionName "1.0-beta2" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } @@ -73,12 +73,12 @@ android { dependencies { implementation 'androidx.core:core-ktx:1.13.1' - implementation 'androidx.appcompat:appcompat:1.6.1' + implementation 'androidx.appcompat:appcompat:1.7.0' implementation 'com.google.android.material:material:1.12.0' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.joaomgcd:taskerpluginlibrary:0.4.4' implementation project(path: ':common') - implementation "androidx.car.app:app:1.2.0" + implementation "androidx.car.app:app:1.4.0" implementation "androidx.preference:preference:1.2.1" implementation "com.jaredrummler:colorpicker:1.1.0" implementation "androidx.media:media:1.7.0" diff --git a/auto/src/main/AndroidManifest.xml b/auto/src/main/AndroidManifest.xml index 1b7a4cbd..e317c338 100644 --- a/auto/src/main/AndroidManifest.xml +++ b/auto/src/main/AndroidManifest.xml @@ -8,7 +8,7 @@ - + diff --git a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt index 0df8bd2c..98ecafb4 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt @@ -4,6 +4,7 @@ import android.app.Notification import android.app.Service import android.content.Context import android.content.Intent +import android.content.SharedPreferences import android.content.pm.ServiceInfo import android.os.Build import android.os.IBinder @@ -35,27 +36,33 @@ class GlucoDataServiceAuto: Service() { private var dataSyncCount = 0 val connected: Boolean get() = car_connected || CarMediaBrowserService.active fun init(context: Context) { + Log.v(LOG_ID, "init called: init=$init") if(!init) { - Log.v(LOG_ID, "init called") - GlucoDataService.context = context - //TimeTaskService.useWorker = true - //SourceTaskService.useWorker = true - ReceiveData.initData(context) - CarConnection(context.applicationContext).type.observeForever(GlucoDataServiceAuto::onConnectionStateUpdated) + startService(context, false) init = true } } - private fun setForeground(context: Context, foreground: Boolean) { + private fun startService(context: Context, foreground: Boolean) { + try { + val sharedPref = context.getSharedPreferences(Constants.SHARED_PREF_TAG, Context.MODE_PRIVATE) + val isForeground = foreground || sharedPref.getBoolean(Constants.SHARED_PREF_FOREGROUND_SERVICE, false) + val serviceIntent = Intent(context, GlucoDataServiceAuto::class.java) + serviceIntent.putExtra(Constants.SHARED_PREF_FOREGROUND_SERVICE, isForeground) + if (isForeground) + context.startForegroundService(serviceIntent) + else + context.startService(serviceIntent) + } catch (exc: Exception) { + Log.e(LOG_ID, "startService exception: " + exc.toString()) + } + } + + fun setForeground(context: Context, foreground: Boolean) { try { Log.v(LOG_ID, "setForeground called " + foreground) if (isForegroundService != foreground) { - val serviceIntent = Intent(context, GlucoDataServiceAuto::class.java) - serviceIntent.putExtra(Constants.SHARED_PREF_FOREGROUND_SERVICE, foreground) - if (foreground) - context.startForegroundService(serviceIntent) - else - context.startService(serviceIntent) + startService(context, foreground) } } catch (exc: Exception) { Log.e(LOG_ID, "setForeground exception: " + exc.toString()) @@ -161,11 +168,14 @@ class GlucoDataServiceAuto: Service() { } @RequiresApi(Build.VERSION_CODES.Q) - override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int { + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { try { Log.d(LOG_ID, "onStartCommand called") super.onStartCommand(intent, flags, startId) - val isForeground = intent.getBooleanExtra(Constants.SHARED_PREF_FOREGROUND_SERVICE, false) + GlucoDataService.context = applicationContext + ReceiveData.initData(applicationContext) + val sharedPref = getSharedPreferences(Constants.SHARED_PREF_TAG, Context.MODE_PRIVATE) + val isForeground = (if(intent != null) intent.getBooleanExtra(Constants.SHARED_PREF_FOREGROUND_SERVICE, false) else false) || sharedPref.getBoolean(Constants.SHARED_PREF_FOREGROUND_SERVICE, false) if (isForeground && !isForegroundService) { Log.i(LOG_ID, "Starting service in foreground!") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) @@ -178,12 +188,12 @@ class GlucoDataServiceAuto: Service() { Log.i(LOG_ID, "Stopping service in foreground!") stopForeground(STOP_FOREGROUND_REMOVE) } + CarConnection(applicationContext).type.observeForever(GlucoDataServiceAuto::onConnectionStateUpdated) } catch (exc: Exception) { Log.e(LOG_ID, "onStartCommand exception: " + exc.toString()) } - if (isForegroundService) - return START_STICKY // keep alive - return START_NOT_STICKY + + return START_STICKY // keep alive } override fun onDestroy() { @@ -202,7 +212,7 @@ class GlucoDataServiceAuto: Service() { val pendingIntent = PackageUtils.getAppIntent(this, MainActivity::class.java, 11, false) return Notification.Builder(this, ChannelType.ANDROID_AUTO_FOREGROUND.channelId) - .setContentTitle(getString(de.michelinside.glucodatahandler.common.R.string.activity_main_car_connected_label)) + .setContentTitle(getString(de.michelinside.glucodatahandler.common.R.string.gda_foreground_info)) .setSmallIcon(R.mipmap.ic_launcher) .setContentIntent(pendingIntent) .setOngoing(true) diff --git a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt index d8558d79..8980e35a 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt @@ -1,5 +1,6 @@ package de.michelinside.glucodataauto +import android.annotation.SuppressLint import android.app.Activity import android.app.AlarmManager import android.content.Context @@ -257,16 +258,16 @@ class MainActivity : AppCompatActivity(), NotifierInterface { try { val pm = getSystemService(POWER_SERVICE) as PowerManager if (!pm.isIgnoringBatteryOptimizations(packageName)) { - Log.w(LOG_ID, "Battery optimization is inactive") + Log.w(LOG_ID, "Battery optimization is active") txtBatteryOptimization.visibility = View.VISIBLE txtBatteryOptimization.setOnClickListener { - val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS) + val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) intent.data = Uri.parse("package:$packageName") startActivity(intent) } } else { txtBatteryOptimization.visibility = View.GONE - Log.i(LOG_ID, "Battery optimization is active") + Log.i(LOG_ID, "Battery optimization is inactive") } } catch (exc: Exception) { Log.e(LOG_ID, "checkBatteryOptimization exception: " + exc.message.toString() ) diff --git a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragment.kt b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragment.kt index 7caab0e9..84f96632 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragment.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragment.kt @@ -1,14 +1,16 @@ package de.michelinside.glucodataauto.preferences +import android.content.SharedPreferences import android.os.Bundle import android.util.Log import androidx.preference.* import de.michelinside.glucodataauto.BuildConfig +import de.michelinside.glucodataauto.GlucoDataServiceAuto import de.michelinside.glucodataauto.R import de.michelinside.glucodatahandler.common.Constants -class SettingsFragment : PreferenceFragmentCompat() { +class SettingsFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener { private val LOG_ID = "GDH.AA.SettingsFragment" override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { @@ -27,4 +29,38 @@ class SettingsFragment : PreferenceFragmentCompat() { } } + + override fun onResume() { + Log.d(LOG_ID, "onResume called") + try { + super.onResume() + preferenceManager.sharedPreferences?.registerOnSharedPreferenceChangeListener(this) + } catch (exc: Exception) { + Log.e(LOG_ID, "onResume exception: " + exc.toString()) + } + } + + override fun onPause() { + Log.d(LOG_ID, "onPause called") + try { + super.onPause() + preferenceManager.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this) + } catch (exc: Exception) { + Log.e(LOG_ID, "onPause exception: " + exc.toString()) + } + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + Log.d(LOG_ID, "onSharedPreferenceChanged called for " + key) + try { + when(key) { + Constants.SHARED_PREF_FOREGROUND_SERVICE -> { + GlucoDataServiceAuto.setForeground(requireContext(), sharedPreferences!!.getBoolean(Constants.SHARED_PREF_FOREGROUND_SERVICE, false)) + } + } + } catch (exc: Exception) { + Log.e(LOG_ID, "onSharedPreferenceChanged exception: " + exc.toString()) + } + } + } diff --git a/auto/src/main/res/layout-land/activity_main.xml b/auto/src/main/res/layout-land/activity_main.xml index e01487e5..d7ae5bc5 100644 --- a/auto/src/main/res/layout-land/activity_main.xml +++ b/auto/src/main/res/layout-land/activity_main.xml @@ -157,7 +157,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="10dp" - android:text="@string/activity_main_battery_optimization_disabled" + android:text="@string/gda_battery_optimization_disabled" android:textSize="16sp" android:textAlignment="center" /> diff --git a/auto/src/main/res/layout/activity_main.xml b/auto/src/main/res/layout/activity_main.xml index c6b0f994..613d3c10 100644 --- a/auto/src/main/res/layout/activity_main.xml +++ b/auto/src/main/res/layout/activity_main.xml @@ -175,7 +175,7 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginBottom="10dp" - android:text="@string/activity_main_battery_optimization_disabled" + android:text="@string/gda_battery_optimization_disabled" android:textSize="16sp" android:textAlignment="center" /> diff --git a/auto/src/main/res/xml/preferences.xml b/auto/src/main/res/xml/preferences.xml index 0930195b..0bfcac8d 100644 --- a/auto/src/main/res/xml/preferences.xml +++ b/auto/src/main/res/xml/preferences.xml @@ -1,6 +1,12 @@ + Bitte deaktivieren, wenn der Trendpfeil zu groß und dadurch abgeschnitten wird. Oberfläche Allgemeine Einstellung für die Oberfläche von dieser App. - + GlucoDataAuto wird ausgeführt + Aktiviere dies nur, wenn du eine Follower-Quelle und nur Android Auto-Benachrichtigungen verwendest.\nDies verhindert, dass Android diese App schließt, wenn sie nicht mit Android Auto verbunden ist, sodass die App die Android Auto-Verbindung nicht erkennen kann.\nAnstatt diese Einstellung zu aktivieren, kannst du die App auch einmal in Android Auto öffnen, wenn du verbunden bist. + Akkuoptimierungen sind aktiv!\nHier drücken, um es zu deaktivieren. diff --git a/common/src/main/res/values-es/strings.xml b/common/src/main/res/values-es/strings.xml index fbab048b..0c3a7de2 100644 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -483,4 +483,7 @@ Por favor, desactiva esta configuración si la flecha de tendencia es demasiado grande y se corta. Interfaz de usuario Ajustes generales para la interfaz de usuario de esta aplicación. + GlucoDataAuto se está ejecutando + Actívalo solo si estás usando una fuente de seguidor y solo notificaciones de Android Auto.\nEsto evita que Android cierre esta aplicación mientras no esté conectado a Android Auto, por lo que la aplicación no puede reconocer la conexión a Android Auto.\nEn lugar de habilitar esta configuración, también puedes abrir la aplicación en Android Auto una vez, si estás conectado. + La optimización de batería está habilitada!\nPulsa aquí para desactivarlo. \ No newline at end of file diff --git a/common/src/main/res/values-pl/strings.xml b/common/src/main/res/values-pl/strings.xml index 00c089ee..b07e69d3 100644 --- a/common/src/main/res/values-pl/strings.xml +++ b/common/src/main/res/values-pl/strings.xml @@ -476,4 +476,7 @@ Należy sprawdzić, czy strzałka trendu nie jest przycięta i czy nie jest zbyt duża. Interfejs użytkownika Ogólne ustawienia dotyczące interfejsu użytkownika tej aplikacji. + GlucoDataAuto działa + Włącz to tylko wtedy, gdy używasz źródła obserwatora i tylko powiadomień Android Auto.\nTo zapobiega zamknięciu tej aplikacji przez Androida, gdy nie jest podłączona do Android Auto, więc aplikacja nie może rozpoznać połączenia z Android Auto.\nZamiast włączać to ustawienie, możesz również otworzyć aplikację w Android Auto raz, gdy jesteś podłączony. + Optymalizacja baterii jest włączona!\nNaciśnij tutaj, aby to wyłączyć. diff --git a/common/src/main/res/values-pt/strings.xml b/common/src/main/res/values-pt/strings.xml index af896b46..2cba702a 100644 --- a/common/src/main/res/values-pt/strings.xml +++ b/common/src/main/res/values-pt/strings.xml @@ -478,4 +478,7 @@ Você tem que verificar se o tendência está cortado, se fica muito grande. Interface de usuário Configurações gerais da interface do usuário deste aplicativo. + GlucoDataAuto está em execução + Ative isso apenas se você estiver usando uma fonte seguidora e somente notificações do Android Auto.\nIsso impede que o Android feche este aplicativo enquanto não estiver conectado ao Android Auto, para que o aplicativo não possa reconhecer a conexão com o Android Auto.\nEm vez de habilitar esta configuração, você também pode abrir o aplicativo no Android Auto uma vez, se estiver conectado. + Otimização da bateria está habilitada!\nPressione aqui para desativá-lo. diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index b8cedf9b..02e8f7bb 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -493,4 +493,7 @@ Please disable this setting, if the trend arrow is to big and is cut off. User interface General settings for the user interface of this application. + GlucoDataAuto is running + Only enable it, if you are using a follower source and Android Auto notifications only.\nThis prevents Android to close this app, while not connected to Android Auto, so the app can not recognize the Android Auto connection.\nInstead of enable this setting, you can also open the app in Android Auto once, if you are connected. + Battery optimization is enabled!\nPress here to disable it. From 35011febae08f47a69f9cb8a43bc3b78b85e2b3f Mon Sep 17 00:00:00 2001 From: pachi81 Date: Wed, 5 Jun 2024 13:58:06 +0200 Subject: [PATCH 02/26] GDA: add follower summary --- auto/src/main/res/xml/sources.xml | 5 +++++ common/src/main/res/values-de/strings.xml | 1 + common/src/main/res/values-es/strings.xml | 1 + common/src/main/res/values-pl/strings.xml | 1 + common/src/main/res/values-pt/strings.xml | 1 + common/src/main/res/values/strings.xml | 1 + 6 files changed, 10 insertions(+) diff --git a/auto/src/main/res/xml/sources.xml b/auto/src/main/res/xml/sources.xml index 21944048..ea566fa0 100644 --- a/auto/src/main/res/xml/sources.xml +++ b/auto/src/main/res/xml/sources.xml @@ -63,6 +63,11 @@ android:title="@string/source_delay" android:summary="@string/source_delay_summary" app:iconSpaceReserved="false" /> + GlucoDataAuto wird ausgeführt Aktiviere dies nur, wenn du eine Follower-Quelle und nur Android Auto-Benachrichtigungen verwendest.\nDies verhindert, dass Android diese App schließt, wenn sie nicht mit Android Auto verbunden ist, sodass die App die Android Auto-Verbindung nicht erkennen kann.\nAnstatt diese Einstellung zu aktivieren, kannst du die App auch einmal in Android Auto öffnen, wenn du verbunden bist. Akkuoptimierungen sind aktiv!\nHier drücken, um es zu deaktivieren. + Wenn du eine Follower-Quelle verwendest, wird die App möglicherweise nicht gestartet, wenn du mit Android Auto verbunden bist und nur Android Auto-Benachrichtigungen verwendest.\nUm sicherzustellen, dass die App die Android Auto-Verbindung erkennt, musst du die Akkuoptimierung deaktivieren.\nWenn es immer noch nicht funktioniert, kannst du auch den Vordergrundmodus aktivieren oder die App einmal in Android Auto öffnen, wenn sie mit Android Auto verbunden ist. diff --git a/common/src/main/res/values-es/strings.xml b/common/src/main/res/values-es/strings.xml index 0c3a7de2..70313bb7 100644 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -486,4 +486,5 @@ GlucoDataAuto se está ejecutando Actívalo solo si estás usando una fuente de seguidor y solo notificaciones de Android Auto.\nEsto evita que Android cierre esta aplicación mientras no esté conectado a Android Auto, por lo que la aplicación no puede reconocer la conexión a Android Auto.\nEn lugar de habilitar esta configuración, también puedes abrir la aplicación en Android Auto una vez, si estás conectado. La optimización de batería está habilitada!\nPulsa aquí para desactivarlo. + Si estás usando una fuente de seguidor, la aplicación puede no iniciarse mientras estés conectado a Android Auto, si solo usas notificaciones de Android Auto.\nPara asegurarte de que la aplicación detecte la conexión de Android Auto, tienes que desactivar la optimización de batería.\nSi aún no funciona, también puedes habilitar el modo de primer plano o tienes que abrir la aplicación en Android Auto una vez, cuando esté conectado a Android Auto. \ No newline at end of file diff --git a/common/src/main/res/values-pl/strings.xml b/common/src/main/res/values-pl/strings.xml index b07e69d3..7e1ef436 100644 --- a/common/src/main/res/values-pl/strings.xml +++ b/common/src/main/res/values-pl/strings.xml @@ -479,4 +479,5 @@ GlucoDataAuto działa Włącz to tylko wtedy, gdy używasz źródła obserwatora i tylko powiadomień Android Auto.\nTo zapobiega zamknięciu tej aplikacji przez Androida, gdy nie jest podłączona do Android Auto, więc aplikacja nie może rozpoznać połączenia z Android Auto.\nZamiast włączać to ustawienie, możesz również otworzyć aplikację w Android Auto raz, gdy jesteś podłączony. Optymalizacja baterii jest włączona!\nNaciśnij tutaj, aby to wyłączyć. + Jeśli używasz źródła obserwatora, aplikacja może nie zostać uruchomiona podczas połączenia z Android Auto, jeśli używasz tylko powiadomień Android Auto.\nAby upewnić się, że aplikacja wykrywa połączenie z Android Auto, musisz wyłączyć optymalizację baterii.\nJeśli to nadal nie działa, możesz również włączyć tryb pierwszoplanowy lub otworzyć aplikację w Android Auto raz, gdy jest podłączona do Android Auto. diff --git a/common/src/main/res/values-pt/strings.xml b/common/src/main/res/values-pt/strings.xml index 2cba702a..66a4b6b9 100644 --- a/common/src/main/res/values-pt/strings.xml +++ b/common/src/main/res/values-pt/strings.xml @@ -481,4 +481,5 @@ GlucoDataAuto está em execução Ative isso apenas se você estiver usando uma fonte seguidora e somente notificações do Android Auto.\nIsso impede que o Android feche este aplicativo enquanto não estiver conectado ao Android Auto, para que o aplicativo não possa reconhecer a conexão com o Android Auto.\nEm vez de habilitar esta configuração, você também pode abrir o aplicativo no Android Auto uma vez, se estiver conectado. Otimização da bateria está habilitada!\nPressione aqui para desativá-lo. + Se você estiver usando uma fonte seguidora, o aplicativo pode não ser iniciado enquanto estiver conectado ao Android Auto, se você estiver usando apenas notificações do Android Auto.\nPara garantir que o aplicativo detecte a conexão com o Android Auto, você deve desativar a otimização da bateria.\nSe ainda não funcionar, você também pode habilitar o modo de primeiro plano ou abrir o aplicativo no Android Auto uma vez, quando estiver conectado ao Android Auto. diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 02e8f7bb..95d5be51 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -496,4 +496,5 @@ GlucoDataAuto is running Only enable it, if you are using a follower source and Android Auto notifications only.\nThis prevents Android to close this app, while not connected to Android Auto, so the app can not recognize the Android Auto connection.\nInstead of enable this setting, you can also open the app in Android Auto once, if you are connected. Battery optimization is enabled!\nPress here to disable it. + If you are using a follower source, the app may not be started while connected to Android Auto, if you are using Android Auto Notifications only.\nTo make sure, the app detects Android Auto connection you have to disable battery optimization.\nIf it still not work, you can als enable foreground mode or you have to open the app in Android Auto once, if it is connected to Android Auto. From 0921d1ff3cdfc52f1610de2840f2b4124841fce0 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Wed, 5 Jun 2024 13:58:20 +0200 Subject: [PATCH 03/26] GDA: fix datasync --- .../glucodataauto/GlucoDataServiceAuto.kt | 23 +++++++++-------- .../glucodataauto/MainActivity.kt | 25 ++++--------------- .../preferences/SourceFragment.kt | 2 ++ .../common/tasks/DataSourceTask.kt | 2 +- common/src/main/res/values-de/strings.xml | 4 +-- 5 files changed, 23 insertions(+), 33 deletions(-) diff --git a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt index 98ecafb4..a774fc78 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt @@ -4,7 +4,6 @@ import android.app.Notification import android.app.Service import android.content.Context import android.content.Intent -import android.content.SharedPreferences import android.content.pm.ServiceInfo import android.os.Build import android.os.IBinder @@ -38,6 +37,7 @@ class GlucoDataServiceAuto: Service() { fun init(context: Context) { Log.v(LOG_ID, "init called: init=$init") if(!init) { + GlucoDataService.context = context startService(context, false) init = true } @@ -54,7 +54,7 @@ class GlucoDataServiceAuto: Service() { else context.startService(serviceIntent) } catch (exc: Exception) { - Log.e(LOG_ID, "startService exception: " + exc.toString()) + Log.e(LOG_ID, "startService exception: " + exc.message.toString() + "\n" + exc.stackTraceToString()) } } @@ -65,13 +65,14 @@ class GlucoDataServiceAuto: Service() { startService(context, foreground) } } catch (exc: Exception) { - Log.e(LOG_ID, "setForeground exception: " + exc.toString()) + Log.e(LOG_ID, "setForeground exception: " + exc.message.toString() + "\n" + exc.stackTraceToString()) } } fun start(context: Context) { try { if(!running) { + init(context) Log.i(LOG_ID, "starting") CarNotification.enable(context) startDataSync(context) @@ -79,7 +80,7 @@ class GlucoDataServiceAuto: Service() { running = true } } catch (exc: Exception) { - Log.e(LOG_ID, "start exception: " + exc.toString()) + Log.e(LOG_ID, "start exception: " + exc.message.toString() + "\n" + exc.stackTraceToString()) } } @@ -93,34 +94,36 @@ class GlucoDataServiceAuto: Service() { running = false } } catch (exc: Exception) { - Log.e(LOG_ID, "stop exception: " + exc.toString()) + Log.e(LOG_ID, "stop exception: " + exc.message.toString() + "\n" + exc.stackTraceToString()) } } fun startDataSync(context: Context) { try { + Log.i(LOG_ID, "starting datasync - count=$dataSyncCount") if (dataSyncCount == 0) { - Log.d(LOG_ID, "startDataSync count: $dataSyncCount") TimeTaskService.run(context) SourceTaskService.run(context) sendStateBroadcast(context, true) + Log.i(LOG_ID, "Datasync started") } dataSyncCount++ } catch (exc: Exception) { - Log.e(LOG_ID, "startDataSync exception: " + exc.toString()) + Log.e(LOG_ID, "startDataSync exception: " + exc.message.toString() + "\n" + exc.stackTraceToString()) } } fun stopDataSync(context: Context) { try { dataSyncCount-- + Log.i(LOG_ID, "stopping datasync - count=$dataSyncCount") if (dataSyncCount == 0) { - Log.d(LOG_ID, "stopDataSync") sendStateBroadcast(context, false) BackgroundWorker.stopAllWork(context) + Log.i(LOG_ID, "Datasync stopped") } } catch (exc: Exception) { - Log.e(LOG_ID, "stopDataSync exception: " + exc.toString()) + Log.e(LOG_ID, "stopDataSync exception: " + exc.message.toString() + "\n" + exc.stackTraceToString()) } } @@ -190,7 +193,7 @@ class GlucoDataServiceAuto: Service() { } CarConnection(applicationContext).type.observeForever(GlucoDataServiceAuto::onConnectionStateUpdated) } catch (exc: Exception) { - Log.e(LOG_ID, "onStartCommand exception: " + exc.toString()) + Log.e(LOG_ID, "onStartCommand exception: " + exc.message.toString() + "\n" + exc.stackTraceToString()) } return START_STICKY // keep alive diff --git a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt index 8980e35a..5b298a2c 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt @@ -1,6 +1,5 @@ package de.michelinside.glucodataauto -import android.annotation.SuppressLint import android.app.Activity import android.app.AlarmManager import android.content.Context @@ -70,7 +69,6 @@ class MainActivity : AppCompatActivity(), NotifierInterface { private lateinit var btnSources: Button private lateinit var txtNoData: TextView private lateinit var sharedPref: SharedPreferences - private var menuOpen = false private var notificationIcon: MenuItem? = null private val LOG_ID = "GDH.AA.Main" private var requestNotificationPermission = false @@ -142,11 +140,10 @@ class MainActivity : AppCompatActivity(), NotifierInterface { override fun onPause() { try { + Log.d(LOG_ID, "onPause called") super.onPause() InternalNotifier.remNotifier(this, this) - if(!menuOpen) - GlucoDataServiceAuto.stopDataSync(this) - Log.v(LOG_ID, "onPause called") + GlucoDataServiceAuto.stopDataSync(this) } catch (exc: Exception) { Log.e(LOG_ID, "onPause exception: " + exc.message.toString() ) } @@ -154,8 +151,8 @@ class MainActivity : AppCompatActivity(), NotifierInterface { override fun onResume() { try { + Log.d(LOG_ID, "onResume called") super.onResume() - Log.v(LOG_ID, "onResume called") update() InternalNotifier.addNotifier( this, this, mutableSetOf( NotifySource.BROADCAST, @@ -166,7 +163,7 @@ class MainActivity : AppCompatActivity(), NotifierInterface { NotifySource.NODE_BATTERY_LEVEL, NotifySource.SETTINGS, NotifySource.CAR_CONNECTION, - NotifySource.OBSOLETE_VALUE, + NotifySource.TIME_VALUE, NotifySource.SOURCE_STATE_CHANGE)) checkExactAlarmPermission() checkBatteryOptimization() @@ -176,21 +173,12 @@ class MainActivity : AppCompatActivity(), NotifierInterface { requestNotificationPermission = false txtNotificationPermission.visibility = View.GONE } - if(!menuOpen) - GlucoDataServiceAuto.startDataSync(this) - menuOpen = false + GlucoDataServiceAuto.startDataSync(this) } catch (exc: Exception) { Log.e(LOG_ID, "onResume exception: " + exc.message.toString() ) } } - private val requestPermissionLauncher = - registerForActivityResult( - ActivityResultContracts.RequestPermission() - ) { isGranted: Boolean -> - Log.d(LOG_ID, "Notification permission allowed: $isGranted") - } - fun requestPermission() : Boolean { requestNotificationPermission = false if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { @@ -306,20 +294,17 @@ class MainActivity : AppCompatActivity(), NotifierInterface { Log.v(LOG_ID, "onOptionsItemSelected for " + item.itemId.toString()) when(item.itemId) { R.id.action_settings -> { - menuOpen = true val intent = Intent(this, SettingsActivity::class.java) startActivity(intent) return true } R.id.action_sources -> { - menuOpen = true val intent = Intent(this, SettingsActivity::class.java) intent.putExtra(SettingsActivity.FRAGMENT_EXTRA, SettingsFragmentClass.SORUCE_FRAGMENT.value) startActivity(intent) return true } R.id.action_alarms -> { - menuOpen = true val intent = Intent(this, SettingsActivity::class.java) intent.putExtra(SettingsActivity.FRAGMENT_EXTRA, SettingsFragmentClass.ALARM_FRAGMENT.value) startActivity(intent) diff --git a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SourceFragment.kt b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SourceFragment.kt index 07a116f3..f0dede6c 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SourceFragment.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SourceFragment.kt @@ -61,6 +61,7 @@ class SourceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPre preferenceManager.sharedPreferences?.registerOnSharedPreferenceChangeListener(this) updateEnableStates(preferenceManager.sharedPreferences!!) InternalNotifier.addNotifier(requireContext(), this, mutableSetOf(NotifySource.PATIENT_DATA_CHANGED)) + //GlucoDataServiceAuto.startDataSync(requireContext()) super.onResume() } catch (exc: Exception) { Log.e(LOG_ID, "onResume exception: " + exc.toString()) @@ -72,6 +73,7 @@ class SourceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPre try { preferenceManager.sharedPreferences?.unregisterOnSharedPreferenceChangeListener(this) InternalNotifier.remNotifier(requireContext(), this) + //GlucoDataServiceAuto.stopDataSync(requireContext()) super.onPause() } catch (exc: Exception) { Log.e(LOG_ID, "onPause exception: " + exc.toString()) diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/DataSourceTask.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/DataSourceTask.kt index 31ebf139..91e31e7a 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/DataSourceTask.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/DataSourceTask.kt @@ -322,7 +322,7 @@ abstract class DataSourceTask(private val enabledKey: String, protected val sour } override fun checkPreferenceChanged(sharedPreferences: SharedPreferences, key: String?, context: Context): Boolean { - Log.v(LOG_ID, "checkPreferenceChanged for $key") + Log.d(LOG_ID, "checkPreferenceChanged for $key") if(key == null) { enabled = sharedPreferences.getBoolean(enabledKey, false) interval = sharedPreferences.getString(Constants.SHARED_PREF_SOURCE_INTERVAL, "1")?.toLong() ?: 1L diff --git a/common/src/main/res/values-de/strings.xml b/common/src/main/res/values-de/strings.xml index 78d17f25..e2ba8c9e 100644 --- a/common/src/main/res/values-de/strings.xml +++ b/common/src/main/res/values-de/strings.xml @@ -469,7 +469,7 @@ Oberfläche Allgemeine Einstellung für die Oberfläche von dieser App. GlucoDataAuto wird ausgeführt - Aktiviere dies nur, wenn du eine Follower-Quelle und nur Android Auto-Benachrichtigungen verwendest.\nDies verhindert, dass Android diese App schließt, wenn sie nicht mit Android Auto verbunden ist, sodass die App die Android Auto-Verbindung nicht erkennen kann.\nAnstatt diese Einstellung zu aktivieren, kannst du die App auch einmal in Android Auto öffnen, wenn du verbunden bist. + Aktiviere dies nur, wenn du eine Online Datenquelle und nur Android Auto-Benachrichtigungen verwendest.\nDies verhindert, dass Android diese App schließt, wenn sie nicht mit Android Auto verbunden ist, sodass die App die Android Auto-Verbindung nicht erkennen kann.\nAnstatt diese Einstellung zu aktivieren, kannst du die App auch einmal in Android Auto öffnen, wenn du verbunden bist. Akkuoptimierungen sind aktiv!\nHier drücken, um es zu deaktivieren. - Wenn du eine Follower-Quelle verwendest, wird die App möglicherweise nicht gestartet, wenn du mit Android Auto verbunden bist und nur Android Auto-Benachrichtigungen verwendest.\nUm sicherzustellen, dass die App die Android Auto-Verbindung erkennt, musst du die Akkuoptimierung deaktivieren.\nWenn es immer noch nicht funktioniert, kannst du auch den Vordergrundmodus aktivieren oder die App einmal in Android Auto öffnen, wenn sie mit Android Auto verbunden ist. + Wenn du eine Online Datenquelle verwendest, wird die App möglicherweise nicht gestartet, wenn du mit Android Auto verbunden bist und nur Android Auto-Benachrichtigungen verwendest.\nUm sicherzustellen, dass die App die Android Auto-Verbindung erkennt, musst du die Akkuoptimierung deaktivieren.\nWenn es immer noch nicht funktioniert, kannst du auch den Vordergrundmodus aktivieren oder die App einmal in Android Auto öffnen, wenn sie mit Android Auto verbunden ist. From 213de44d19855745830298ed26ea67cad61c02c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arkadiusz=20Deli=C5=9B?= <137992536+froster82@users.noreply.github.com> Date: Wed, 5 Jun 2024 19:08:04 +0200 Subject: [PATCH 04/26] Update strings.xml PL --- common/src/main/res/values-pl/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/main/res/values-pl/strings.xml b/common/src/main/res/values-pl/strings.xml index 7e1ef436..c22d0f5a 100644 --- a/common/src/main/res/values-pl/strings.xml +++ b/common/src/main/res/values-pl/strings.xml @@ -477,7 +477,7 @@ Interfejs użytkownika Ogólne ustawienia dotyczące interfejsu użytkownika tej aplikacji. GlucoDataAuto działa - Włącz to tylko wtedy, gdy używasz źródła obserwatora i tylko powiadomień Android Auto.\nTo zapobiega zamknięciu tej aplikacji przez Androida, gdy nie jest podłączona do Android Auto, więc aplikacja nie może rozpoznać połączenia z Android Auto.\nZamiast włączać to ustawienie, możesz również otworzyć aplikację w Android Auto raz, gdy jesteś podłączony. - Optymalizacja baterii jest włączona!\nNaciśnij tutaj, aby to wyłączyć. - Jeśli używasz źródła obserwatora, aplikacja może nie zostać uruchomiona podczas połączenia z Android Auto, jeśli używasz tylko powiadomień Android Auto.\nAby upewnić się, że aplikacja wykrywa połączenie z Android Auto, musisz wyłączyć optymalizację baterii.\nJeśli to nadal nie działa, możesz również włączyć tryb pierwszoplanowy lub otworzyć aplikację w Android Auto raz, gdy jest podłączona do Android Auto. + Włącz tę opcję tylko wtedy, gdy jako źródła używasz funkcji „follower” (obserwatora) i wyłącznie powiadomień z Android Auto.\nZapobiega to zamknięciu tej aplikacji przez system Android, gdy nie jest podłączona do Android Auto, więc aplikacja nie może rozpoznać połączenia z Android Auto.\nZamiast włączać to ustawienie, możesz również otworzyć aplikację w Android Auto raz, gdy jesteś już podłączony. + Optymalizacja baterii jest włączona!\nNaciśnij tutaj, aby ją wyłączyć. + Jeżeli jako źródła używasz funkcji „follower” (obserwatora), aplikacja może nie zostać uruchomiona podczas połączenia z Android Auto, gdy używa się wyłącznie powiadomień z Android Auto.\nAby upewnić się, że aplikacja wykrywa połączenie z Android Auto, należy wyłączyć optymalizację baterii.\nJeśli to nadal nie działa, można również włączyć tryb pierwszoplanowy lub otworzyć aplikację w Android Auto raz, gdy jest podłączona do Android Auto. From 64438da7236027d2f44c04d422fc6ca5a5cf7b95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arkadiusz=20Deli=C5=9B?= <137992536+froster82@users.noreply.github.com> Date: Wed, 5 Jun 2024 19:10:50 +0200 Subject: [PATCH 05/26] Update strings.xml small corrections to ENG --- common/src/main/res/values/strings.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 95d5be51..816b636a 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -494,7 +494,7 @@ User interface General settings for the user interface of this application. GlucoDataAuto is running - Only enable it, if you are using a follower source and Android Auto notifications only.\nThis prevents Android to close this app, while not connected to Android Auto, so the app can not recognize the Android Auto connection.\nInstead of enable this setting, you can also open the app in Android Auto once, if you are connected. + Only enable it, if you are using a follower source and Android Auto notifications only.\nThis prevents Android from closing this app, while not connected to Android Auto, so the app can not recognize the Android Auto connection.\nInstead of enabling this setting, you can also open the app in Android Auto once, if you are connected. Battery optimization is enabled!\nPress here to disable it. - If you are using a follower source, the app may not be started while connected to Android Auto, if you are using Android Auto Notifications only.\nTo make sure, the app detects Android Auto connection you have to disable battery optimization.\nIf it still not work, you can als enable foreground mode or you have to open the app in Android Auto once, if it is connected to Android Auto. + If you are using a follower source, the app may not be started while connected to Android Auto, if you are using Android Auto Notifications only.\nTo make sure the app detects Android Auto connection you have to disable battery optimization.\nIf it still does not work, you can also enable foreground mode or you have to open the app in Android Auto once, if it is connected to Android Auto. From df4bbda8000373ec81d78a975a00cfd1fb2a9e93 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Thu, 6 Jun 2024 08:54:16 +0200 Subject: [PATCH 06/26] GDA: request notification permission --- .../glucodataauto/MainActivity.kt | 29 +++++++++++++++---- .../preferences/SettingsFragmentBase.kt | 25 ++++++++++++++-- .../notification/AlarmNotificationBase.kt | 13 ++++----- .../common/notification/Channels.kt | 19 ++++++++++++ 4 files changed, 72 insertions(+), 14 deletions(-) diff --git a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt index 5b298a2c..ed40b2c8 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt @@ -38,6 +38,8 @@ import de.michelinside.glucodatahandler.common.SourceStateData import de.michelinside.glucodatahandler.common.WearPhoneConnection import de.michelinside.glucodatahandler.common.notification.AlarmHandler import de.michelinside.glucodatahandler.common.notification.AlarmType +import de.michelinside.glucodatahandler.common.notification.ChannelType +import de.michelinside.glucodatahandler.common.notification.Channels import de.michelinside.glucodatahandler.common.notifier.DataSource import de.michelinside.glucodatahandler.common.notifier.InternalNotifier import de.michelinside.glucodatahandler.common.notifier.NotifierInterface @@ -281,7 +283,15 @@ class MainActivity : AppCompatActivity(), NotifierInterface { private fun updateNotificationIcon() { try { if(notificationIcon != null) { - val enabled = sharedPref.getBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false) + var enabled = sharedPref.getBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false) + if(enabled && !Channels.notificationChannelActive(this, ChannelType.ANDROID_AUTO)) { + Log.i(LOG_ID, "Disable car notification as there is no permission!") + with(sharedPref.edit()) { + putBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false) + apply() + } + enabled = false + } notificationIcon!!.icon = ContextCompat.getDrawable(this, if(enabled) R.drawable.icon_popup_white else R.drawable.icon_popup_off_white) } } catch (exc: Exception) { @@ -339,11 +349,20 @@ class MainActivity : AppCompatActivity(), NotifierInterface { } R.id.action_notification_toggle -> { Log.v(LOG_ID, "notification toggle") - with(sharedPref.edit()) { - putBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, !sharedPref.getBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false)) - apply() + if(!sharedPref.getBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false) && !Channels.notificationChannelActive(this, ChannelType.ANDROID_AUTO)) + { + val intent: Intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, this.packageName) + if (Channels.notificationActive(this)) // only the channel is inactive! + intent.putExtra(Settings.EXTRA_CHANNEL_ID, ChannelType.ANDROID_AUTO.channelId) + startActivity(intent) + } else { + with(sharedPref.edit()) { + putBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, !sharedPref.getBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false)) + apply() + } + updateNotificationIcon() } - updateNotificationIcon() } else -> return super.onOptionsItemSelected(item) } diff --git a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt index b4dfe19b..cf099f9a 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt @@ -1,12 +1,16 @@ package de.michelinside.glucodataauto.preferences +import android.content.Intent import android.content.SharedPreferences import android.os.Bundle +import android.provider.Settings import android.util.Log import androidx.core.content.ContextCompat import androidx.preference.* import de.michelinside.glucodatahandler.common.Constants import de.michelinside.glucodataauto.R +import de.michelinside.glucodatahandler.common.notification.ChannelType +import de.michelinside.glucodatahandler.common.notification.Channels abstract class SettingsFragmentBase(private val prefResId: Int) : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener { @@ -107,13 +111,30 @@ class GDASettingsFragment: SettingsFragmentBase(R.xml.pref_gda) { override fun updatePreferences() { super.updatePreferences() val pref = findPreference(Constants.SHARED_PREF_CAR_NOTIFICATION) ?: return + if (pref.isChecked && !Channels.notificationChannelActive(requireContext(), ChannelType.ANDROID_AUTO)) { + Log.i(LOG_ID, "Disable car notification as there is no permission!") + pref.isChecked = false + with(preferenceManager.sharedPreferences!!.edit()) { + putBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false) + apply() + } + } pref.icon = ContextCompat.getDrawable(requireContext(), if(pref.isChecked) R.drawable.icon_popup else R.drawable.icon_popup_off) } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { super.onSharedPreferenceChanged(sharedPreferences, key) - if(key == Constants.SHARED_PREF_CAR_NOTIFICATION) - updatePreferences() + if(key == Constants.SHARED_PREF_CAR_NOTIFICATION) { + if (preferenceManager.sharedPreferences!!.getBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false) && !Channels.notificationChannelActive(requireContext(), ChannelType.ANDROID_AUTO)) { + val intent: Intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) + if (Channels.notificationActive(requireContext())) // only the channel is inactive! + intent.putExtra(Settings.EXTRA_CHANNEL_ID, ChannelType.ANDROID_AUTO.channelId) + startActivity(intent) + } else { + updatePreferences() + } + } } } \ No newline at end of file diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt index 89312256..dbac47ed 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt @@ -568,12 +568,7 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha } fun channelActive(context: Context): Boolean { - if(Utils.checkPermission(context, android.Manifest.permission.POST_NOTIFICATIONS, Build.VERSION_CODES.TIRAMISU)) { - val channel = Channels.getNotificationManager(context).getNotificationChannel(getChannelId()) - Log.d(LOG_ID, "Channel: prio=${channel.importance}") - return (channel.importance > NotificationManager.IMPORTANCE_NONE) - } - return false + return Channels.notificationChannelActive(context, getChannel()) } protected fun checkRecreateSound() { @@ -610,8 +605,12 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha } } + fun getChannel(): ChannelType { + return ChannelType.ALARM + } + fun getChannelId(): String { - return ChannelType.ALARM.channelId + return getChannel().channelId } fun getAlarmSoundRes(alarmType: AlarmType): Int? { diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/notification/Channels.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/notification/Channels.kt index 0feade11..0038eaea 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/notification/Channels.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/notification/Channels.kt @@ -1,11 +1,15 @@ package de.michelinside.glucodatahandler.common.notification +import android.annotation.SuppressLint import android.app.Notification import android.app.NotificationChannel import android.app.NotificationManager import android.content.Context +import android.os.Build +import android.util.Log import de.michelinside.glucodatahandler.common.GlucoDataService import de.michelinside.glucodatahandler.common.R +import de.michelinside.glucodatahandler.common.utils.Utils enum class ChannelType(val channelId: String, val nameResId: Int, val descrResId: Int, val importance: Int = NotificationManager.IMPORTANCE_DEFAULT) { MOBILE_FOREGROUND("GDH_foreground", R.string.mobile_foreground_notification_name, R.string.mobile_foreground_notification_descr ), @@ -17,6 +21,7 @@ enum class ChannelType(val channelId: String, val nameResId: Int, val descrResId ALARM("gdh_alarm_notification_channel", R.string.alarm_notification_name, R.string.alarm_notification_descr, NotificationManager.IMPORTANCE_MAX ); } object Channels { + private val LOG_ID = "GDH.Channels" private var notificationMgr: NotificationManager? = null private val obsoleteNotifications = mutableSetOf( @@ -60,4 +65,18 @@ object Channels { fun deleteNotificationChannel(context: Context, type: ChannelType) { getNotificationManager(context).deleteNotificationChannel(type.channelId) } + + @SuppressLint("InlinedApi") + fun notificationActive(context: Context): Boolean { + return Utils.checkPermission(context, android.Manifest.permission.POST_NOTIFICATIONS, Build.VERSION_CODES.TIRAMISU) + } + + fun notificationChannelActive(context: Context, type: ChannelType): Boolean { + if(notificationActive(context)) { + val channel = Channels.getNotificationManager(context).getNotificationChannel(type.channelId) + Log.d(LOG_ID, "Channel: prio=${channel.importance}") + return (channel.importance > NotificationManager.IMPORTANCE_NONE) + } + return false + } } \ No newline at end of file From d4faf552e001cf4fc55c2a9a6554d3d98b4c517d Mon Sep 17 00:00:00 2001 From: pachi81 Date: Thu, 6 Jun 2024 09:36:07 +0200 Subject: [PATCH 07/26] GDA: help added --- auto/build.gradle | 2 +- .../glucodataauto/MainActivity.kt | 7 ++++- .../preferences/AppSettingsActivity.kt | 11 +++++++- .../glucodataauto/preferences/HelpFragment.kt | 22 +++++++++++++++ .../preferences/SettingsFragmentBase.kt | 2 +- auto/src/main/res/menu/menu_items.xml | 7 +++++ auto/src/main/res/xml/alarms.xml | 2 +- auto/src/main/res/xml/help.xml | 27 +++++++++++++++++++ common/src/main/res/values-de/strings.xml | 8 ++++++ common/src/main/res/values-es/strings.xml | 8 ++++++ common/src/main/res/values-pl/strings.xml | 8 ++++++ common/src/main/res/values-pt/strings.xml | 8 ++++++ common/src/main/res/values/strings.xml | 8 ++++++ 13 files changed, 115 insertions(+), 5 deletions(-) create mode 100644 auto/src/main/java/de/michelinside/glucodataauto/preferences/HelpFragment.kt create mode 100644 auto/src/main/res/xml/help.xml diff --git a/auto/build.gradle b/auto/build.gradle index cec29032..dcfe53ab 100644 --- a/auto/build.gradle +++ b/auto/build.gradle @@ -14,7 +14,7 @@ android { minSdk rootProject.minSdk targetSdk rootProject.targetSdk versionCode 1025 - versionName "1.0-beta2" + versionName "1.0-beta3" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt index ed40b2c8..98e8a27f 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt @@ -21,7 +21,6 @@ import android.widget.ImageView import android.widget.TableLayout import android.widget.TableRow import android.widget.TextView -import androidx.activity.result.contract.ActivityResultContracts import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import androidx.core.content.ContextCompat @@ -320,6 +319,12 @@ class MainActivity : AppCompatActivity(), NotifierInterface { startActivity(intent) return true } + R.id.action_gda_help -> { + val intent = Intent(this, SettingsActivity::class.java) + intent.putExtra(SettingsActivity.FRAGMENT_EXTRA, SettingsFragmentClass.HELP_FRAGMENT.value) + startActivity(intent) + return true + } R.id.action_help -> { val browserIntent = Intent( Intent.ACTION_VIEW, diff --git a/auto/src/main/java/de/michelinside/glucodataauto/preferences/AppSettingsActivity.kt b/auto/src/main/java/de/michelinside/glucodataauto/preferences/AppSettingsActivity.kt index a4e20657..8acaefc9 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/preferences/AppSettingsActivity.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/preferences/AppSettingsActivity.kt @@ -12,7 +12,8 @@ import de.michelinside.glucodatahandler.common.R as RC enum class SettingsFragmentClass(val value: Int, val titleRes: Int) { SETTINGS_FRAGMENT(0, RC.string.menu_settings), SORUCE_FRAGMENT(1, RC.string.menu_sources), - ALARM_FRAGMENT(2, RC.string.menu_alarms) + ALARM_FRAGMENT(2, RC.string.menu_alarms), + HELP_FRAGMENT(3, RC.string.menu_help), } class SettingsActivity : AppCompatActivity(), PreferenceFragmentCompat.OnPreferenceStartFragmentCallback { @@ -51,6 +52,14 @@ class SettingsActivity : AppCompatActivity(), .replace(R.id.content, AlarmFragment()) .commit() } + + SettingsFragmentClass.HELP_FRAGMENT.value -> { + this.supportActionBar!!.title = + this.applicationContext.resources.getText(SettingsFragmentClass.HELP_FRAGMENT.titleRes) + supportFragmentManager.beginTransaction() + .replace(R.id.content, HelpFragment()) + .commit() + } } } diff --git a/auto/src/main/java/de/michelinside/glucodataauto/preferences/HelpFragment.kt b/auto/src/main/java/de/michelinside/glucodataauto/preferences/HelpFragment.kt new file mode 100644 index 00000000..031d2262 --- /dev/null +++ b/auto/src/main/java/de/michelinside/glucodataauto/preferences/HelpFragment.kt @@ -0,0 +1,22 @@ +package de.michelinside.glucodataauto.preferences + +import android.os.Bundle +import android.util.Log +import androidx.preference.* +import de.michelinside.glucodatahandler.common.Constants +import de.michelinside.glucodataauto.R + + +class HelpFragment() : PreferenceFragmentCompat() { + protected val LOG_ID = "GDH.AA.HelpFragment" + + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + Log.d(LOG_ID, "onCreatePreferences called") + try { + preferenceManager.sharedPreferencesName = Constants.SHARED_PREF_TAG + setPreferencesFromResource(R.xml.help, rootKey) + } catch (exc: Exception) { + Log.e(LOG_ID, "onCreatePreferences exception: " + exc.toString()) + } + } +} \ No newline at end of file diff --git a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt index cf099f9a..06ef52a8 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt @@ -14,7 +14,7 @@ import de.michelinside.glucodatahandler.common.notification.Channels abstract class SettingsFragmentBase(private val prefResId: Int) : PreferenceFragmentCompat(), SharedPreferences.OnSharedPreferenceChangeListener { - protected val LOG_ID = "GDH.SettingsFragmentBase" + protected val LOG_ID = "GDH.AA.SettingsFragmentBase" private val updateEnablePrefs = mutableSetOf() override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { diff --git a/auto/src/main/res/menu/menu_items.xml b/auto/src/main/res/menu/menu_items.xml index 7e66a17b..ffe988d8 100644 --- a/auto/src/main/res/menu/menu_items.xml +++ b/auto/src/main/res/menu/menu_items.xml @@ -29,6 +29,13 @@ android:title="@string/menu_alarms" app:showAsAction="never" /> + + + + + + + + + + + \ No newline at end of file diff --git a/common/src/main/res/values-de/strings.xml b/common/src/main/res/values-de/strings.xml index e2ba8c9e..3aa77c2b 100644 --- a/common/src/main/res/values-de/strings.xml +++ b/common/src/main/res/values-de/strings.xml @@ -472,4 +472,12 @@ Aktiviere dies nur, wenn du eine Online Datenquelle und nur Android Auto-Benachrichtigungen verwendest.\nDies verhindert, dass Android diese App schließt, wenn sie nicht mit Android Auto verbunden ist, sodass die App die Android Auto-Verbindung nicht erkennen kann.\nAnstatt diese Einstellung zu aktivieren, kannst du die App auch einmal in Android Auto öffnen, wenn du verbunden bist. Akkuoptimierungen sind aktiv!\nHier drücken, um es zu deaktivieren. Wenn du eine Online Datenquelle verwendest, wird die App möglicherweise nicht gestartet, wenn du mit Android Auto verbunden bist und nur Android Auto-Benachrichtigungen verwendest.\nUm sicherzustellen, dass die App die Android Auto-Verbindung erkennt, musst du die Akkuoptimierung deaktivieren.\nWenn es immer noch nicht funktioniert, kannst du auch den Vordergrundmodus aktivieren oder die App einmal in Android Auto öffnen, wenn sie mit Android Auto verbunden ist. + Android Auto einrichten + Um GlucoDataAuto in Android Auto zu verwenden, müssen die folgende Schritte durchgeführt werden: + 1. Entwicklereinstellungen aktivieren + - Android Auto App öffnen\n- bis zu Version scrollen\n- mehrfach auf Version drücken bis ein Popup mit \"Entwicklereinstellungen zulassen\" kommt\n- \"OK\" drücken + 2. \"Unbekannte Quellen\" aktivieren + - Android Auto App öffnen\n- in den 3-Punkt Menü \"Entwicklereinstellungen auswählen\"\n- bis zu \"Unbekannte Quellen\" scrollen und aktivieren + 3. Benachrichtigungen aktivieren + - Android Auto App öffnen\n- bis zu \"Benachrichtigungen\" scrollen\n- \"Unterhaltungen anzeigen\" aktivieren\n- \"Erste Zeile einer Unterhaltung anzeigen\" aktivieren diff --git a/common/src/main/res/values-es/strings.xml b/common/src/main/res/values-es/strings.xml index 70313bb7..47b13387 100644 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -487,4 +487,12 @@ Actívalo solo si estás usando una fuente de seguidor y solo notificaciones de Android Auto.\nEsto evita que Android cierre esta aplicación mientras no esté conectado a Android Auto, por lo que la aplicación no puede reconocer la conexión a Android Auto.\nEn lugar de habilitar esta configuración, también puedes abrir la aplicación en Android Auto una vez, si estás conectado. La optimización de batería está habilitada!\nPulsa aquí para desactivarlo. Si estás usando una fuente de seguidor, la aplicación puede no iniciarse mientras estés conectado a Android Auto, si solo usas notificaciones de Android Auto.\nPara asegurarte de que la aplicación detecte la conexión de Android Auto, tienes que desactivar la optimización de batería.\nSi aún no funciona, también puedes habilitar el modo de primer plano o tienes que abrir la aplicación en Android Auto una vez, cuando esté conectado a Android Auto. + Configurar Android Auto + Para activar GlucoDataAuto para Android Auto, debes seguir los siguientes pasos: + 1. Activar el modo de desarrollador + - Abre la aplicación Android Auto\n- Desplázate hacia abajo hasta la Versión\n- Toca varias veces en la Versión hasta que aparezca una ventana emergente que diga \"Permitir ajustes de desarollo\"\n- Presiona \"Aceptar\" + 2. Activar \"Fuentes desconocidas\" + - Abre la aplicación Android Auto\n- Abre en el menú de 3 puntos las \"Ajustes de desarrollador\"\n- Desplázate hacia abajo hasta \"Fuentes desconocidas\"\n- Actívalo + 3. Configurar las configuraciones de notificaciones + - Abre la aplicación Android Auto\n- Desplázate hacia abajo hasta \"Mensajes\"\n- Activa \"Mostrar notificaciones de mensajes\"\n- Activa \"Mostrar la primera línea de los mensajes\" \ No newline at end of file diff --git a/common/src/main/res/values-pl/strings.xml b/common/src/main/res/values-pl/strings.xml index 7e1ef436..621bcf44 100644 --- a/common/src/main/res/values-pl/strings.xml +++ b/common/src/main/res/values-pl/strings.xml @@ -480,4 +480,12 @@ Włącz to tylko wtedy, gdy używasz źródła obserwatora i tylko powiadomień Android Auto.\nTo zapobiega zamknięciu tej aplikacji przez Androida, gdy nie jest podłączona do Android Auto, więc aplikacja nie może rozpoznać połączenia z Android Auto.\nZamiast włączać to ustawienie, możesz również otworzyć aplikację w Android Auto raz, gdy jesteś podłączony. Optymalizacja baterii jest włączona!\nNaciśnij tutaj, aby to wyłączyć. Jeśli używasz źródła obserwatora, aplikacja może nie zostać uruchomiona podczas połączenia z Android Auto, jeśli używasz tylko powiadomień Android Auto.\nAby upewnić się, że aplikacja wykrywa połączenie z Android Auto, musisz wyłączyć optymalizację baterii.\nJeśli to nadal nie działa, możesz również włączyć tryb pierwszoplanowy lub otworzyć aplikację w Android Auto raz, gdy jest podłączona do Android Auto. + Konfiguracja Android Auto + Aby aktywować GlucoDataAuto dla Android Auto, należy wykonać następujące kroki: + 1. Aktywacja trybu programisty + - otwórz aplikację Android Auto\n- przewiń w dół do pozycji Wersja\n- dotknij kilkakrotnie pozycji Wersja, aż pojawi się wyskakujące okienko „Zezwalaj na ustawienia programistyczne\"\n- naciśnij \"OK\" + 2. Aktywuj „Nieznane źródła\" + - otwórz aplikację Android Auto\n- otwórz w menu (3 kropki) „Ustawienia programisty\"\n- przewiń w dół do pozycji „Nieznane źródło\"\n- włącz ją + 3. Ustawienia powiadomień + - otwórz aplikację Android Auto\n- przewiń w dół do pozycji „Powiadomienia\"\n- włącz „Pokazuj rozmowy\"\n- włącz „Pokazuj pierwszy wiersz rozmów\" diff --git a/common/src/main/res/values-pt/strings.xml b/common/src/main/res/values-pt/strings.xml index 66a4b6b9..fa840b14 100644 --- a/common/src/main/res/values-pt/strings.xml +++ b/common/src/main/res/values-pt/strings.xml @@ -482,4 +482,12 @@ Ative isso apenas se você estiver usando uma fonte seguidora e somente notificações do Android Auto.\nIsso impede que o Android feche este aplicativo enquanto não estiver conectado ao Android Auto, para que o aplicativo não possa reconhecer a conexão com o Android Auto.\nEm vez de habilitar esta configuração, você também pode abrir o aplicativo no Android Auto uma vez, se estiver conectado. Otimização da bateria está habilitada!\nPressione aqui para desativá-lo. Se você estiver usando uma fonte seguidora, o aplicativo pode não ser iniciado enquanto estiver conectado ao Android Auto, se você estiver usando apenas notificações do Android Auto.\nPara garantir que o aplicativo detecte a conexão com o Android Auto, você deve desativar a otimização da bateria.\nSe ainda não funcionar, você também pode habilitar o modo de primeiro plano ou abrir o aplicativo no Android Auto uma vez, quando estiver conectado ao Android Auto. + Configurar Android Auto + Para ativar o GlucoDataAuto para Android Auto, você deve seguir os seguintes passos: + 1. Ativar o modo desenvolvedor + - Abra o aplicativo Android Auto\n- Role para baixo até a Versão\n- Toque várias vezes na Versão até aparecer um pop-up para \"Permitir definições de programação\"\n- Pressione \"OK\" + 2. Ativar \"Fontes desconhecidas\" + - Abra o aplicativo Android Auto\n- Abra no menu de 3 pontos as \"Definições do programador\"\n- Role para baixo até \"Fontes desconhecidas\"\n- Ative-o + 3. Configurar as configurações de notificações + - Abra o aplicativo Android Auto\n- Role para baixo até \"Mensagens\"\n- Ative \"Mostrar notificações de mensagens\"\n- Ative \"Mostrar primeira linha das mensagens\" diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 95d5be51..707bdb72 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -497,4 +497,12 @@ Only enable it, if you are using a follower source and Android Auto notifications only.\nThis prevents Android to close this app, while not connected to Android Auto, so the app can not recognize the Android Auto connection.\nInstead of enable this setting, you can also open the app in Android Auto once, if you are connected. Battery optimization is enabled!\nPress here to disable it. If you are using a follower source, the app may not be started while connected to Android Auto, if you are using Android Auto Notifications only.\nTo make sure, the app detects Android Auto connection you have to disable battery optimization.\nIf it still not work, you can als enable foreground mode or you have to open the app in Android Auto once, if it is connected to Android Auto. + Setup Android Auto + To activate GlucoDataAuto for Android Auto, you have to do the following steps: + 1. Activate developer mode + - open Android Auto app\n- scroll down to the Version\n- tap several times on the Version until a popup appears to \"Allow development settings\"\n- press \"OK\" + 2. Activate \"Unknown sources\" + - open Android Auto app\n- open in the 3-dot menu the \"Developer settings\"\n- scroll down to \"Unknown source\"\n- enable it + 3. Set notification settings + - open Android Auto app\n- scroll down to \"Notifications\"\n- enable \"Show conversations\"\n- enable \"Show first line of conversations\" From cc05f1d78b2cc6f15a4cbe522270993f06d16989 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Thu, 6 Jun 2024 09:59:45 +0200 Subject: [PATCH 08/26] GDA: fix notification permission --- .../de/michelinside/glucodataauto/MainActivity.kt | 12 ++++++++---- .../android_auto/CarMediaBrowserService.kt | 8 +++++++- .../preferences/SettingsFragmentBase.kt | 12 ++++++++---- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt index 98e8a27f..2418c0da 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt @@ -356,10 +356,14 @@ class MainActivity : AppCompatActivity(), NotifierInterface { Log.v(LOG_ID, "notification toggle") if(!sharedPref.getBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false) && !Channels.notificationChannelActive(this, ChannelType.ANDROID_AUTO)) { - val intent: Intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) - .putExtra(Settings.EXTRA_APP_PACKAGE, this.packageName) - if (Channels.notificationActive(this)) // only the channel is inactive! - intent.putExtra(Settings.EXTRA_CHANNEL_ID, ChannelType.ANDROID_AUTO.channelId) + val intent: Intent = if (Channels.notificationActive(this)) { // only the channel is inactive! + Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, this.packageName) + .putExtra(Settings.EXTRA_CHANNEL_ID, ChannelType.ANDROID_AUTO.channelId) + } else { + Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, this.packageName) + } startActivity(intent) } else { with(sharedPref.edit()) { diff --git a/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarMediaBrowserService.kt b/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarMediaBrowserService.kt index e65b2439..98f7f546 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarMediaBrowserService.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarMediaBrowserService.kt @@ -21,6 +21,8 @@ import androidx.media.MediaBrowserServiceCompat import de.michelinside.glucodataauto.GlucoDataServiceAuto import de.michelinside.glucodatahandler.common.Constants import de.michelinside.glucodatahandler.common.ReceiveData +import de.michelinside.glucodatahandler.common.notification.ChannelType +import de.michelinside.glucodatahandler.common.notification.Channels import de.michelinside.glucodatahandler.common.notifier.InternalNotifier import de.michelinside.glucodatahandler.common.notifier.NotifierInterface import de.michelinside.glucodatahandler.common.notifier.NotifySource @@ -149,7 +151,11 @@ class CarMediaBrowserService: MediaBrowserServiceCompat(), NotifierInterface, Sh try { Log.d(LOG_ID, "onLoadChildren for parent: " + parentId) if (MEDIA_ROOT_ID == parentId) { - result.sendResult(mutableListOf(createMediaItem(), createToggleItem())) + val items = mutableListOf(createMediaItem()) + if (Channels.notificationChannelActive(this, ChannelType.ANDROID_AUTO)) { + items.add(createToggleItem()) + } + result.sendResult(items) } else { result.sendResult(null) } diff --git a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt index 06ef52a8..b8c28cc5 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/preferences/SettingsFragmentBase.kt @@ -126,10 +126,14 @@ class GDASettingsFragment: SettingsFragmentBase(R.xml.pref_gda) { super.onSharedPreferenceChanged(sharedPreferences, key) if(key == Constants.SHARED_PREF_CAR_NOTIFICATION) { if (preferenceManager.sharedPreferences!!.getBoolean(Constants.SHARED_PREF_CAR_NOTIFICATION, false) && !Channels.notificationChannelActive(requireContext(), ChannelType.ANDROID_AUTO)) { - val intent: Intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) - .putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) - if (Channels.notificationActive(requireContext())) // only the channel is inactive! - intent.putExtra(Settings.EXTRA_CHANNEL_ID, ChannelType.ANDROID_AUTO.channelId) + val intent: Intent = if (Channels.notificationActive(requireContext())) { // only the channel is inactive! + Intent(Settings.ACTION_CHANNEL_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) + .putExtra(Settings.EXTRA_CHANNEL_ID, ChannelType.ANDROID_AUTO.channelId) + } else { + Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) + .putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) + } startActivity(intent) } else { updatePreferences() From cc20d24025e425e9b4f635ea4758f7b3ef503599 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Thu, 6 Jun 2024 13:11:48 +0200 Subject: [PATCH 09/26] GDA: adjust help to current version --- common/src/main/res/values-de/strings.xml | 2 +- common/src/main/res/values/strings.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/common/src/main/res/values-de/strings.xml b/common/src/main/res/values-de/strings.xml index 3aa77c2b..549af73c 100644 --- a/common/src/main/res/values-de/strings.xml +++ b/common/src/main/res/values-de/strings.xml @@ -479,5 +479,5 @@ 2. \"Unbekannte Quellen\" aktivieren - Android Auto App öffnen\n- in den 3-Punkt Menü \"Entwicklereinstellungen auswählen\"\n- bis zu \"Unbekannte Quellen\" scrollen und aktivieren 3. Benachrichtigungen aktivieren - - Android Auto App öffnen\n- bis zu \"Benachrichtigungen\" scrollen\n- \"Unterhaltungen anzeigen\" aktivieren\n- \"Erste Zeile einer Unterhaltung anzeigen\" aktivieren + - Android Auto App öffnen\n- bis zu \"Messaging\" scrollen\n- \"Benachrichtigungen für Nachrichten anzeigen\" aktivieren\n- \"Erste Zeile einer Nachricht anzeigen\" aktivieren diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 707bdb72..f3d0dd30 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -504,5 +504,5 @@ 2. Activate \"Unknown sources\" - open Android Auto app\n- open in the 3-dot menu the \"Developer settings\"\n- scroll down to \"Unknown source\"\n- enable it 3. Set notification settings - - open Android Auto app\n- scroll down to \"Notifications\"\n- enable \"Show conversations\"\n- enable \"Show first line of conversations\" + - open Android Auto app\n- scroll down to \"Messaging\"\n- enable \"Show message notifications\"\n- enable \"Show first line of messages\" From 2340fc96ff213a5abe50766844ae8baeaef1de14 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Thu, 6 Jun 2024 16:04:28 +0200 Subject: [PATCH 10/26] GDA: fix time task --- auto/build.gradle | 2 +- .../glucodataauto/GlucoDataServiceAuto.kt | 2 ++ .../android_auto/CarMediaBrowserService.kt | 4 ++-- .../android_auto/CarNotification.kt | 21 ++++++++++++------- .../preferences/AlarmFragment.kt | 9 ++++++++ auto/src/main/res/xml/alarms.xml | 1 + .../common/notification/Channels.kt | 10 ++++++--- .../common/tasks/BackgroundTaskService.kt | 2 ++ 8 files changed, 37 insertions(+), 14 deletions(-) diff --git a/auto/build.gradle b/auto/build.gradle index dcfe53ab..c7da9e40 100644 --- a/auto/build.gradle +++ b/auto/build.gradle @@ -14,7 +14,7 @@ android { minSdk rootProject.minSdk targetSdk rootProject.targetSdk versionCode 1025 - versionName "1.0-beta3" + versionName "1.0-beta4" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt index a774fc78..d8095fc2 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt @@ -38,6 +38,7 @@ class GlucoDataServiceAuto: Service() { Log.v(LOG_ID, "init called: init=$init") if(!init) { GlucoDataService.context = context + CarNotification.initNotification(context) startService(context, false) init = true } @@ -177,6 +178,7 @@ class GlucoDataServiceAuto: Service() { super.onStartCommand(intent, flags, startId) GlucoDataService.context = applicationContext ReceiveData.initData(applicationContext) + CarNotification.initNotification(this) val sharedPref = getSharedPreferences(Constants.SHARED_PREF_TAG, Context.MODE_PRIVATE) val isForeground = (if(intent != null) intent.getBooleanExtra(Constants.SHARED_PREF_FOREGROUND_SERVICE, false) else false) || sharedPref.getBoolean(Constants.SHARED_PREF_FOREGROUND_SERVICE, false) if (isForeground && !isForegroundService) { diff --git a/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarMediaBrowserService.kt b/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarMediaBrowserService.kt index 98f7f546..e239f957 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarMediaBrowserService.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarMediaBrowserService.kt @@ -166,7 +166,7 @@ class CarMediaBrowserService: MediaBrowserServiceCompat(), NotifierInterface, Sh } override fun OnNotifyData(context: Context, dataSource: NotifySource, extras: Bundle?) { - Log.v(LOG_ID, "OnNotifyData called") + Log.d(LOG_ID, "OnNotifyData called for source $dataSource") try { notifyChildrenChanged(MEDIA_ROOT_ID) } catch (exc: Exception) { @@ -175,7 +175,7 @@ class CarMediaBrowserService: MediaBrowserServiceCompat(), NotifierInterface, Sh } override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { - Log.v(LOG_ID, "onSharedPreferenceChanged called for key " + key) + Log.d(LOG_ID, "onSharedPreferenceChanged called for key " + key) try { when(key) { Constants.SHARED_PREF_CAR_NOTIFICATION, diff --git a/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarNotification.kt b/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarNotification.kt index 25683b11..3cee6bf1 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarNotification.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/android_auto/CarNotification.kt @@ -106,7 +106,7 @@ object CarNotification: NotifierInterface, SharedPreferences.OnSharedPreferenceC } } - private fun initNotification(context: Context) { + fun initNotification(context: Context) { try { if(!init) { Log.v(LOG_ID, "initNotification called") @@ -154,7 +154,8 @@ object CarNotification: NotifierInterface, SharedPreferences.OnSharedPreferenceC private fun getFilter(): MutableSet { val filter = mutableSetOf( NotifySource.BROADCAST, - NotifySource.MESSAGECLIENT) + NotifySource.MESSAGECLIENT, + NotifySource.OBSOLETE_ALARM_TRIGGER) if (notification_reappear_interval > 0) filter.add(NotifySource.TIME_VALUE) return filter @@ -207,28 +208,32 @@ object CarNotification: NotifierInterface, SharedPreferences.OnSharedPreferenceC + "\nnotification_interval: " + notification_interval + "\nnotification_reappear_interval: " + notification_reappear_interval ) - if (dataSource == NotifySource.BROADCAST || dataSource == NotifySource.MESSAGECLIENT) { + if (dataSource == NotifySource.OBSOLETE_ALARM_TRIGGER) { + Log.d(LOG_ID, "Obsolete alarm triggered") + forceNextNotify = true + return true + } else if (dataSource == NotifySource.BROADCAST || dataSource == NotifySource.MESSAGECLIENT) { if(notification_interval == 1L || ReceiveData.forceAlarm) { - Log.v(LOG_ID, "Notification has forced by interval or alarm") + Log.d(LOG_ID, "Notification has forced by interval or alarm") return true } if (ReceiveData.getAlarmType() == AlarmType.VERY_LOW) { - Log.v(LOG_ID, "Notification for very low-alarm") + Log.d(LOG_ID, "Notification for very low-alarm") forceNextNotify = true // if obsolete or VERY_LOW, the next value is important! return true } if (forceNextNotify) { - Log.v(LOG_ID, "Force notification") + Log.d(LOG_ID, "Force notification") forceNextNotify = false return true } if (notification_interval > 1L && getTimeDiffMinute() >= notification_interval && ReceiveData.getElapsedTimeMinute() == 0L) { - Log.v(LOG_ID, "Interval for new value elapsed") + Log.d(LOG_ID, "Interval for new value elapsed") return true } } else if(dataSource == NotifySource.TIME_VALUE) { if (notification_reappear_interval > 0 && ReceiveData.getElapsedTimeMinute().mod(notification_reappear_interval) == 0L) { - Log.v(LOG_ID, "reappear after: " + ReceiveData.getElapsedTimeMinute() + " - interval: " + notification_reappear_interval) + Log.d(LOG_ID, "reappear after: " + ReceiveData.getElapsedTimeMinute() + " - interval: " + notification_reappear_interval) return true } } diff --git a/auto/src/main/java/de/michelinside/glucodataauto/preferences/AlarmFragment.kt b/auto/src/main/java/de/michelinside/glucodataauto/preferences/AlarmFragment.kt index bf460376..c776f2f2 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/preferences/AlarmFragment.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/preferences/AlarmFragment.kt @@ -3,6 +3,7 @@ package de.michelinside.glucodataauto.preferences import android.annotation.SuppressLint import android.os.Bundle import android.util.Log +import androidx.core.content.ContextCompat import androidx.preference.Preference import androidx.preference.PreferenceFragmentCompat import de.michelinside.glucodataauto.R @@ -82,6 +83,14 @@ class AlarmFragment : PreferenceFragmentCompat() { val pref = findPreference(key) ?: return val alarmType = AlarmType.fromIndex(pref.extras.getInt("type")) pref.summary = getAlarmCatSummary(alarmType) + pref.icon = ContextCompat.getDrawable(requireContext(), getAlarmCatIcon(alarmType, key + "_enabled")) + } + + private fun getAlarmCatIcon(alarmType: AlarmType, enableKey: String): Int { + if(alarmType != AlarmType.VERY_LOW && !preferenceManager.sharedPreferences!!.getBoolean(enableKey, true)) { + return R.drawable.icon_popup_off + } + return R.drawable.icon_popup } private fun getAlarmCatSummary(alarmType: AlarmType): String { diff --git a/auto/src/main/res/xml/alarms.xml b/auto/src/main/res/xml/alarms.xml index fa1eb02f..d3cd90d0 100644 --- a/auto/src/main/res/xml/alarms.xml +++ b/auto/src/main/res/xml/alarms.xml @@ -20,6 +20,7 @@ android:key="alarm_very_low" android:title="@string/very_low_alarm_notification_name" android:summary="@string/very_low_alarm_summary" + android:icon="@drawable/icon_popup" app:iconSpaceReserved="false"> NotificationManager.IMPORTANCE_NONE) + val channel = getNotificationManager(context).getNotificationChannel(type.channelId) + if (channel != null) { + Log.d(LOG_ID, "Channel: prio=${channel.importance}") + return (channel.importance > NotificationManager.IMPORTANCE_NONE) + } else { + Log.w(LOG_ID, "Notification channel $type still not exists!") + } } return false } diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/BackgroundTaskService.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/BackgroundTaskService.kt index 473b3412..cef76b37 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/BackgroundTaskService.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/BackgroundTaskService.kt @@ -317,6 +317,8 @@ abstract class BackgroundTaskService(val alarmReqId: Int, protected val LOG_ID: alarmManager!!.cancel(pendingIntent!!) alarmManager = null currentAlarmTime = 0L + curDelay = -1L + curInterval = -1L } } From 4d7fe357c5ea752ff247acb30b0a6231607c18e2 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Fri, 7 Jun 2024 07:48:30 +0200 Subject: [PATCH 11/26] fix initial task execution --- .../common/tasks/BackgroundTaskService.kt | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/BackgroundTaskService.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/BackgroundTaskService.kt index cef76b37..e72292d5 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/BackgroundTaskService.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/tasks/BackgroundTaskService.kt @@ -66,7 +66,7 @@ abstract class BackgroundTaskService(val alarmReqId: Int, protected val LOG_ID: fun checkExecution(task: BackgroundTask? = null): Boolean { if(task != null) { - Log.v(LOG_ID, "checkExecution for " + task.javaClass.simpleName + ": elapsedTimeMinute=" + elapsedTimeMinute + Log.d(LOG_ID, "checkExecution for " + task.javaClass.simpleName + ": elapsedTimeMinute=" + elapsedTimeMinute + " - lastElapsedMinute=" + lastElapsedMinute + " - elapsedIobCobTimeMinute=" + elapsedIobCobTimeMinute + " - interval=" + task.getIntervalMinute() @@ -74,17 +74,17 @@ abstract class BackgroundTaskService(val alarmReqId: Int, protected val LOG_ID: if(task.active(elapsedTimeMinute)) { if (elapsedTimeMinute != 0L) { if (lastElapsedMinute < 0 && initialExecution) { - Log.v(LOG_ID, "Trigger initial task execution") + Log.d(LOG_ID, "Trigger initial task execution") return true // trigger initial execution } if (elapsedTimeMinute.mod(task.getIntervalMinute()) == 0L) { - Log.v(LOG_ID, "Trigger "+ task.javaClass.simpleName + " execution after " + elapsedTimeMinute + " min") + Log.d(LOG_ID, "Trigger "+ task.javaClass.simpleName + " execution after " + elapsedTimeMinute + " min") return true // interval expired for active task } } if (task.hasIobCobSupport()) { if (elapsedIobCobTimeMinute >= task.getIntervalMinute()) { - Log.v(LOG_ID, "Trigger " + task.javaClass.simpleName + " IOB/COB execution after " + elapsedIobCobTimeMinute + " min") + Log.d(LOG_ID, "Trigger " + task.javaClass.simpleName + " IOB/COB execution after " + elapsedIobCobTimeMinute + " min") return true // IOB/COB interval expired for active task } } @@ -94,11 +94,11 @@ abstract class BackgroundTaskService(val alarmReqId: Int, protected val LOG_ID: + " - lastElapsedMinute=" + lastElapsedMinute + " - elapsedIobCobTimeMinute=" + elapsedIobCobTimeMinute) if ((lastElapsedMinute != elapsedTimeMinute && elapsedTimeMinute != 0L)) { - Log.v(LOG_ID, "Check task execution after " + elapsedTimeMinute + " min") + Log.d(LOG_ID, "Check task execution after " + elapsedTimeMinute + " min") return true // time expired and no new value } if (hasIobCobSupport() && elapsedIobCobTimeMinute > 0) { - Log.v(LOG_ID, "Check IOB/COB task execution after " + elapsedIobCobTimeMinute + " min") + Log.d(LOG_ID, "Check IOB/COB task execution after " + elapsedIobCobTimeMinute + " min") return true // check each task for additional IOB COB data } } @@ -197,10 +197,11 @@ abstract class BackgroundTaskService(val alarmReqId: Int, protected val LOG_ID: return // not yet initialized val newInterval = getInterval() val newDelay = getDelay() - if (initialExecution || curInterval != newInterval || curDelay != newDelay) { - Log.i(LOG_ID, "Interval has changed from " + curInterval + "m+" + curDelay + "ms to " + newInterval + "m+" + newDelay + "ms") - var triggerExecute = initialExecution || (curInterval <= 0 && newInterval > 0) // changed from inactive to active so trigger an initial execution - if (!triggerExecute && curInterval > newInterval && elapsedTimeMinute >= newInterval) { + Log.d(LOG_ID, "checkTimer for current: ${curInterval}m+${curDelay}ms and new: ${newInterval}m+${newDelay}ms - initialExecution=$initialExecution") + if (curInterval != newInterval || curDelay != newDelay) { + Log.i(LOG_ID, "Interval has changed from ${curInterval}m+${curDelay}ms to ${newInterval}m+${newDelay}ms - initialExecution=$initialExecution") + var triggerExecute = initialExecution && (curInterval <= 0 && newInterval > 0) // changed from inactive to active so trigger an initial execution + if (!triggerExecute && newInterval > 0 && curInterval > newInterval && elapsedTimeMinute >= newInterval) { // interval get decreased, so check for execution is needed triggerExecute = true } @@ -325,7 +326,7 @@ abstract class BackgroundTaskService(val alarmReqId: Int, protected val LOG_ID: override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { try { if (sharedPreferences != null) { - Log.v(LOG_ID, "onSharedPreferenceChanged called for " + key) + Log.d(LOG_ID, "onSharedPreferenceChanged called for " + key) var changed = false backgroundTaskList.forEach { if (it.checkPreferenceChanged(sharedPreferences, key, context!!)) From defa8e0d485214dc8d374ad1a13502925e835899 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Sat, 8 Jun 2024 18:15:53 +0200 Subject: [PATCH 12/26] Workaround for Samsung notification bug --- .../glucodatahandler/common/Constants.kt | 3 + .../common/GdhUncaughtExecptionHandler.kt | 43 +++++++++++ .../common/GlucoDataService.kt | 2 + common/src/main/res/values-de/strings.xml | 4 + common/src/main/res/values-es/strings.xml | 4 + common/src/main/res/values-pl/strings.xml | 4 + common/src/main/res/values-pt/strings.xml | 4 + common/src/main/res/values/strings.xml | 4 + .../michelinside/glucodatahandler/Dialogs.kt | 12 +-- .../GlucoDataServiceMobile.kt | 4 +- .../glucodatahandler/MainActivity.kt | 19 ++++- .../notification/PermanentNotification.kt | 76 +++++++++++++------ .../preferences/AlarmFragment.kt | 2 +- .../preferences/SettingsFragmentBase.kt | 5 +- .../preferences/SourceFragment.kt | 8 +- mobile/src/main/res/xml/pref_notification.xml | 6 ++ 16 files changed, 161 insertions(+), 39 deletions(-) create mode 100644 common/src/main/java/de/michelinside/glucodatahandler/common/GdhUncaughtExecptionHandler.kt diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/Constants.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/Constants.kt index f75e520a..b25c4d52 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/Constants.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/Constants.kt @@ -84,6 +84,7 @@ object Constants { const val SHARED_PREF_PERMANENT_NOTIFICATION_ICON = "status_bar_notification_icon" const val SHARED_PREF_PERMANENT_NOTIFICATION_COLORED_ICON = "status_bar_notification_colored_icon" const val SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY = "permanent_notification_empty" + const val SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT = "permanent_notification_custom_layout" const val SHARED_PREF_PERMANENT_NOTIFICATION_TAP_ACTION = "permanent_notification_tap_action" const val SHARED_PREF_SECOND_PERMANENT_NOTIFICATION = "second_permanent_notification" const val SHARED_PREF_SECOND_PERMANENT_NOTIFICATION_ICON = "second_status_bar_notification_icon" @@ -103,6 +104,8 @@ object Constants { const val SHARED_PREF_WATCHDRIP_RECEIVERS = "watchdrip_receivers" const val SHARED_PREF_CHECK_WEAR_OS_CONNECTION = "wear_os_check_connection" const val SHARED_PREF_OPEN_WATCH_DRIP_LINK = "open_watchdrip_link" + const val SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT = "uncaught_exception_detected" + const val SHARED_PREF_UNCAUGHT_EXCEPTION_MESSAGE = "uncaught_exception_message" // internal app preferences (not changed by settings) -> use separate tag for not trigger onChanged events const val SHARED_PREF_INTERNAL_TAG = "GlucoDataHandlerInternalAppPrefs" diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/GdhUncaughtExecptionHandler.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/GdhUncaughtExecptionHandler.kt new file mode 100644 index 00000000..891710ea --- /dev/null +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/GdhUncaughtExecptionHandler.kt @@ -0,0 +1,43 @@ +package de.michelinside.glucodatahandler.common + +import android.content.Context +import android.util.Log +import java.lang.Exception +import kotlin.system.exitProcess + +class GdhUncaughtExecptionHandler(val context: Context) : Thread.UncaughtExceptionHandler { + private val LOG_ID = "GDH.UncaughtExceptionHandler" + private var defaultHandler: Thread.UncaughtExceptionHandler + + init { + defaultHandler = Thread.getDefaultUncaughtExceptionHandler()!! + Thread.setDefaultUncaughtExceptionHandler(this) + } + + override fun uncaughtException(t: Thread, e: Throwable) { + try { + val message = "${e.message}\n${e.stackTraceToString()}" + Log.e(LOG_ID, "Uncaught exception detected in thread ${t.name}: $message") + val sharedPref = context.getSharedPreferences(Constants.SHARED_PREF_TAG, Context.MODE_PRIVATE) + val customLayoutEnabled = sharedPref.getBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, true) + with(sharedPref.edit()) { + putBoolean(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT, true) + putString(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_MESSAGE, message) + if (message.contains("BadForegroundServiceNotificationException") || message.contains("RemoteServiceException")) { + Log.e(LOG_ID, "BadForegroundServiceNotificationException detected! customLayoutEnabled=$customLayoutEnabled") + if (customLayoutEnabled) + putBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, false) + else + putBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY, true) + } + apply() + Thread.sleep(100) // wait for saving + Log.v(LOG_ID, "Exception saved!") + } + } catch (e: Exception) { + Log.e(LOG_ID, "Exception: ${e.message}") + } + exitProcess(10) + } + +} \ No newline at end of file diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt index a2392279..bacfca36 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt @@ -30,6 +30,7 @@ abstract class GlucoDataService(source: AppSource) : WearableListenerService() { private lateinit var batteryReceiver: BatteryReceiver private lateinit var xDripReceiver: XDripBroadcastReceiver private lateinit var aapsReceiver: AAPSReceiver + private lateinit var uncaughtExecptionHandler: GdhUncaughtExecptionHandler @SuppressLint("StaticFieldLeak") companion object { @@ -137,6 +138,7 @@ abstract class GlucoDataService(source: AppSource) : WearableListenerService() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { try { Log.v(LOG_ID, "onStartCommand called") + uncaughtExecptionHandler = GdhUncaughtExecptionHandler(this) super.onStartCommand(intent, flags, startId) val isForeground = true // intent?.getBooleanExtra(Constants.SHARED_PREF_FOREGROUND_SERVICE, true) --> always use foreground!!! if (isForeground && !isForegroundService) { diff --git a/common/src/main/res/values-de/strings.xml b/common/src/main/res/values-de/strings.xml index 549af73c..52d36dfc 100644 --- a/common/src/main/res/values-de/strings.xml +++ b/common/src/main/res/values-de/strings.xml @@ -480,4 +480,8 @@ - Android Auto App öffnen\n- in den 3-Punkt Menü \"Entwicklereinstellungen auswählen\"\n- bis zu \"Unbekannte Quellen\" scrollen und aktivieren 3. Benachrichtigungen aktivieren - Android Auto App öffnen\n- bis zu \"Messaging\" scrollen\n- \"Benachrichtigungen für Nachrichten anzeigen\" aktivieren\n- \"Erste Zeile einer Nachricht anzeigen\" aktivieren + Farbiges Layout + Zeigt die Werte in großer und farbiger Schrift.\nAuf einigen Samsung Geräte ab Android 13 kann dies zu einem Absturz der App führen, aufgrund eines Bugs auf Seite von Samsung.\nWenn das Problem auftritt, wird diese Einstellung automatisch deaktiviert, damit die App wieder lauffähig ist. + Absturz erkannt! + Es tut mir so leid, dass die App während der Ausführung abgestürzt ist!\nBitte sendet mir die Logs zu, dann kann ich den Fehler analysieren und versuchen so schnell wie möglich zu fixen.\nDanke! diff --git a/common/src/main/res/values-es/strings.xml b/common/src/main/res/values-es/strings.xml index 47b13387..389b3b8e 100644 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -495,4 +495,8 @@ - Abre la aplicación Android Auto\n- Abre en el menú de 3 puntos las \"Ajustes de desarrollador\"\n- Desplázate hacia abajo hasta \"Fuentes desconocidas\"\n- Actívalo 3. Configurar las configuraciones de notificaciones - Abre la aplicación Android Auto\n- Desplázate hacia abajo hasta \"Mensajes\"\n- Activa \"Mostrar notificaciones de mensajes\"\n- Activa \"Mostrar la primera línea de los mensajes\" + Diseño colorido + Muestra los valores en texto grande y colorido.\nEn algunos dispositivos Samsung con Android 13 y superior, esto puede hacer que la aplicación se bloquee debido a un error del lado de Samsung.\nSi ocurre el problema, esta configuración se desactivará automáticamente para garantizar que la aplicación siga siendo funcional. + ¡Error detectado! + ¡Lo siento mucho que la aplicación se haya bloqueado durante la ejecución!\nPor favor, envíame los registros para que pueda analizar el error e intentar solucionarlo lo antes posible.\n¡Gracias! \ No newline at end of file diff --git a/common/src/main/res/values-pl/strings.xml b/common/src/main/res/values-pl/strings.xml index 3747df3f..6b6d8403 100644 --- a/common/src/main/res/values-pl/strings.xml +++ b/common/src/main/res/values-pl/strings.xml @@ -488,4 +488,8 @@ - otwórz aplikację Android Auto\n- otwórz w menu (3 kropki) „Ustawienia programisty\"\n- przewiń w dół do pozycji „Nieznane źródło\"\n- włącz ją 3. Ustawienia powiadomień - otwórz aplikację Android Auto\n- przewiń w dół do pozycji „Powiadomienia\"\n- włącz „Pokazuj rozmowy\"\n- włącz „Pokazuj pierwszy wiersz rozmów\" + Kolorowy układ + Wyświetla wartości dużą i kolorową czcionką.\nNa niektórych urządzeniach Samsung z Androidem 13 i nowszym, może to spowodować awarię aplikacji z powodu błędu po stronie Samsunga.\nJeśli problem wystąpi, to ustawienie zostanie automatycznie wyłączone, aby aplikacja mogła działać poprawnie. + Wykryto awarię! + Bardzo mi przykro, że aplikacja zawiesiła się podczas działania!\nProszę, wyślij mi logi, abym mógł przeanalizować błąd i spróbować go jak najszybciej naprawić.\nDziękuję! diff --git a/common/src/main/res/values-pt/strings.xml b/common/src/main/res/values-pt/strings.xml index fa840b14..ae555e41 100644 --- a/common/src/main/res/values-pt/strings.xml +++ b/common/src/main/res/values-pt/strings.xml @@ -490,4 +490,8 @@ - Abra o aplicativo Android Auto\n- Abra no menu de 3 pontos as \"Definições do programador\"\n- Role para baixo até \"Fontes desconhecidas\"\n- Ative-o 3. Configurar as configurações de notificações - Abra o aplicativo Android Auto\n- Role para baixo até \"Mensagens\"\n- Ative \"Mostrar notificações de mensagens\"\n- Ative \"Mostrar primeira linha das mensagens\" + Layout colorido + Exibe os valores em texto grande e colorido.\nEm alguns dispositivos Samsung com Android 13 e superior, isso pode fazer com que o aplicativo trave devido a um bug do lado da Samsung.\nSe o problema ocorrer, essa configuração será desativada automaticamente para garantir que o aplicativo permaneça funcional. + Falha detectada! + Sinto muito que o aplicativo tenha travado durante a execução!\nPor favor, envie-me os logs para que eu possa analisar o erro e tentar corrigi-lo o mais rápido possível.\nObrigado! diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index d6f6db45..874653ad 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -505,4 +505,8 @@ - open Android Auto app\n- open in the 3-dot menu the \"Developer settings\"\n- scroll down to \"Unknown source\"\n- enable it 3. Set notification settings - open Android Auto app\n- scroll down to \"Messaging\"\n- enable \"Show message notifications\"\n- enable \"Show first line of messages\" + Colored layout + Displays the values in large and colored text.\nOn some Samsung devices with Android 13 and higher, this may cause the app to crash due to a bug on Samsung\'s side.\nIf the problem occurs, this setting will be automatically disabled to ensure the app remains functional. + Crash detected! + I am so sorry that the app crashed during execution!\nPlease send me the logs so I can analyze the error and try to fix it as soon as possible.\nThank you! diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/Dialogs.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/Dialogs.kt index a3a857a1..5dd318dd 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/Dialogs.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/Dialogs.kt @@ -11,17 +11,17 @@ import de.michelinside.glucodatahandler.common.R object Dialogs { - fun showOkDialog(context: Context, title: String, message: String, okListener: DialogInterface.OnClickListener) { + fun showOkDialog(context: Context, titleResId: Int, messageResId: Int, okListener: DialogInterface.OnClickListener?) { MaterialAlertDialogBuilder(context) - .setTitle(title) - .setMessage(message) + .setTitle(context.resources.getString(titleResId)) + .setMessage(context.resources.getString(messageResId)) .setPositiveButton(context.resources.getText(R.string.button_ok), okListener) .show() } - fun showOkCancelDialog(context: Context, title: String, message: String, okListener: DialogInterface.OnClickListener) { + fun showOkCancelDialog(context: Context, titleResId: Int, messageResId: Int, okListener: DialogInterface.OnClickListener?) { MaterialAlertDialogBuilder(context) - .setTitle(title) - .setMessage(message) + .setTitle(context.resources.getString(titleResId)) + .setMessage(context.resources.getString(messageResId)) .setPositiveButton(context.resources.getText(R.string.button_ok), okListener) .setNegativeButton(context.resources.getText(R.string.button_cancel), null) .show() diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/GlucoDataServiceMobile.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/GlucoDataServiceMobile.kt index ca103f69..85013d63 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/GlucoDataServiceMobile.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/GlucoDataServiceMobile.kt @@ -159,7 +159,9 @@ class GlucoDataServiceMobile: GlucoDataService(AppSource.PHONE_APP), NotifierInt Log.v(LOG_ID, "getNotification called") return PermanentNotification.getNotification( !sharedPref!!.getBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY, false), - Constants.SHARED_PREF_PERMANENT_NOTIFICATION_ICON, true + Constants.SHARED_PREF_PERMANENT_NOTIFICATION_ICON, + true, + sharedPref!!.getBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, true) ) } diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/MainActivity.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/MainActivity.kt index ed099c2e..2cc0ed96 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/MainActivity.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/MainActivity.kt @@ -124,7 +124,6 @@ class MainActivity : AppCompatActivity(), NotifierInterface { intent.putExtra(SettingsActivity.FRAGMENT_EXTRA, SettingsFragmentClass.SORUCE_FRAGMENT.value) startActivity(intent) } - if (requestPermission()) GlucoDataServiceMobile.start(this, true) @@ -148,6 +147,7 @@ class MainActivity : AppCompatActivity(), NotifierInterface { try { super.onResume() Log.v(LOG_ID, "onResume called") + checkUncaughtException() update() InternalNotifier.addNotifier(this, this, mutableSetOf( NotifySource.BROADCAST, @@ -198,7 +198,7 @@ class MainActivity : AppCompatActivity(), NotifierInterface { }*/ if (this.shouldShowRequestPermissionRationale( android.Manifest.permission.POST_NOTIFICATIONS)) { - Dialogs.showOkDialog(this, resources.getString(CR.string.permission_notification_title), resources.getString(CR.string.permission_notification_message)) { _, _ -> requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS) } + Dialogs.showOkDialog(this, CR.string.permission_notification_title, CR.string.permission_notification_message) { _, _ -> requestPermissionLauncher.launch(android.Manifest.permission.POST_NOTIFICATIONS) } } else { this.requestPermissions(arrayOf(android.Manifest.permission.POST_NOTIFICATIONS), 3) } @@ -444,7 +444,7 @@ class MainActivity : AppCompatActivity(), NotifierInterface { putBoolean(Constants.SHARED_PREF_ALARM_NOTIFICATION_ENABLED, false) apply() } - Dialogs.showOkDialog(this, resources.getString(CR.string.permission_alarm_notification_title), resources.getString(CR.string.permission_alarm_notification_message)) { _, _ -> + Dialogs.showOkDialog(this, CR.string.permission_alarm_notification_title, CR.string.permission_alarm_notification_message) { _, _ -> val intent: Intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) .putExtra(Settings.EXTRA_APP_PACKAGE, this.packageName) startActivity(intent) @@ -646,4 +646,17 @@ class MainActivity : AppCompatActivity(), NotifierInterface { const val CREATE_PHONE_FILE = 1 const val CREATE_WEAR_FILE = 2 } + + private fun checkUncaughtException() { + Log.d(LOG_ID, "Check uncaught exception ${sharedPref.getBoolean(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT, false)}") + if(sharedPref.getBoolean(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT, false)) { + val excMsg = sharedPref.getString(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_MESSAGE, "") + Log.e(LOG_ID, "Uncaught exception detected last time: $excMsg") + with(sharedPref.edit()) { + putBoolean(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT, false) + apply() + } + Dialogs.showOkDialog(this, CR.string.app_crash_title, CR.string.app_crash_message, null) + } + } } \ No newline at end of file diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/notification/PermanentNotification.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/notification/PermanentNotification.kt index dba4068b..f4348608 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/notification/PermanentNotification.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/notification/PermanentNotification.kt @@ -108,7 +108,6 @@ object PermanentNotification: NotifierInterface, SharedPreferences.OnSharedPrefe .setVisibility(Notification.VISIBILITY_PUBLIC) } - private fun removeNotifications() { //notificationMgr.cancel(NOTIFICATION_ID) // remove notification showPrimaryNotification(false) @@ -188,38 +187,57 @@ object PermanentNotification: NotifierInterface, SharedPreferences.OnSharedPrefe return null } - fun getNotification(withContent: Boolean, iconKey: String, foreground: Boolean) : Notification { - var remoteViews: RemoteViews? = null - if (withContent) { - val bitmap = createNotificationView(GlucoDataService.context!!) - if(bitmap != null) { - remoteViews = RemoteViews(GlucoDataService.context!!.packageName, R.layout.image_view) - remoteViews.setImageViewBitmap(R.id.imageLayout, bitmap) - } - } - + fun getNotification(withContent: Boolean, iconKey: String, foreground: Boolean, customLayout: Boolean) : Notification { val notificationBuilder = if(foreground) foregroundNotificationCompat else notificationCompat - val notification = notificationBuilder + val notificationBuild = notificationBuilder .setSmallIcon(getStatusBarIcon(iconKey)) .setContentIntent(getTapActionIntent(foreground)) .setWhen(ReceiveData.time) - .setCustomContentView(remoteViews) - .setCustomBigContentView(remoteViews) .setColorized(false) - .setStyle(Notification.DecoratedCustomViewStyle()) - .build() + + if (customLayout) { + Log.v(LOG_ID, "Use custom layout") + var remoteViews: RemoteViews? = null + if (withContent) { + val bitmap = createNotificationView(GlucoDataService.context!!) + if (bitmap != null) { + remoteViews = + RemoteViews(GlucoDataService.context!!.packageName, R.layout.image_view) + remoteViews.setImageViewBitmap(R.id.imageLayout, bitmap) + } + } + notificationBuild.setCustomContentView(remoteViews) + notificationBuild.setCustomBigContentView(remoteViews) + notificationBuild.setStyle(Notification.DecoratedCustomViewStyle()) + } else { + Log.v(LOG_ID, "Use default layout") + if (withContent) { + notificationBuild.setContentTitle(ReceiveData.getGlucoseAsString() + " Δ " + ReceiveData.getDeltaAsString()) + if (!ReceiveData.isIobCobObsolete(Constants.VALUE_OBSOLETE_LONG_SEC)) { + notificationBuild.setContentText("💉 " + ReceiveData.getIobAsString() + if (!ReceiveData.cob.isNaN()) (" " + "🍔 " + ReceiveData.getCobAsString()) else "") + } else { + notificationBuild.setContentText(null) + } + notificationBuild.setLargeIcon(BitmapUtils.getRateAsBitmap(withShadow = true)) + } else { + notificationBuild.setContentTitle(null) + notificationBuild.setContentText(null) + } + notificationBuild.setStyle(null) + } + val notification = notificationBuild.build() notification.visibility = Notification.VISIBILITY_PUBLIC notification.flags = notification.flags or Notification.FLAG_NO_CLEAR return notification } - private fun showNotification(id: Int, withContent: Boolean, iconKey: String, foreground: Boolean) { + private fun showNotification(id: Int, withContent: Boolean, iconKey: String, foreground: Boolean, customLayout: Boolean) { try { Log.v(LOG_ID, "showNotification called for id " + id) Channels.getNotificationManager().notify( id, - getNotification(withContent, iconKey, foreground) + getNotification(withContent, iconKey, foreground, customLayout) ) } catch (exc: Exception) { Log.e(LOG_ID, "showNotification exception: " + exc.toString() ) @@ -230,7 +248,7 @@ object PermanentNotification: NotifierInterface, SharedPreferences.OnSharedPrefe showPrimaryNotification(true) if (sharedPref.getBoolean(Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION, false)) { Log.d(LOG_ID, "show second notification") - showNotification(SECOND_NOTIFICATION_ID, false, Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION_ICON, false) + showNotification(SECOND_NOTIFICATION_ID, false, Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION_ICON, false, false) } else { Channels.getNotificationManager().cancel(SECOND_NOTIFICATION_ID) } @@ -238,7 +256,13 @@ object PermanentNotification: NotifierInterface, SharedPreferences.OnSharedPrefe private fun showPrimaryNotification(show: Boolean) { Log.d(LOG_ID, "showPrimaryNotification " + show) - showNotification(GlucoDataService.NOTIFICATION_ID, !sharedPref.getBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY, false), Constants.SHARED_PREF_PERMANENT_NOTIFICATION_ICON, true) + showNotification( + GlucoDataService.NOTIFICATION_ID, + !sharedPref.getBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY, false), + Constants.SHARED_PREF_PERMANENT_NOTIFICATION_ICON, + true, + sharedPref.getBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, true) + ) } private fun hasContent(): Boolean { @@ -287,7 +311,7 @@ object PermanentNotification: NotifierInterface, SharedPreferences.OnSharedPrefe } } - override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences, key: String?) { try { Log.d(LOG_ID, "onSharedPreferenceChanged called for key " + key) when(key) { @@ -298,8 +322,16 @@ object PermanentNotification: NotifierInterface, SharedPreferences.OnSharedPrefe Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION_TAP_ACTION, Constants.SHARED_PREF_PERMANENT_NOTIFICATION_USE_BIG_ICON, Constants.SHARED_PREF_PERMANENT_NOTIFICATION_COLORED_ICON, - Constants.SHARED_PREF_PERMANENT_NOTIFICATION_TAP_ACTION, + Constants.SHARED_PREF_PERMANENT_NOTIFICATION_TAP_ACTION -> { + updatePreferences() + } Constants.SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY -> { + if(!sharedPreferences.getBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, true)) + createNofitication(GlucoDataService.context!!) // reset notification to remove large icon + updatePreferences() + } + Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT-> { + createNofitication(GlucoDataService.context!!) // reset notification to remove large icon updatePreferences() } } diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/AlarmFragment.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/AlarmFragment.kt index e7b4d828..933e7630 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/AlarmFragment.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/AlarmFragment.kt @@ -188,7 +188,7 @@ class AlarmFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPref } } private fun requestChannelActivation() { - Dialogs.showOkDialog(requireContext(), resources.getString(CR.string.permission_alarm_notification_title), resources.getString(CR.string.permission_alarm_notification_message)) { _, _ -> + Dialogs.showOkDialog(requireContext(),CR.string.permission_alarm_notification_title, CR.string.permission_alarm_notification_message) { _, _ -> val intent: Intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS) .putExtra(Settings.EXTRA_APP_PACKAGE, requireContext().packageName) startActivity(intent) diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SettingsFragmentBase.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SettingsFragmentBase.kt index bb5dd184..3e08012d 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SettingsFragmentBase.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SettingsFragmentBase.kt @@ -152,10 +152,10 @@ abstract class SettingsFragmentBase(private val prefResId: Int) : PreferenceFrag } } - fun setEnableState(sharedPreferences: SharedPreferences, key: String, enableKey: String, secondEnableKey: String? = null, defValue: Boolean = false) { + fun setEnableState(sharedPreferences: SharedPreferences, key: String, enableKey: String, secondEnableKey: String? = null, defValue: Boolean = false, invert: Boolean = false) { val pref = findPreference(key) if (pref != null) { - pref.isEnabled = sharedPreferences.getBoolean(enableKey, defValue) && (if (secondEnableKey != null) sharedPreferences.getBoolean(secondEnableKey, defValue) else true) + pref.isEnabled = invert != (sharedPreferences.getBoolean(enableKey, defValue) && (if (secondEnableKey != null) sharedPreferences.getBoolean(secondEnableKey, defValue) else true)) if(!updateEnablePrefs.contains(enableKey)) { Log.v(LOG_ID, "Add update enable pref $enableKey") @@ -191,6 +191,7 @@ abstract class SettingsFragmentBase(private val prefResId: Int) : PreferenceFrag setEnableState(sharedPreferences, Constants.SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY, Constants.SHARED_PREF_PERMANENT_NOTIFICATION, defValue = true) setEnableState(sharedPreferences, Constants.SHARED_PREF_PERMANENT_NOTIFICATION_USE_BIG_ICON, Constants.SHARED_PREF_PERMANENT_NOTIFICATION, defValue = true) setEnableState(sharedPreferences, Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION, Constants.SHARED_PREF_PERMANENT_NOTIFICATION, defValue = true)*/ + setEnableState(sharedPreferences, Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, Constants.SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY, defValue = true, invert = true) setEnableState(sharedPreferences, Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION_ICON, /*Constants.SHARED_PREF_PERMANENT_NOTIFICATION,*/Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION, defValue = false) setEnableState(sharedPreferences, Constants.SHARED_PREF_FLOATING_WIDGET_SIZE, Constants.SHARED_PREF_FLOATING_WIDGET) setEnableState(sharedPreferences, Constants.SHARED_PREF_FLOATING_WIDGET_STYLE, Constants.SHARED_PREF_FLOATING_WIDGET) diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SourceFragment.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SourceFragment.kt index 493d8414..215d55df 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SourceFragment.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SourceFragment.kt @@ -134,7 +134,7 @@ class SourceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPre val pref = findPreference(key) if(pref != null) { val value = preferenceManager.sharedPreferences!!.getString(key, "")!!.trim() - pref.summary = if(value.isNullOrEmpty()) + pref.summary = if(value.isEmpty()) resources.getString(defaultResId) else value @@ -156,7 +156,7 @@ class SourceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPre Constants.SHARED_PREF_LIBRE_PATIENT_ID, "" )!!.trim() - if (value.isNullOrEmpty() || !LibreLinkSourceTask.patientData.containsKey(value)) + if (value.isEmpty() || !LibreLinkSourceTask.patientData.containsKey(value)) pref.summary = resources.getString(CR.string.src_libre_patient_summary) else { pref.summary = LibreLinkSourceTask.patientData[value] @@ -181,8 +181,8 @@ class SourceFragment : PreferenceFragmentCompat(), SharedPreferences.OnSharedPre private fun setupLocalIobAction(preference: Preference?) { if(preference != null) { preference.setOnPreferenceClickListener { - Dialogs.showOkCancelDialog(requireContext(), resources.getString(de.michelinside.glucodatahandler.common.R.string.activate_local_nightscout_iob_title), resources.getString( - de.michelinside.glucodatahandler.common.R.string.activate_local_nightscout_iob_message)) { _, _ -> + Dialogs.showOkCancelDialog(requireContext(), CR.string.activate_local_nightscout_iob_title, + CR.string.activate_local_nightscout_iob_message) { _, _ -> with(preferenceManager!!.sharedPreferences!!.edit()) { putBoolean(Constants.SHARED_PREF_NIGHTSCOUT_IOB_COB, true) putString(Constants.SHARED_PREF_NIGHTSCOUT_URL, "http://127.0.0.1:17580") diff --git a/mobile/src/main/res/xml/pref_notification.xml b/mobile/src/main/res/xml/pref_notification.xml index 1ac46a04..c8a81710 100644 --- a/mobile/src/main/res/xml/pref_notification.xml +++ b/mobile/src/main/res/xml/pref_notification.xml @@ -24,6 +24,12 @@ android:summary="@string/pref_notification_icon_summary" android:title="@string/pref_notification_icon" app:iconSpaceReserved="false" /> + Date: Sat, 8 Jun 2024 20:27:00 +0200 Subject: [PATCH 13/26] v47 (1.0.1) --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index b1a89a29..bc47d0e8 100644 --- a/build.gradle +++ b/build.gradle @@ -5,8 +5,8 @@ plugins { id 'org.jetbrains.kotlin.android' version '1.9.23' apply false } -project.ext.set("versionCode", 46) -project.ext.set("versionName", "1.0") +project.ext.set("versionCode", 47) +project.ext.set("versionName", "1.0.1") project.ext.set("compileSdk", 34) project.ext.set("targetSdk", 33) project.ext.set("minSdk", 26) From 4a903ce08af2cb0b974301fc86277a7f67c08b6f Mon Sep 17 00:00:00 2001 From: pachi81 Date: Sat, 8 Jun 2024 20:28:44 +0200 Subject: [PATCH 14/26] GDA: uncaught ExceptionHandler --- .../de/michelinside/glucodataauto/Dialogs.kt | 55 +++++++++++++++++++ .../glucodataauto/GlucoDataServiceAuto.kt | 3 + .../glucodataauto/MainActivity.kt | 14 +++++ 3 files changed, 72 insertions(+) create mode 100644 auto/src/main/java/de/michelinside/glucodataauto/Dialogs.kt diff --git a/auto/src/main/java/de/michelinside/glucodataauto/Dialogs.kt b/auto/src/main/java/de/michelinside/glucodataauto/Dialogs.kt new file mode 100644 index 00000000..7d96450a --- /dev/null +++ b/auto/src/main/java/de/michelinside/glucodataauto/Dialogs.kt @@ -0,0 +1,55 @@ +package de.michelinside.glucodataauto + +import android.app.UiModeManager +import android.content.Context +import android.content.DialogInterface +import android.os.Build +import androidx.appcompat.app.AppCompatDelegate +import com.google.android.material.dialog.MaterialAlertDialogBuilder +import de.michelinside.glucodatahandler.common.Constants +import de.michelinside.glucodatahandler.common.R + + +object Dialogs { + fun showOkDialog(context: Context, titleResId: Int, messageResId: Int, okListener: DialogInterface.OnClickListener?) { + MaterialAlertDialogBuilder(context) + .setTitle(context.resources.getString(titleResId)) + .setMessage(context.resources.getString(messageResId)) + .setPositiveButton(context.resources.getText(R.string.button_ok), okListener) + .show() + } + fun showOkCancelDialog(context: Context, titleResId: Int, messageResId: Int, okListener: DialogInterface.OnClickListener?) { + MaterialAlertDialogBuilder(context) + .setTitle(context.resources.getString(titleResId)) + .setMessage(context.resources.getString(messageResId)) + .setPositiveButton(context.resources.getText(R.string.button_ok), okListener) + .setNegativeButton(context.resources.getText(R.string.button_cancel), null) + .show() + } + + fun updateColorScheme(context: Context) { + val sharedPref = context.getSharedPreferences(Constants.SHARED_PREF_TAG, Context.MODE_PRIVATE) + val colorScheme = sharedPref.getString(Constants.SHARED_PREF_APP_COLOR_SCHEME, "") + // This will be the top level handling of theme + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + // If you don't want to adapt the device's theme settings, uncomment the snippet below + val uiModeManager = context.getSystemService(Context.UI_MODE_SERVICE) as UiModeManager + uiModeManager.setApplicationNightMode( + when (colorScheme) { + "light" -> UiModeManager.MODE_NIGHT_NO // User set this explicitly + "dark" -> UiModeManager.MODE_NIGHT_YES // User set this explicitly + else -> UiModeManager.MODE_NIGHT_AUTO // Follow the device Dark Theme settings when not define yet by user + } + ) + } else { + AppCompatDelegate.setDefaultNightMode( + when (colorScheme) { + "light" -> AppCompatDelegate.MODE_NIGHT_NO // User set this explicitly + "dark" -> AppCompatDelegate.MODE_NIGHT_YES // User set this explicitly + else -> AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM // For Android 10 and 11, follow the device Dark Theme settings when not define yet by user + } + ) + + } + } +} \ No newline at end of file diff --git a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt index d8095fc2..7308b267 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt @@ -13,6 +13,7 @@ import androidx.car.app.connection.CarConnection import de.michelinside.glucodataauto.android_auto.CarMediaBrowserService import de.michelinside.glucodataauto.android_auto.CarNotification import de.michelinside.glucodatahandler.common.Constants +import de.michelinside.glucodatahandler.common.GdhUncaughtExecptionHandler import de.michelinside.glucodatahandler.common.GlucoDataService import de.michelinside.glucodatahandler.common.ReceiveData import de.michelinside.glucodatahandler.common.notification.ChannelType @@ -25,6 +26,7 @@ import de.michelinside.glucodatahandler.common.tasks.TimeTaskService import de.michelinside.glucodatahandler.common.utils.PackageUtils class GlucoDataServiceAuto: Service() { + private lateinit var uncaughtExecptionHandler: GdhUncaughtExecptionHandler companion object { private const val LOG_ID = "GDH.AA.GlucoDataServiceAuto" private var isForegroundService = false @@ -175,6 +177,7 @@ class GlucoDataServiceAuto: Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { try { Log.d(LOG_ID, "onStartCommand called") + uncaughtExecptionHandler = GdhUncaughtExecptionHandler(this) super.onStartCommand(intent, flags, startId) GlucoDataService.context = applicationContext ReceiveData.initData(applicationContext) diff --git a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt index 2418c0da..0f5870a6 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/MainActivity.kt @@ -154,6 +154,7 @@ class MainActivity : AppCompatActivity(), NotifierInterface { try { Log.d(LOG_ID, "onResume called") super.onResume() + checkUncaughtException() update() InternalNotifier.addNotifier( this, this, mutableSetOf( NotifySource.BROADCAST, @@ -541,4 +542,17 @@ class MainActivity : AppCompatActivity(), NotifierInterface { companion object { const val CREATE_FILE = 1 } + + private fun checkUncaughtException() { + Log.d(LOG_ID, "Check uncaught exception ${sharedPref.getBoolean(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT, false)}") + if(sharedPref.getBoolean(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT, false)) { + val excMsg = sharedPref.getString(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_MESSAGE, "") + Log.e(LOG_ID, "Uncaught exception detected last time: $excMsg") + with(sharedPref.edit()) { + putBoolean(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT, false) + apply() + } + Dialogs.showOkDialog(this, CR.string.app_crash_title, CR.string.app_crash_message, null) + } + } } \ No newline at end of file From 41ce1b025815593eae72b3ab64b50a6b188552f5 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Sun, 9 Jun 2024 11:19:03 +0200 Subject: [PATCH 15/26] fix uncaught ExceptionHandler --- .../glucodataauto/GlucoDataServiceAuto.kt | 4 +- .../common/GdhUncaughtExecptionHandler.kt | 72 +++++++++++++------ .../common/GlucoDataService.kt | 3 +- 3 files changed, 52 insertions(+), 27 deletions(-) diff --git a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt index 7308b267..50463dde 100644 --- a/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt +++ b/auto/src/main/java/de/michelinside/glucodataauto/GlucoDataServiceAuto.kt @@ -26,7 +26,7 @@ import de.michelinside.glucodatahandler.common.tasks.TimeTaskService import de.michelinside.glucodatahandler.common.utils.PackageUtils class GlucoDataServiceAuto: Service() { - private lateinit var uncaughtExecptionHandler: GdhUncaughtExecptionHandler + companion object { private const val LOG_ID = "GDH.AA.GlucoDataServiceAuto" private var isForegroundService = false @@ -177,7 +177,7 @@ class GlucoDataServiceAuto: Service() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { try { Log.d(LOG_ID, "onStartCommand called") - uncaughtExecptionHandler = GdhUncaughtExecptionHandler(this) + GdhUncaughtExecptionHandler.init() super.onStartCommand(intent, flags, startId) GlucoDataService.context = applicationContext ReceiveData.initData(applicationContext) diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/GdhUncaughtExecptionHandler.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/GdhUncaughtExecptionHandler.kt index 891710ea..9318754f 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/GdhUncaughtExecptionHandler.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/GdhUncaughtExecptionHandler.kt @@ -1,43 +1,69 @@ package de.michelinside.glucodatahandler.common -import android.content.Context import android.util.Log import java.lang.Exception import kotlin.system.exitProcess -class GdhUncaughtExecptionHandler(val context: Context) : Thread.UncaughtExceptionHandler { +object GdhUncaughtExecptionHandler : Thread.UncaughtExceptionHandler { private val LOG_ID = "GDH.UncaughtExceptionHandler" - private var defaultHandler: Thread.UncaughtExceptionHandler + private var defaultHandler: Thread.UncaughtExceptionHandler? = null + private var exceptionCaught = false - init { - defaultHandler = Thread.getDefaultUncaughtExceptionHandler()!! - Thread.setDefaultUncaughtExceptionHandler(this) + fun init() { + Log.d(LOG_ID, "init called") + if(defaultHandler == null) { + defaultHandler = Thread.getDefaultUncaughtExceptionHandler()!! + Log.d(LOG_ID, "Replace default handler $defaultHandler") + Thread.setDefaultUncaughtExceptionHandler(this) + } } override fun uncaughtException(t: Thread, e: Throwable) { try { - val message = "${e.message}\n${e.stackTraceToString()}" - Log.e(LOG_ID, "Uncaught exception detected in thread ${t.name}: $message") - val sharedPref = context.getSharedPreferences(Constants.SHARED_PREF_TAG, Context.MODE_PRIVATE) - val customLayoutEnabled = sharedPref.getBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, true) - with(sharedPref.edit()) { - putBoolean(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT, true) - putString(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_MESSAGE, message) - if (message.contains("BadForegroundServiceNotificationException") || message.contains("RemoteServiceException")) { - Log.e(LOG_ID, "BadForegroundServiceNotificationException detected! customLayoutEnabled=$customLayoutEnabled") - if (customLayoutEnabled) - putBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, false) - else - putBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY, true) + if(!exceptionCaught) { + exceptionCaught = true + val message = "${e.message}\n${e.stackTraceToString()}" + Log.e(LOG_ID, "Uncaught exception detected in thread ${t.name}: $message") + if(GlucoDataService.sharedPref != null) { + val sharedPref = GlucoDataService.sharedPref!! + val customLayoutEnabled = sharedPref.getBoolean( + Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, + true + ) + with(sharedPref.edit()) { + putBoolean(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_DETECT, true) + putString(Constants.SHARED_PREF_UNCAUGHT_EXCEPTION_MESSAGE, message) + if (message.contains("BadForegroundServiceNotificationException") || message.contains( + "RemoteServiceException" + ) + ) { + Log.e( + LOG_ID, + "BadForegroundServiceNotificationException detected! customLayoutEnabled=$customLayoutEnabled" + ) + if (customLayoutEnabled) + putBoolean( + Constants.SHARED_PREF_PERMANENT_NOTIFICATION_CUSTOM_LAYOUT, + false + ) + else + putBoolean(Constants.SHARED_PREF_PERMANENT_NOTIFICATION_EMPTY, true) + } + apply() + Thread.sleep(100) // wait for saving + Log.v(LOG_ID, "Exception saved!") + } } - apply() - Thread.sleep(100) // wait for saving - Log.v(LOG_ID, "Exception saved!") + } else { + Log.d(LOG_ID, "Exception already handled!") } } catch (e: Exception) { Log.e(LOG_ID, "Exception: ${e.message}") } - exitProcess(10) + if(defaultHandler!=null) + defaultHandler!!.uncaughtException(t, e) + else + exitProcess(10) } } \ No newline at end of file diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt index bacfca36..18c8da81 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt @@ -30,7 +30,6 @@ abstract class GlucoDataService(source: AppSource) : WearableListenerService() { private lateinit var batteryReceiver: BatteryReceiver private lateinit var xDripReceiver: XDripBroadcastReceiver private lateinit var aapsReceiver: AAPSReceiver - private lateinit var uncaughtExecptionHandler: GdhUncaughtExecptionHandler @SuppressLint("StaticFieldLeak") companion object { @@ -138,7 +137,7 @@ abstract class GlucoDataService(source: AppSource) : WearableListenerService() { override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { try { Log.v(LOG_ID, "onStartCommand called") - uncaughtExecptionHandler = GdhUncaughtExecptionHandler(this) + GdhUncaughtExecptionHandler.init() super.onStartCommand(intent, flags, startId) val isForeground = true // intent?.getBooleanExtra(Constants.SHARED_PREF_FOREGROUND_SERVICE, true) --> always use foreground!!! if (isForeground && !isForegroundService) { From faa8e38f365e4b05b110a4bd78f0d0276045ac4a Mon Sep 17 00:00:00 2001 From: pachi81 Date: Sun, 9 Jun 2024 11:33:57 +0200 Subject: [PATCH 16/26] Change widget style summary --- .../preferences/SettingsFragmentBase.kt | 26 ++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SettingsFragmentBase.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SettingsFragmentBase.kt index 3e08012d..028d2681 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SettingsFragmentBase.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/preferences/SettingsFragmentBase.kt @@ -242,7 +242,29 @@ abstract class SettingsFragmentBase(private val prefResId: Int) : PreferenceFrag class GeneralSettingsFragment: SettingsFragmentBase(R.xml.pref_general) {} class RangeSettingsFragment: SettingsFragmentBase(R.xml.pref_target_range) {} class UiSettingsFragment: SettingsFragmentBase(R.xml.pref_ui) {} -class WidgetSettingsFragment: SettingsFragmentBase(R.xml.pref_widgets) {} +class WidgetSettingsFragment: SettingsFragmentBase(R.xml.pref_widgets) { + + override fun initPreferences() { + Log.v(LOG_ID, "initPreferences called") + super.initPreferences() + updateStyleSummary() + } + + override fun onSharedPreferenceChanged(sharedPreferences: SharedPreferences?, key: String?) { + super.onSharedPreferenceChanged(sharedPreferences, key) + when (key) { + Constants.SHARED_PREF_FLOATING_WIDGET_STYLE -> updateStyleSummary() + } + } + + private fun updateStyleSummary() { + val stylePref = findPreference(Constants.SHARED_PREF_FLOATING_WIDGET_STYLE) + if(stylePref != null) { + stylePref.summary = stylePref.entry + } + } + +} class NotificaitonSettingsFragment: SettingsFragmentBase(R.xml.pref_notification) {} class LockscreenSettingsFragment: SettingsFragmentBase(R.xml.pref_lockscreen) {} class WatchSettingsFragment: SettingsFragmentBase(R.xml.pref_watch) { @@ -268,6 +290,7 @@ class WatchSettingsFragment: SettingsFragmentBase(R.xml.pref_watch) { class TransferSettingsFragment: SettingsFragmentBase(R.xml.pref_transfer) { override fun initPreferences() { Log.v(LOG_ID, "initPreferences called") + super.initPreferences() setupReceivers(Constants.GLUCODATA_BROADCAST_ACTION, Constants.SHARED_PREF_GLUCODATA_RECEIVERS) setupReceivers(Constants.XDRIP_ACTION_GLUCOSE_READING, Constants.SHARED_PREF_XDRIP_RECEIVERS) setupReceivers(Constants.XDRIP_BROADCAST_ACTION, Constants.SHARED_PREF_XDRIP_BROADCAST_RECEIVERS) @@ -277,6 +300,7 @@ class TransferSettingsFragment: SettingsFragmentBase(R.xml.pref_transfer) { class GDASettingsFragment: SettingsFragmentBase(R.xml.pref_gda) { override fun initPreferences() { Log.v(LOG_ID, "initPreferences called") + super.initPreferences() if (PackageUtils.isGlucoDataAutoAvailable(requireContext())) { val sendToGDA = findPreference(Constants.SHARED_PREF_SEND_TO_GLUCODATAAUTO) sendToGDA!!.isVisible = true From 95fadcf23888f81c4e032c2fe39d24727235428e Mon Sep 17 00:00:00 2001 From: pachi81 Date: Sun, 9 Jun 2024 13:48:33 +0200 Subject: [PATCH 17/26] Additional fix for notification --- .../common/GlucoDataService.kt | 1 + .../GlucoDataServiceMobile.kt | 15 +++++++++++ .../notification/PermanentNotification.kt | 26 ++++++++++++++----- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt index 18c8da81..3e4aaeb8 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/GlucoDataService.kt @@ -158,6 +158,7 @@ abstract class GlucoDataService(source: AppSource) : WearableListenerService() { return START_STICKY // keep alive } + @SuppressLint("UnspecifiedRegisterReceiverFlag") override fun onCreate() { try { diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/GlucoDataServiceMobile.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/GlucoDataServiceMobile.kt index 85013d63..39fa67b2 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/GlucoDataServiceMobile.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/GlucoDataServiceMobile.kt @@ -4,8 +4,10 @@ import android.app.Notification import android.content.Context import android.content.Intent import android.content.SharedPreferences +import android.os.Build import android.os.Bundle import android.util.Log +import androidx.annotation.RequiresApi import de.michelinside.glucodatahandler.android_auto.CarModeReceiver import de.michelinside.glucodatahandler.common.* import de.michelinside.glucodatahandler.notification.AlarmNotification @@ -78,6 +80,19 @@ class GlucoDataServiceMobile: GlucoDataService(AppSource.PHONE_APP), NotifierInt } } + @RequiresApi(Build.VERSION_CODES.Q) + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + try { + Log.d(LOG_ID, "onStartCommand called") + val start = super.onStartCommand(intent, flags, startId) + PermanentNotification.showNotifications(true) + return start + } catch (exc: Exception) { + Log.e(LOG_ID, "onStartCommand exception: " + exc.toString()) + } + return START_STICKY // keep alive + } + private fun migrateSettings() { try { Log.v(LOG_ID, "migrateSettings called") diff --git a/mobile/src/main/java/de/michelinside/glucodatahandler/notification/PermanentNotification.kt b/mobile/src/main/java/de/michelinside/glucodatahandler/notification/PermanentNotification.kt index f4348608..aaf8d74a 100644 --- a/mobile/src/main/java/de/michelinside/glucodatahandler/notification/PermanentNotification.kt +++ b/mobile/src/main/java/de/michelinside/glucodatahandler/notification/PermanentNotification.kt @@ -80,6 +80,7 @@ object PermanentNotification: NotifierInterface, SharedPreferences.OnSharedPrefe } private fun createNofitication(context: Context) { + Log.d(LOG_ID, "createNofitication called") createNotificationChannel(context) Channels.getNotificationManager().cancel(GlucoDataService.NOTIFICATION_ID) @@ -188,6 +189,7 @@ object PermanentNotification: NotifierInterface, SharedPreferences.OnSharedPrefe } fun getNotification(withContent: Boolean, iconKey: String, foreground: Boolean, customLayout: Boolean) : Notification { + Log.d(LOG_ID, "getNotification withContent=$withContent - foreground=$foreground - customLayout=$customLayout") val notificationBuilder = if(foreground) foregroundNotificationCompat else notificationCompat val notificationBuild = notificationBuilder .setSmallIcon(getStatusBarIcon(iconKey)) @@ -244,13 +246,23 @@ object PermanentNotification: NotifierInterface, SharedPreferences.OnSharedPrefe } } - fun showNotifications() { - showPrimaryNotification(true) - if (sharedPref.getBoolean(Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION, false)) { - Log.d(LOG_ID, "show second notification") - showNotification(SECOND_NOTIFICATION_ID, false, Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION_ICON, false, false) - } else { - Channels.getNotificationManager().cancel(SECOND_NOTIFICATION_ID) + fun showNotifications(onlySecond: Boolean = false) { + Log.d(LOG_ID, "showNotifications service running: ${GlucoDataService.foreground} - onlySecond=$onlySecond") + if (GlucoDataService.foreground) { + if (!onlySecond) + showPrimaryNotification(true) + if (sharedPref.getBoolean(Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION, false)) { + Log.d(LOG_ID, "show second notification") + showNotification( + SECOND_NOTIFICATION_ID, + false, + Constants.SHARED_PREF_SECOND_PERMANENT_NOTIFICATION_ICON, + false, + false + ) + } else { + Channels.getNotificationManager().cancel(SECOND_NOTIFICATION_ID) + } } } From 1c0f1b3c2d25e303cbaa78614643ca78c4956a32 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Sun, 9 Jun 2024 13:49:27 +0200 Subject: [PATCH 18/26] v48 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index bc47d0e8..c634c916 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'org.jetbrains.kotlin.android' version '1.9.23' apply false } -project.ext.set("versionCode", 47) +project.ext.set("versionCode", 48) project.ext.set("versionName", "1.0.1") project.ext.set("compileSdk", 34) project.ext.set("targetSdk", 33) From 7cfefa8132fff1f296bd5d795a9b4ed93add02f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arkadiusz=20Deli=C5=9B?= <137992536+froster82@users.noreply.github.com> Date: Mon, 10 Jun 2024 10:51:12 +0200 Subject: [PATCH 19/26] Update strings.xml PL --- common/src/main/res/values-pl/strings.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/common/src/main/res/values-pl/strings.xml b/common/src/main/res/values-pl/strings.xml index 6b6d8403..3c9b109a 100644 --- a/common/src/main/res/values-pl/strings.xml +++ b/common/src/main/res/values-pl/strings.xml @@ -483,11 +483,11 @@ Konfiguracja Android Auto Aby aktywować GlucoDataAuto dla Android Auto, należy wykonać następujące kroki: 1. Aktywacja trybu programisty - - otwórz aplikację Android Auto\n- przewiń w dół do pozycji Wersja\n- dotknij kilkakrotnie pozycji Wersja, aż pojawi się wyskakujące okienko „Zezwalaj na ustawienia programistyczne\"\n- naciśnij \"OK\" + - otwórz aplikację Android Auto\n- przewiń w dół do pozycji Wersja\n- dotknij kilkakrotnie pozycji Wersja, aż pojawi się wyskakujące okienko „Zezwalaj na ustawienia programisty\"\n- naciśnij \"OK\" 2. Aktywuj „Nieznane źródła\" - - otwórz aplikację Android Auto\n- otwórz w menu (3 kropki) „Ustawienia programisty\"\n- przewiń w dół do pozycji „Nieznane źródło\"\n- włącz ją + - otwórz aplikację Android Auto\n- otwórz w menu (3 kropki) „Ustawienia programisty\"\n- przewiń w dół do pozycji „Nieznane źródła\"\n- włącz ją 3. Ustawienia powiadomień - - otwórz aplikację Android Auto\n- przewiń w dół do pozycji „Powiadomienia\"\n- włącz „Pokazuj rozmowy\"\n- włącz „Pokazuj pierwszy wiersz rozmów\" + - otwórz aplikację Android Auto\n- przewiń w dół do pozycji „Powiadomienia\"\n- włącz „Pokaż podgląd wiadomości przychodzących\"\n- włącz „Pokazuj pierwszy wiersz wiadomości\" Kolorowy układ Wyświetla wartości dużą i kolorową czcionką.\nNa niektórych urządzeniach Samsung z Androidem 13 i nowszym, może to spowodować awarię aplikacji z powodu błędu po stronie Samsunga.\nJeśli problem wystąpi, to ustawienie zostanie automatycznie wyłączone, aby aplikacja mogła działać poprawnie. Wykryto awarię! From a4d9d50ed4ff0eca9460bc5523112a15f6efcd32 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Mon, 10 Jun 2024 13:33:54 +0200 Subject: [PATCH 20/26] fix snooze end detection --- auto/src/main/AndroidManifest.xml | 1 + .../common/notification/AlarmHandler.kt | 73 ++++++++++++++++++- mobile/src/main/AndroidManifest.xml | 1 + .../glucodatahandler/MainActivity.kt | 6 +- wear/src/main/AndroidManifest.xml | 1 + 5 files changed, 80 insertions(+), 2 deletions(-) diff --git a/auto/src/main/AndroidManifest.xml b/auto/src/main/AndroidManifest.xml index e317c338..9da27997 100644 --- a/auto/src/main/AndroidManifest.xml +++ b/auto/src/main/AndroidManifest.xml @@ -106,6 +106,7 @@ + = System.currentTimeMillis() } @@ -112,10 +120,11 @@ object AlarmHandler: SharedPreferences.OnSharedPreferenceChangeListener, Notifie fun setSnoozeTime(time: Long, fromClient: Boolean = false) { snoozeTime = time - Log.d(LOG_ID, "New snooze-time: $snoozeTimestamp") + Log.i(LOG_ID, "New snooze-time: $snoozeTimestamp") saveExtras() if(GlucoDataService.context != null) { InternalNotifier.notify(GlucoDataService.context!!, NotifySource.ALARM_STATE_CHANGED, null) + triggerSnoozeEnd(GlucoDataService.context!!) } if(!fromClient) { val bundle = Bundle() @@ -334,4 +343,66 @@ object AlarmHandler: SharedPreferences.OnSharedPreferenceChangeListener, Notifie } } } + + fun triggerSnoozeEnd(context: Context) { + stopSnoozeEnd() + if(isSnoozeActive) { + alarmManager = context.getSystemService(Context.ALARM_SERVICE) as AlarmManager + var hasExactAlarmPermission = true + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) { + if (!alarmManager!!.canScheduleExactAlarms()) { + Log.d(LOG_ID, "Need permission to set exact alarm!") + hasExactAlarmPermission = false + } + } + val intent = Intent(context, AlarmSnoozeEndReceiver::class.java) + intent.addFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES) + snoozeEndPendingIntent = PendingIntent.getBroadcast( + context, + 800, + intent, + PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT + ) + Log.i(LOG_ID, "Trigger SnoozeEnd at $snoozeTimestamp - exact-alarm=$hasExactAlarmPermission") + if (hasExactAlarmPermission) { + alarmManager!!.setExactAndAllowWhileIdle( + AlarmManager.RTC_WAKEUP, + snoozeTime, + snoozeEndPendingIntent!! + ) + } else { + alarmManager!!.setAndAllowWhileIdle( + AlarmManager.RTC_WAKEUP, + snoozeTime, + snoozeEndPendingIntent!! + ) + } + } + } + + fun stopSnoozeEnd() { + if(alarmManager != null && snoozeEndPendingIntent != null) { + Log.i(LOG_ID, "Stop SnoozeEnd triggered") + alarmManager!!.cancel(snoozeEndPendingIntent!!) + alarmManager = null + snoozeEndPendingIntent = null + } + } +} + + +class AlarmSnoozeEndReceiver: BroadcastReceiver() { + private val LOG_ID = "GDH.AlarmSnoozeEndReceiver" + override fun onReceive(context: Context, intent: Intent) { + try { + Log.d(LOG_ID, "onReceive called snoozeActive:${AlarmHandler.isSnoozeActive}") + if(!AlarmHandler.isSnoozeActive) { + Log.i(LOG_ID, "End of snooze reached") + InternalNotifier.notify(context, NotifySource.ALARM_STATE_CHANGED, null) + AlarmHandler.stopSnoozeEnd() + } + } catch (exc: Exception) { + Log.e(LOG_ID, "onReceive exception: " + exc.toString()) + } + } } \ No newline at end of file diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml index ac92e646..f2c66696 100644 --- a/mobile/src/main/AndroidManifest.xml +++ b/mobile/src/main/AndroidManifest.xml @@ -247,6 +247,7 @@ + { - AlarmHandler.setSnooze(30L) + if(BuildConfig.DEBUG) { + AlarmHandler.setSnooze(1L) + } else { + AlarmHandler.setSnooze(30L) + } return true } R.id.action_snooze_60 -> { diff --git a/wear/src/main/AndroidManifest.xml b/wear/src/main/AndroidManifest.xml index bcc7be26..a6ebb295 100644 --- a/wear/src/main/AndroidManifest.xml +++ b/wear/src/main/AndroidManifest.xml @@ -140,6 +140,7 @@ + Date: Mon, 10 Jun 2024 13:47:51 +0200 Subject: [PATCH 21/26] AlarmNotification refactor --- .../notification/AlarmNotificationBase.kt | 54 +++++++------------ 1 file changed, 18 insertions(+), 36 deletions(-) diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt index dbac47ed..72a65975 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt @@ -60,7 +60,6 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha private var vibratorInstance: Vibrator? = null private var alarmManager: AlarmManager? = null private var alarmPendingIntent: PendingIntent? = null - private var alarmNotificationActive: Boolean = false private var useAlarmSound: Boolean = true private var currentAlarmState: AlarmState = AlarmState.DISABLED @@ -102,13 +101,10 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha if(state == AlarmState.DISABLED || !channelActive(context)) { state = AlarmState.DISABLED } else if(state == AlarmState.ACTIVE) { - if(!alarmNotificationActive) { - initNotifier(context) - } - if(!active || !alarmNotificationActive) { + if(!active) { Log.d( LOG_ID, - "Inactive causes by active: $active - notification-active: $alarmNotificationActive" + "Inactive causes by active: $active" ) state = AlarmState.INACTIVE } @@ -120,10 +116,6 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha return state } - private fun isAlarmActive(context: Context): Boolean { - return AlarmState.currentState(context) == AlarmState.ACTIVE - } - fun initNotifications(context: Context) { try { Log.v(LOG_ID, "initNotifications called") @@ -133,12 +125,25 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha val sharedPref = context.getSharedPreferences(Constants.SHARED_PREF_TAG, Context.MODE_PRIVATE) sharedPref.registerOnSharedPreferenceChangeListener(this) onSharedPreferenceChanged(sharedPref, null) - initNotifier() + initNotifier(context) } catch (exc: Exception) { Log.e(LOG_ID, "initNotifications exception: " + exc.toString() ) } } + open fun getNotifierFilter(): MutableSet { + return mutableSetOf() + } + + fun initNotifier(context: Context) { + Log.v(LOG_ID, "initNotifier called") + val filter = mutableSetOf(NotifySource.ALARM_STATE_CHANGED) + filter.add(NotifySource.ALARM_TRIGGER) + filter.add(NotifySource.OBSOLETE_ALARM_TRIGGER) + filter.addAll(getNotifierFilter()) + InternalNotifier.addNotifier(context, this, filter ) + } + fun getEnabled(): Boolean = enabled private fun setEnabled(newEnabled: Boolean) { @@ -147,7 +152,6 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha if (enabled != newEnabled) { enabled = newEnabled Log.i(LOG_ID, "enable alarm notifications: $newEnabled") - initNotifier() if(!enabled) { stopCurrentNotification() } @@ -760,14 +764,13 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha Log.d(LOG_ID, "OnNotifyData called for $dataSource") when(dataSource) { NotifySource.ALARM_TRIGGER -> { - if (ReceiveData.forceAlarm) - triggerNotification(ReceiveData.getAlarmType(), context) + triggerNotification(ReceiveData.getAlarmType(), context) } NotifySource.OBSOLETE_ALARM_TRIGGER -> { triggerNotification(AlarmType.OBSOLETE, context) } NotifySource.ALARM_STATE_CHANGED -> { - initNotifier(context) + AlarmState.currentState(context) } else -> Log.w(LOG_ID, "Unsupported source $dataSource") } @@ -802,27 +805,6 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha } } - open fun getNotifierFilter(): MutableSet { - return mutableSetOf() - } - - fun initNotifier(context: Context? = null) { - val requireConext = context ?: GlucoDataService.context!! - val newActive = isAlarmActive(requireConext) - Log.v(LOG_ID, "initNotifier called for newActive: $newActive") - if(alarmNotificationActive != newActive) { - Log.i(LOG_ID, "Change alarm notification active to ${newActive}") - alarmNotificationActive = newActive - val filter = mutableSetOf(NotifySource.ALARM_STATE_CHANGED) - if(alarmNotificationActive) { - filter.add(NotifySource.ALARM_TRIGGER) - filter.add(NotifySource.OBSOLETE_ALARM_TRIGGER) - } - filter.addAll(getNotifierFilter()) - InternalNotifier.addNotifier(requireConext, this, filter ) - } - } - fun hasFullscreenPermission(): Boolean { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.UPSIDE_DOWN_CAKE) return Channels.getNotificationManager().canUseFullScreenIntent() From afa91aa85ee1581bacda68db25ed7e778fab9d4b Mon Sep 17 00:00:00 2001 From: pachi81 Date: Mon, 10 Jun 2024 13:53:08 +0200 Subject: [PATCH 22/26] v49 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index c634c916..f27eceb8 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'org.jetbrains.kotlin.android' version '1.9.23' apply false } -project.ext.set("versionCode", 48) +project.ext.set("versionCode", 49) project.ext.set("versionName", "1.0.1") project.ext.set("compileSdk", 34) project.ext.set("targetSdk", 33) From ba871ac052a3c51487ce100140155fd8f7cc12d2 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Mon, 10 Jun 2024 14:51:59 +0200 Subject: [PATCH 23/26] Fix notification output --- .../common/notification/AlarmNotificationBase.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt b/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt index 72a65975..04eea980 100644 --- a/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt +++ b/common/src/main/java/de/michelinside/glucodatahandler/common/notification/AlarmNotificationBase.kt @@ -770,7 +770,7 @@ abstract class AlarmNotificationBase: NotifierInterface, SharedPreferences.OnSha triggerNotification(AlarmType.OBSOLETE, context) } NotifySource.ALARM_STATE_CHANGED -> { - AlarmState.currentState(context) + getAlarmState(context) } else -> Log.w(LOG_ID, "Unsupported source $dataSource") } From ba24c669bb65041fa8160c69535f4e12815d2995 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Mon, 10 Jun 2024 19:58:35 +0200 Subject: [PATCH 24/26] v50 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index f27eceb8..676e2c1e 100644 --- a/build.gradle +++ b/build.gradle @@ -5,7 +5,7 @@ plugins { id 'org.jetbrains.kotlin.android' version '1.9.23' apply false } -project.ext.set("versionCode", 49) +project.ext.set("versionCode", 50) project.ext.set("versionName", "1.0.1") project.ext.set("compileSdk", 34) project.ext.set("targetSdk", 33) From f3620386910c777ef4c2d9c4240be60506c38ae8 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Mon, 10 Jun 2024 19:59:28 +0200 Subject: [PATCH 25/26] GDA: adjust help --- auto/src/main/res/xml/help.xml | 5 +++++ common/src/main/res/values-de/strings.xml | 10 ++++++---- common/src/main/res/values-es/strings.xml | 10 ++++++---- common/src/main/res/values-pl/strings.xml | 10 ++++++---- common/src/main/res/values-pt/strings.xml | 10 ++++++---- common/src/main/res/values/strings.xml | 10 ++++++---- 6 files changed, 35 insertions(+), 20 deletions(-) diff --git a/auto/src/main/res/xml/help.xml b/auto/src/main/res/xml/help.xml index 50e5441f..b239a215 100644 --- a/auto/src/main/res/xml/help.xml +++ b/auto/src/main/res/xml/help.xml @@ -23,5 +23,10 @@ android:title="@string/gda_help_aa_notification" android:summary="@string/gda_help_aa_notification_summary" app:iconSpaceReserved="false" /> + \ No newline at end of file diff --git a/common/src/main/res/values-de/strings.xml b/common/src/main/res/values-de/strings.xml index 52d36dfc..6cccdb6e 100644 --- a/common/src/main/res/values-de/strings.xml +++ b/common/src/main/res/values-de/strings.xml @@ -473,13 +473,15 @@ Akkuoptimierungen sind aktiv!\nHier drücken, um es zu deaktivieren. Wenn du eine Online Datenquelle verwendest, wird die App möglicherweise nicht gestartet, wenn du mit Android Auto verbunden bist und nur Android Auto-Benachrichtigungen verwendest.\nUm sicherzustellen, dass die App die Android Auto-Verbindung erkennt, musst du die Akkuoptimierung deaktivieren.\nWenn es immer noch nicht funktioniert, kannst du auch den Vordergrundmodus aktivieren oder die App einmal in Android Auto öffnen, wenn sie mit Android Auto verbunden ist. Android Auto einrichten - Um GlucoDataAuto in Android Auto zu verwenden, müssen die folgende Schritte durchgeführt werden: + Android Auto ist entweder eine separate App oder Bestandteil vom System und kann über die Android Einstellungen geöffnet werden.\nUm GlucoDataAuto in Android Auto zu verwenden, müssen die folgende Schritte durchgeführt werden: 1. Entwicklereinstellungen aktivieren - - Android Auto App öffnen\n- bis zu Version scrollen\n- mehrfach auf Version drücken bis ein Popup mit \"Entwicklereinstellungen zulassen\" kommt\n- \"OK\" drücken + - Android Auto öffnen\n- bis zu Version scrollen\n- mehrfach auf Version drücken bis ein Popup mit \"Entwicklereinstellungen zulassen\" kommt\n- \"OK\" drücken 2. \"Unbekannte Quellen\" aktivieren - - Android Auto App öffnen\n- in den 3-Punkt Menü \"Entwicklereinstellungen auswählen\"\n- bis zu \"Unbekannte Quellen\" scrollen und aktivieren + - Android Auto öffnen\n- in den 3-Punkt Menü \"Entwicklereinstellungen auswählen\"\n- bis zu \"Unbekannte Quellen\" scrollen und aktivieren 3. Benachrichtigungen aktivieren - - Android Auto App öffnen\n- bis zu \"Messaging\" scrollen\n- \"Benachrichtigungen für Nachrichten anzeigen\" aktivieren\n- \"Erste Zeile einer Nachricht anzeigen\" aktivieren + - Android Auto öffnen\n- bis zu \"Messaging\" scrollen\n- \"Benachrichtigungen für Nachrichten anzeigen\" aktivieren\n- \"Erste Zeile einer Nachricht anzeigen\" aktivieren + 4. GlucoDataAuto aktivieren + - Android Auto öffnen\n- bis zu \"Display\" scrollen\n- \"Launcher anpassen\" öffnen\n- \"GlucoDataAuto\" aktivieren\nIst GlucoDataAuto nicht verfügbar, bitte das Telefon neustarten. Farbiges Layout Zeigt die Werte in großer und farbiger Schrift.\nAuf einigen Samsung Geräte ab Android 13 kann dies zu einem Absturz der App führen, aufgrund eines Bugs auf Seite von Samsung.\nWenn das Problem auftritt, wird diese Einstellung automatisch deaktiviert, damit die App wieder lauffähig ist. Absturz erkannt! diff --git a/common/src/main/res/values-es/strings.xml b/common/src/main/res/values-es/strings.xml index 389b3b8e..071b75d3 100644 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -488,15 +488,17 @@ La optimización de batería está habilitada!\nPulsa aquí para desactivarlo. Si estás usando una fuente de seguidor, la aplicación puede no iniciarse mientras estés conectado a Android Auto, si solo usas notificaciones de Android Auto.\nPara asegurarte de que la aplicación detecte la conexión de Android Auto, tienes que desactivar la optimización de batería.\nSi aún no funciona, también puedes habilitar el modo de primer plano o tienes que abrir la aplicación en Android Auto una vez, cuando esté conectado a Android Auto. Configurar Android Auto - Para activar GlucoDataAuto para Android Auto, debes seguir los siguientes pasos: + Android Auto es una aplicación independiente o parte del sistema y se puede acceder a ella a través de la configuración de Android.\nPara activar GlucoDataAuto para Android Auto, debes seguir los siguientes pasos: 1. Activar el modo de desarrollador - - Abre la aplicación Android Auto\n- Desplázate hacia abajo hasta la Versión\n- Toca varias veces en la Versión hasta que aparezca una ventana emergente que diga \"Permitir ajustes de desarollo\"\n- Presiona \"Aceptar\" + - Abre Android Auto\n- Desplázate hacia abajo hasta la Versión\n- Toca varias veces en la Versión hasta que aparezca una ventana emergente que diga \"Permitir ajustes de desarollo\"\n- Presiona \"Aceptar\" 2. Activar \"Fuentes desconocidas\" - - Abre la aplicación Android Auto\n- Abre en el menú de 3 puntos las \"Ajustes de desarrollador\"\n- Desplázate hacia abajo hasta \"Fuentes desconocidas\"\n- Actívalo + - Abre Android Auto\n- Abre en el menú de 3 puntos las \"Ajustes de desarrollador\"\n- Desplázate hacia abajo hasta \"Fuentes desconocidas\"\n- Actívalo 3. Configurar las configuraciones de notificaciones - - Abre la aplicación Android Auto\n- Desplázate hacia abajo hasta \"Mensajes\"\n- Activa \"Mostrar notificaciones de mensajes\"\n- Activa \"Mostrar la primera línea de los mensajes\" + - Abre Android Auto\n- Desplázate hacia abajo hasta \"Mensajes\"\n- Activa \"Mostrar notificaciones de mensajes\"\n- Activa \"Mostrar la primera línea de los mensajes\" Diseño colorido Muestra los valores en texto grande y colorido.\nEn algunos dispositivos Samsung con Android 13 y superior, esto puede hacer que la aplicación se bloquee debido a un error del lado de Samsung.\nSi ocurre el problema, esta configuración se desactivará automáticamente para garantizar que la aplicación siga siendo funcional. ¡Error detectado! ¡Lo siento mucho que la aplicación se haya bloqueado durante la ejecución!\nPor favor, envíame los registros para que pueda analizar el error e intentar solucionarlo lo antes posible.\n¡Gracias! + 4. Habilitar GlucoDataAuto + - Abre Android Auto\n- Desplázate hacia abajo hasta \"Pantalla\"\n- Abre \"Personalizar menú de apps\"\n- Habilita \"GlucoDataAuto\"\nSi GlucoDataAuto no está disponible, por favor reinicia el teléfono. \ No newline at end of file diff --git a/common/src/main/res/values-pl/strings.xml b/common/src/main/res/values-pl/strings.xml index 3c9b109a..8811d0e9 100644 --- a/common/src/main/res/values-pl/strings.xml +++ b/common/src/main/res/values-pl/strings.xml @@ -481,15 +481,17 @@ Optymalizacja baterii jest włączona!\nNaciśnij tutaj, aby ją wyłączyć. Jeżeli jako źródła używasz funkcji „follower” (obserwatora), aplikacja może nie zostać uruchomiona podczas połączenia z Android Auto, gdy używa się wyłącznie powiadomień z Android Auto.\nAby upewnić się, że aplikacja wykrywa połączenie z Android Auto, należy wyłączyć optymalizację baterii.\nJeśli to nadal nie działa, można również włączyć tryb pierwszoplanowy lub otworzyć aplikację w Android Auto raz, gdy jest podłączona do Android Auto. Konfiguracja Android Auto - Aby aktywować GlucoDataAuto dla Android Auto, należy wykonać następujące kroki: + Android Auto jest albo osobną aplikacją, albo częścią systemu i można do niej uzyskać dostęp poprzez ustawienia Androida.\nAby aktywować GlucoDataAuto dla Android Auto, należy wykonać następujące kroki: 1. Aktywacja trybu programisty - - otwórz aplikację Android Auto\n- przewiń w dół do pozycji Wersja\n- dotknij kilkakrotnie pozycji Wersja, aż pojawi się wyskakujące okienko „Zezwalaj na ustawienia programisty\"\n- naciśnij \"OK\" + - otwórz Android Auto\n- przewiń w dół do pozycji Wersja\n- dotknij kilkakrotnie pozycji Wersja, aż pojawi się wyskakujące okienko „Zezwalaj na ustawienia programisty\"\n- naciśnij \"OK\" 2. Aktywuj „Nieznane źródła\" - - otwórz aplikację Android Auto\n- otwórz w menu (3 kropki) „Ustawienia programisty\"\n- przewiń w dół do pozycji „Nieznane źródła\"\n- włącz ją + - otwórz Android Auto\n- otwórz w menu (3 kropki) „Ustawienia programisty\"\n- przewiń w dół do pozycji „Nieznane źródła\"\n- włącz ją 3. Ustawienia powiadomień - - otwórz aplikację Android Auto\n- przewiń w dół do pozycji „Powiadomienia\"\n- włącz „Pokaż podgląd wiadomości przychodzących\"\n- włącz „Pokazuj pierwszy wiersz wiadomości\" + - otwórz Android Auto\n- przewiń w dół do pozycji „Powiadomienia\"\n- włącz „Pokaż podgląd wiadomości przychodzących\"\n- włącz „Pokazuj pierwszy wiersz wiadomości\" Kolorowy układ Wyświetla wartości dużą i kolorową czcionką.\nNa niektórych urządzeniach Samsung z Androidem 13 i nowszym, może to spowodować awarię aplikacji z powodu błędu po stronie Samsunga.\nJeśli problem wystąpi, to ustawienie zostanie automatycznie wyłączone, aby aplikacja mogła działać poprawnie. Wykryto awarię! Bardzo mi przykro, że aplikacja zawiesiła się podczas działania!\nProszę, wyślij mi logi, abym mógł przeanalizować błąd i spróbować go jak najszybciej naprawić.\nDziękuję! + 4. Włącz GlucoDataAuto + - otwórz Android Auto\n- przewiń w dół do pozycji \"Wyświetlanie\"\n- otwórz \"Dostosuj aplikacje w menu\"\n- włącz \"GlucoDataAuto\"\nJeśli GlucoDataAuto nie jest dostępny, proszę zrestartować telefon. diff --git a/common/src/main/res/values-pt/strings.xml b/common/src/main/res/values-pt/strings.xml index ae555e41..4069eb24 100644 --- a/common/src/main/res/values-pt/strings.xml +++ b/common/src/main/res/values-pt/strings.xml @@ -483,15 +483,17 @@ Otimização da bateria está habilitada!\nPressione aqui para desativá-lo. Se você estiver usando uma fonte seguidora, o aplicativo pode não ser iniciado enquanto estiver conectado ao Android Auto, se você estiver usando apenas notificações do Android Auto.\nPara garantir que o aplicativo detecte a conexão com o Android Auto, você deve desativar a otimização da bateria.\nSe ainda não funcionar, você também pode habilitar o modo de primeiro plano ou abrir o aplicativo no Android Auto uma vez, quando estiver conectado ao Android Auto. Configurar Android Auto - Para ativar o GlucoDataAuto para Android Auto, você deve seguir os seguintes passos: + O Android Auto é um aplicativo separado ou parte do sistema e pode ser acessado através das configurações do Android.\nPara ativar o GlucoDataAuto para Android Auto, você deve seguir os seguintes passos: 1. Ativar o modo desenvolvedor - - Abra o aplicativo Android Auto\n- Role para baixo até a Versão\n- Toque várias vezes na Versão até aparecer um pop-up para \"Permitir definições de programação\"\n- Pressione \"OK\" + - Abra o Android Auto\n- Role para baixo até a Versão\n- Toque várias vezes na Versão até aparecer um pop-up para \"Permitir definições de programação\"\n- Pressione \"OK\" 2. Ativar \"Fontes desconhecidas\" - - Abra o aplicativo Android Auto\n- Abra no menu de 3 pontos as \"Definições do programador\"\n- Role para baixo até \"Fontes desconhecidas\"\n- Ative-o + - Abra o Android Auto\n- Abra no menu de 3 pontos as \"Definições do programador\"\n- Role para baixo até \"Fontes desconhecidas\"\n- Ative-o 3. Configurar as configurações de notificações - - Abra o aplicativo Android Auto\n- Role para baixo até \"Mensagens\"\n- Ative \"Mostrar notificações de mensagens\"\n- Ative \"Mostrar primeira linha das mensagens\" + - Abra o Android Auto\n- Role para baixo até \"Mensagens\"\n- Ative \"Mostrar notificações de mensagens\"\n- Ative \"Mostrar primeira linha das mensagens\" Layout colorido Exibe os valores em texto grande e colorido.\nEm alguns dispositivos Samsung com Android 13 e superior, isso pode fazer com que o aplicativo trave devido a um bug do lado da Samsung.\nSe o problema ocorrer, essa configuração será desativada automaticamente para garantir que o aplicativo permaneça funcional. Falha detectada! Sinto muito que o aplicativo tenha travado durante a execução!\nPor favor, envie-me os logs para que eu possa analisar o erro e tentar corrigi-lo o mais rápido possível.\nObrigado! + 4. Habilitar GlucoDataAuto + - Abra o Android Auto\n- Role para baixo até \"Ecrã\"\n- Abra \"Personalize o Launcher\"\n- Habilite \"GlucoDataAuto\"\nSe o GlucoDataAuto não estiver disponível, reinicie o telefone, por favor. diff --git a/common/src/main/res/values/strings.xml b/common/src/main/res/values/strings.xml index 874653ad..7c6f4fe2 100644 --- a/common/src/main/res/values/strings.xml +++ b/common/src/main/res/values/strings.xml @@ -498,13 +498,15 @@ Battery optimization is enabled!\nPress here to disable it. If you are using a follower source, the app may not be started while connected to Android Auto, if you are using Android Auto Notifications only.\nTo make sure the app detects Android Auto connection you have to disable battery optimization.\nIf it still does not work, you can also enable foreground mode or you have to open the app in Android Auto once, if it is connected to Android Auto. Setup Android Auto - To activate GlucoDataAuto for Android Auto, you have to do the following steps: + Android Auto is either a separate app or part of the system and can be accessed through the Android settings.\nTo activate GlucoDataAuto for Android Auto, you have to do the following steps: 1. Activate developer mode - - open Android Auto app\n- scroll down to the Version\n- tap several times on the Version until a popup appears to \"Allow development settings\"\n- press \"OK\" + - open Android Auto\n- scroll down to the Version\n- tap several times on the Version until a popup appears to \"Allow development settings\"\n- press \"OK\" 2. Activate \"Unknown sources\" - - open Android Auto app\n- open in the 3-dot menu the \"Developer settings\"\n- scroll down to \"Unknown source\"\n- enable it + - open Android Auto\n- open in the 3-dot menu the \"Developer settings\"\n- scroll down to \"Unknown source\"\n- enable it 3. Set notification settings - - open Android Auto app\n- scroll down to \"Messaging\"\n- enable \"Show message notifications\"\n- enable \"Show first line of messages\" + - open Android Auto\n- scroll down to \"Messaging\"\n- enable \"Show message notifications\"\n- enable \"Show first line of messages\" + 4. Enable GlucoDataAuto + - open Android Auto\n- scroll down to \"Display\"\n- open \"Customise launcher\"\n- enable \"GlucoDataAuto\"\nIf GlucoDataAuto is not available, please restart your phone. Colored layout Displays the values in large and colored text.\nOn some Samsung devices with Android 13 and higher, this may cause the app to crash due to a bug on Samsung\'s side.\nIf the problem occurs, this setting will be automatically disabled to ensure the app remains functional. Crash detected! From b5c7853a444b1c20c25cfe27c7d41330b587b300 Mon Sep 17 00:00:00 2001 From: pachi81 Date: Mon, 10 Jun 2024 20:12:59 +0200 Subject: [PATCH 26/26] GDA: v1.0 --- auto/build.gradle | 4 ++-- common/src/main/res/values-es/strings.xml | 4 ++-- common/src/main/res/values-pl/strings.xml | 4 ++-- common/src/main/res/values-pt/strings.xml | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/auto/build.gradle b/auto/build.gradle index c7da9e40..e5c6de95 100644 --- a/auto/build.gradle +++ b/auto/build.gradle @@ -13,8 +13,8 @@ android { applicationId "de.michelinside.glucodataauto" minSdk rootProject.minSdk targetSdk rootProject.targetSdk - versionCode 1025 - versionName "1.0-beta4" + versionCode 1026 + versionName "1.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" } diff --git a/common/src/main/res/values-es/strings.xml b/common/src/main/res/values-es/strings.xml index 071b75d3..678bdd81 100644 --- a/common/src/main/res/values-es/strings.xml +++ b/common/src/main/res/values-es/strings.xml @@ -495,10 +495,10 @@ - Abre Android Auto\n- Abre en el menú de 3 puntos las \"Ajustes de desarrollador\"\n- Desplázate hacia abajo hasta \"Fuentes desconocidas\"\n- Actívalo 3. Configurar las configuraciones de notificaciones - Abre Android Auto\n- Desplázate hacia abajo hasta \"Mensajes\"\n- Activa \"Mostrar notificaciones de mensajes\"\n- Activa \"Mostrar la primera línea de los mensajes\" + 4. Habilitar GlucoDataAuto + - Abre Android Auto\n- Desplázate hacia abajo hasta \"Pantalla\"\n- Abre \"Personalizar menú de apps\"\n- Habilita \"GlucoDataAuto\"\nSi GlucoDataAuto no está disponible, por favor reinicia el teléfono. Diseño colorido Muestra los valores en texto grande y colorido.\nEn algunos dispositivos Samsung con Android 13 y superior, esto puede hacer que la aplicación se bloquee debido a un error del lado de Samsung.\nSi ocurre el problema, esta configuración se desactivará automáticamente para garantizar que la aplicación siga siendo funcional. ¡Error detectado! ¡Lo siento mucho que la aplicación se haya bloqueado durante la ejecución!\nPor favor, envíame los registros para que pueda analizar el error e intentar solucionarlo lo antes posible.\n¡Gracias! - 4. Habilitar GlucoDataAuto - - Abre Android Auto\n- Desplázate hacia abajo hasta \"Pantalla\"\n- Abre \"Personalizar menú de apps\"\n- Habilita \"GlucoDataAuto\"\nSi GlucoDataAuto no está disponible, por favor reinicia el teléfono. \ No newline at end of file diff --git a/common/src/main/res/values-pl/strings.xml b/common/src/main/res/values-pl/strings.xml index 8811d0e9..93f7be91 100644 --- a/common/src/main/res/values-pl/strings.xml +++ b/common/src/main/res/values-pl/strings.xml @@ -488,10 +488,10 @@ - otwórz Android Auto\n- otwórz w menu (3 kropki) „Ustawienia programisty\"\n- przewiń w dół do pozycji „Nieznane źródła\"\n- włącz ją 3. Ustawienia powiadomień - otwórz Android Auto\n- przewiń w dół do pozycji „Powiadomienia\"\n- włącz „Pokaż podgląd wiadomości przychodzących\"\n- włącz „Pokazuj pierwszy wiersz wiadomości\" + 4. Włącz GlucoDataAuto + - otwórz Android Auto\n- przewiń w dół do pozycji \"Wyświetlanie\"\n- otwórz \"Dostosuj aplikacje w menu\"\n- włącz \"GlucoDataAuto\"\nJeśli GlucoDataAuto nie jest dostępny, proszę zrestartować telefon. Kolorowy układ Wyświetla wartości dużą i kolorową czcionką.\nNa niektórych urządzeniach Samsung z Androidem 13 i nowszym, może to spowodować awarię aplikacji z powodu błędu po stronie Samsunga.\nJeśli problem wystąpi, to ustawienie zostanie automatycznie wyłączone, aby aplikacja mogła działać poprawnie. Wykryto awarię! Bardzo mi przykro, że aplikacja zawiesiła się podczas działania!\nProszę, wyślij mi logi, abym mógł przeanalizować błąd i spróbować go jak najszybciej naprawić.\nDziękuję! - 4. Włącz GlucoDataAuto - - otwórz Android Auto\n- przewiń w dół do pozycji \"Wyświetlanie\"\n- otwórz \"Dostosuj aplikacje w menu\"\n- włącz \"GlucoDataAuto\"\nJeśli GlucoDataAuto nie jest dostępny, proszę zrestartować telefon. diff --git a/common/src/main/res/values-pt/strings.xml b/common/src/main/res/values-pt/strings.xml index 4069eb24..b062503b 100644 --- a/common/src/main/res/values-pt/strings.xml +++ b/common/src/main/res/values-pt/strings.xml @@ -490,10 +490,10 @@ - Abra o Android Auto\n- Abra no menu de 3 pontos as \"Definições do programador\"\n- Role para baixo até \"Fontes desconhecidas\"\n- Ative-o 3. Configurar as configurações de notificações - Abra o Android Auto\n- Role para baixo até \"Mensagens\"\n- Ative \"Mostrar notificações de mensagens\"\n- Ative \"Mostrar primeira linha das mensagens\" + 4. Habilitar GlucoDataAuto + - Abra o Android Auto\n- Role para baixo até \"Ecrã\"\n- Abra \"Personalize o Launcher\"\n- Habilite \"GlucoDataAuto\"\nSe o GlucoDataAuto não estiver disponível, reinicie o telefone, por favor. Layout colorido Exibe os valores em texto grande e colorido.\nEm alguns dispositivos Samsung com Android 13 e superior, isso pode fazer com que o aplicativo trave devido a um bug do lado da Samsung.\nSe o problema ocorrer, essa configuração será desativada automaticamente para garantir que o aplicativo permaneça funcional. Falha detectada! Sinto muito que o aplicativo tenha travado durante a execução!\nPor favor, envie-me os logs para que eu possa analisar o erro e tentar corrigi-lo o mais rápido possível.\nObrigado! - 4. Habilitar GlucoDataAuto - - Abra o Android Auto\n- Role para baixo até \"Ecrã\"\n- Abra \"Personalize o Launcher\"\n- Habilite \"GlucoDataAuto\"\nSe o GlucoDataAuto não estiver disponível, reinicie o telefone, por favor.