diff --git a/energy_settings/src/main/kotlin/de/cyface/energy_settings/EnergySettings.kt b/energy_settings/src/main/kotlin/de/cyface/energy_settings/CustomSettings.kt similarity index 60% rename from energy_settings/src/main/kotlin/de/cyface/energy_settings/EnergySettings.kt rename to energy_settings/src/main/kotlin/de/cyface/energy_settings/CustomSettings.kt index 0351f74..ccef4a7 100644 --- a/energy_settings/src/main/kotlin/de/cyface/energy_settings/EnergySettings.kt +++ b/energy_settings/src/main/kotlin/de/cyface/energy_settings/CustomSettings.kt @@ -18,9 +18,8 @@ */ package de.cyface.energy_settings -import android.content.Context -import androidx.core.content.edit -import de.cyface.energy_settings.Constants.PREFERENCES_MANUFACTURER_WARNING_SHOWN_KEY +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.map /** * Custom settings used by this library. @@ -33,20 +32,29 @@ import de.cyface.energy_settings.Constants.PREFERENCES_MANUFACTURER_WARNING_SHOW * * @author Armin Schnabel * @version 2.0.0 - * @since 3.4.0 + * @since 3.3.4 */ -class CustomPreferences(context: Context) { +class CustomSettings { - fun saveWarningShown(warningShown: Boolean) { - //FIXME - /*preferences.edit { - putBoolean(PREFERENCES_MANUFACTURER_WARNING_SHOWN_KEY, warningShown) - apply() - }*/ + /** + * Saves whether the user marked the manufacturer-specific warning as "don't show again". + * + * @param value The boolean value to save. + */ + @Suppress("unused") // Part of the API + suspend fun setManufacturerWarningShown(value: Boolean) { + TrackingSettings.dataStore.updateData { currentSettings -> + currentSettings.toBuilder() + .setManufacturerWarningShown(value) + .build() + } } - fun getWarningShown(): Boolean { - return true // FIXME - //return preferences.getBoolean(PREFERENCES_MANUFACTURER_WARNING_SHOWN_KEY, false) - } + /** + * @return Whether user marked the manufacturer-specific warning as "don't show again". + */ + val manufacturerWarningShownFlow: Flow = TrackingSettings.dataStore.data + .map { settings -> + settings.manufacturerWarningShown + } } \ No newline at end of file diff --git a/energy_settings/src/main/kotlin/de/cyface/energy_settings/ProblematicManufacturerWarningDialog.kt b/energy_settings/src/main/kotlin/de/cyface/energy_settings/ProblematicManufacturerWarningDialog.kt index e1301a6..e9a2827 100644 --- a/energy_settings/src/main/kotlin/de/cyface/energy_settings/ProblematicManufacturerWarningDialog.kt +++ b/energy_settings/src/main/kotlin/de/cyface/energy_settings/ProblematicManufacturerWarningDialog.kt @@ -32,6 +32,8 @@ import com.afollestad.materialdialogs.MaterialDialog import de.cyface.energy_settings.Constants.TAG import de.cyface.energy_settings.GnssDisabledWarningDialog.Companion.create import de.cyface.energy_settings.ProblematicManufacturerWarningDialog.Companion.create +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import java.util.Locale /** @@ -67,7 +69,9 @@ internal class ProblematicManufacturerWarningDialog(private val recipientEmail: // Allow the user to express its preference to disable auto-popup of this dialog builder.setNegativeButton(negativeButtonRes) { _, _ -> - onNegativeButtonCall(context) + GlobalScope.launch { // FIXME + onNegativeButtonCall(context) + } } // Show Sony STAMINA specific dialog (no manufacturer specific intent name known yet) @@ -166,8 +170,8 @@ internal class ProblematicManufacturerWarningDialog(private val recipientEmail: /** * Saves the user's preference to disable auto-popup of this dialog */ - private fun onNegativeButtonCall(context: Context?) { - CustomPreferences(context!!).saveWarningShown(true) + private suspend fun onNegativeButtonCall(context: Context?) { + CustomSettings().setManufacturerWarningShown(true) } /** @@ -183,7 +187,9 @@ internal class ProblematicManufacturerWarningDialog(private val recipientEmail: // Allow the user to express its preference to disable auto-popup of this dialog dialog.negativeButton(negativeButtonRes) { - onNegativeButtonCall(activity.applicationContext) + GlobalScope.launch { // FIXME + onNegativeButtonCall(activity.applicationContext) + } } // Show Sony STAMINA specific dialog (no manufacturer specific intent name known yet) diff --git a/energy_settings/src/main/kotlin/de/cyface/energy_settings/SettingsSerializer.kt b/energy_settings/src/main/kotlin/de/cyface/energy_settings/SettingsSerializer.kt index 8346a07..5c4d87b 100644 --- a/energy_settings/src/main/kotlin/de/cyface/energy_settings/SettingsSerializer.kt +++ b/energy_settings/src/main/kotlin/de/cyface/energy_settings/SettingsSerializer.kt @@ -1,20 +1,20 @@ /* * Copyright 2023 Cyface GmbH * - * This file is part of the Cyface App for Android. + * This file is part of the Cyface Energy Settings for Android. * - * The Cyface App for Android is free software: you can redistribute it and/or modify + * The Cyface Energy Settings for Android is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * - * The Cyface App for Android is distributed in the hope that it will be useful, + * The Cyface Energy Settings for Android is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License - * along with the Cyface App for Android. If not, see . + * along with the Cyface Energy Settings for Android. If not, see . */ package de.cyface.energy_settings @@ -25,12 +25,12 @@ import java.io.InputStream import java.io.OutputStream /** - * The serializer for the Proto DataStore of the preferences stored in the [Settings] file. + * The serializer for the Proto DataStore of the settings stored in the [Settings] file. * * For details: https://developer.android.com/topic/libraries/architecture/datastore#proto-datastore * * @author Armin Schnabel - * @since 3.7.0 + * @since 3.4.0 * @version 1.0.0 */ object SettingsSerializer : Serializer { diff --git a/energy_settings/src/main/kotlin/de/cyface/energy_settings/TrackingSettings.kt b/energy_settings/src/main/kotlin/de/cyface/energy_settings/TrackingSettings.kt index e19b892..f29d4f7 100644 --- a/energy_settings/src/main/kotlin/de/cyface/energy_settings/TrackingSettings.kt +++ b/energy_settings/src/main/kotlin/de/cyface/energy_settings/TrackingSettings.kt @@ -28,9 +28,14 @@ import android.os.Build import android.os.PowerManager import android.util.Log import androidx.annotation.RequiresApi +import androidx.datastore.core.DataStore +import androidx.datastore.core.DataStoreFactory +import androidx.datastore.dataStoreFile import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import de.cyface.utils.Validate +import kotlinx.coroutines.flow.first +import kotlinx.coroutines.runBlocking import java.util.Locale /** @@ -38,12 +43,33 @@ import java.util.Locale * * Offers checks and dialogs for energy settings required for background tracking. * + * Attention: You need to call [initialize] before you use this object, e.g. in Activity.onCreate. + * * @author Armin Schnabel * @version 2.0.3 * @since 1.0.0 */ object TrackingSettings { + /** + * Custom settings used by this library. + */ + private val settings: CustomSettings = CustomSettings() + + /** + * The data store with single-process support. + */ + lateinit var dataStore: DataStore + + @JvmStatic + fun initialize(context: Context) { + val dataStoreFile = context.dataStoreFile("energy_settings.pb") + dataStore = DataStoreFactory.create( + serializer = SettingsSerializer, + produceFile = { dataStoreFile } + ) + } + /** * Checks whether the energy safer mode is active *at this moment*. * @@ -311,9 +337,12 @@ object TrackingSettings { force: Boolean, recipientEmail: String ): Boolean { - - val preferences = CustomPreferences(context) - if (isProblematicManufacturer && (force || !preferences.getWarningShown())) { + // FIXME: consider async-preloading data at least, see: + // https://developer.android.com/topic/libraries/architecture/datastore#synchronous + val warningShown = runBlocking { // FIXME + settings.manufacturerWarningShownFlow.first() // FIXME + } + if (isProblematicManufacturer && (force || !warningShown)) { val fragmentManager = fragment.fragmentManager Validate.notNull(fragmentManager) val dialog = ProblematicManufacturerWarningDialog(recipientEmail) @@ -351,8 +380,11 @@ object TrackingSettings { return false } - val preferences = CustomPreferences(activity.applicationContext) - if (isProblematicManufacturer && (force || !preferences.getWarningShown())) { + val warningShown = runBlocking { // FIXME + settings.manufacturerWarningShownFlow.first() // FIXME + } + + if (isProblematicManufacturer && (force || !warningShown)) { ProblematicManufacturerWarningDialog.create(activity, recipientEmail).show() return true } diff --git a/energy_settings/src/main/proto/energy_settings.proto b/energy_settings/src/main/proto/energy_settings.proto new file mode 100644 index 0000000..c8ba478 --- /dev/null +++ b/energy_settings/src/main/proto/energy_settings.proto @@ -0,0 +1,38 @@ +/* + * Copyright 2023 Cyface GmbH + * + * This file is part of the Cyface Energy Settings for Android. + * + * The Cyface Energy Settings for Android is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * The Cyface Energy Settings for Android is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with the Cyface Energy Settings for Android. If not, see . + */ +syntax = "proto3"; + +option java_package = "de.cyface.energy_settings"; +option java_multiple_files = true; + +/** + * The data types for the values stored in the `EnergySettings`. + * + * See https://protobuf.dev/programming-guides/proto3/ + * + * Attention: The classes are generated from the file at compile time. Don't forget to rebuild. + * + * @author: Armin Schnabel + * @since: 3.4.0 + * @version: 1.0.0 + */ +message Settings { + // Whether the user marked the manufacturer-specific warning as "don't show again". + bool manufacturer_warning_shown = 1; +} \ No newline at end of file diff --git a/energy_settings/src/main/proto/settings.proto b/energy_settings/src/main/proto/settings.proto deleted file mode 100644 index faeeb61..0000000 --- a/energy_settings/src/main/proto/settings.proto +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2023 Cyface GmbH - * - * This file is part of the Cyface Utils for Android. - * - * The Cyface Utils for Android is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * The Cyface Utils for Android is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with the Cyface Utils for Android. If not, see . - */ -syntax = "proto3"; - -option java_package = "de.cyface.utils"; -option java_multiple_files = true; - -/** - * The data types for the values stored in the `AppPreferences`. - * - * See https://protobuf.dev/programming-guides/proto3/ - * - * Attention: The classes are generated from the file at compile time. Don't forget to rebuild. - * - * @author: Armin Schnabel - * @since: 4.0.0 - * @version: 1.0.0 - */ -message Settings { - // Whether the map should be automatically centered while moving - bool center_map = 1; - - // Whether the app should be able to upload measurementsA. - bool upload_enabled = 2; - - // The maximum frequency with which the IMU sensors should collect data, e.g. 100 Hz. - int32 sensor_frequency = 3; - - // Whether the app should report to the error monitoring service. - bool report_errors = 4; - - // The currently selected modality, e.g. 'CAR'. - string modality = 5; - - // The API version of the terms accepted by the user, e.g. 5. - int32 accepted_terms = 6; -} \ No newline at end of file