UpdatesPreference: Allow to configure automated updates constraints

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2025-02-18 15:56:16 +08:00
parent 86d085fe55
commit 5c7289381f
9 changed files with 172 additions and 6 deletions

View File

@@ -20,6 +20,9 @@ import com.aurora.store.data.model.UpdateMode
import com.aurora.store.data.room.update.UpdateDao import com.aurora.store.data.room.update.UpdateDao
import com.aurora.store.data.work.UpdateWorker import com.aurora.store.data.work.UpdateWorker
import com.aurora.store.util.Preferences import com.aurora.store.util.Preferences
import com.aurora.store.util.Preferences.PREFERENCES_UPDATES_RESTRICTIONS_BATTERY
import com.aurora.store.util.Preferences.PREFERENCES_UPDATES_RESTRICTIONS_IDLE
import com.aurora.store.util.Preferences.PREFERENCES_UPDATES_RESTRICTIONS_METERED
import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_CHECK_INTERVAL import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_CHECK_INTERVAL
import dagger.hilt.android.qualifiers.ApplicationContext import dagger.hilt.android.qualifiers.ApplicationContext
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
@@ -160,10 +163,18 @@ class UpdateHelper @Inject constructor(
).toLong() ).toLong()
val constraints = Constraints.Builder() val constraints = Constraints.Builder()
.setRequiredNetworkType(NetworkType.UNMETERED)
.setRequiresBatteryNotLow(true)
if (isMAndAbove) constraints.setRequiresDeviceIdle(true) if (Preferences.getBoolean(context, PREFERENCES_UPDATES_RESTRICTIONS_METERED, true)) {
constraints.setRequiredNetworkType(NetworkType.UNMETERED)
}
if (Preferences.getBoolean(context, PREFERENCES_UPDATES_RESTRICTIONS_BATTERY, true)) {
constraints.setRequiresBatteryNotLow(true)
}
if (isMAndAbove && Preferences.getBoolean(context, PREFERENCES_UPDATES_RESTRICTIONS_IDLE, true)) {
constraints.setRequiresDeviceIdle(true)
}
return PeriodicWorkRequestBuilder<UpdateWorker>( return PeriodicWorkRequestBuilder<UpdateWorker>(
repeatInterval = updateCheckInterval, repeatInterval = updateCheckInterval,

View File

@@ -55,6 +55,10 @@ object Preferences {
const val PREFERENCE_UPDATES_EXTENDED = "PREFERENCE_UPDATES_EXTENDED" const val PREFERENCE_UPDATES_EXTENDED = "PREFERENCE_UPDATES_EXTENDED"
const val PREFERENCE_UPDATES_AUTO = "PREFERENCE_UPDATES_AUTO" const val PREFERENCE_UPDATES_AUTO = "PREFERENCE_UPDATES_AUTO"
const val PREFERENCE_UPDATES_CHECK_INTERVAL = "PREFERENCE_UPDATES_CHECK_INTERVAL" const val PREFERENCE_UPDATES_CHECK_INTERVAL = "PREFERENCE_UPDATES_CHECK_INTERVAL"
const val PREFERENCES_UPDATES_RESTRICTIONS = "PREFERENCES_UPDATES_RESTRICTIONS"
const val PREFERENCES_UPDATES_RESTRICTIONS_METERED = "PREFERENCES_UPDATES_RESTRICTIONS_METERED"
const val PREFERENCES_UPDATES_RESTRICTIONS_IDLE = "PREFERENCES_UPDATES_RESTRICTIONS_IDLE"
const val PREFERENCES_UPDATES_RESTRICTIONS_BATTERY = "PREFERENCES_UPDATES_RESTRICTIONS_BATTERY"
const val PREFERENCE_MIGRATION_VERSION = "PREFERENCE_MIGRATION_VERSION" const val PREFERENCE_MIGRATION_VERSION = "PREFERENCE_MIGRATION_VERSION"

View File

@@ -17,7 +17,7 @@
* *
*/ */
package com.aurora.store.view.ui.preferences package com.aurora.store.view.ui.preferences.updates
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
@@ -25,18 +25,21 @@ import androidx.appcompat.widget.Toolbar
import androidx.fragment.app.viewModels import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.Preference
import androidx.preference.SeekBarPreference import androidx.preference.SeekBarPreference
import androidx.preference.SwitchPreferenceCompat import androidx.preference.SwitchPreferenceCompat
import com.aurora.store.R import com.aurora.store.R
import com.aurora.store.data.model.PermissionType import com.aurora.store.data.model.PermissionType
import com.aurora.store.data.model.UpdateMode import com.aurora.store.data.model.UpdateMode
import com.aurora.store.util.Preferences import com.aurora.store.util.Preferences
import com.aurora.store.util.Preferences.PREFERENCES_UPDATES_RESTRICTIONS
import com.aurora.store.util.Preferences.PREFERENCE_FILTER_AURORA_ONLY import com.aurora.store.util.Preferences.PREFERENCE_FILTER_AURORA_ONLY
import com.aurora.store.util.Preferences.PREFERENCE_FILTER_FDROID import com.aurora.store.util.Preferences.PREFERENCE_FILTER_FDROID
import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_AUTO import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_AUTO
import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_CHECK_INTERVAL import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_CHECK_INTERVAL
import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_EXTENDED import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_EXTENDED
import com.aurora.store.util.save import com.aurora.store.util.save
import com.aurora.store.view.ui.preferences.BasePreferenceFragment
import com.aurora.store.viewmodel.all.UpdatesViewModel import com.aurora.store.viewmodel.all.UpdatesViewModel
import dagger.hilt.android.AndroidEntryPoint import dagger.hilt.android.AndroidEntryPoint
@@ -49,11 +52,13 @@ class UpdatesPreference : BasePreferenceFragment() {
setPreferencesFromResource(R.xml.preferences_updates, rootKey) setPreferencesFromResource(R.xml.preferences_updates, rootKey)
findPreference<ListPreference>(PREFERENCE_UPDATES_AUTO)?.setOnPreferenceChangeListener { _, newValue -> findPreference<ListPreference>(PREFERENCE_UPDATES_AUTO)?.setOnPreferenceChangeListener { _, newValue ->
val updateRestrictionsPref = findPreference<Preference>(PREFERENCES_UPDATES_RESTRICTIONS)
val updateCheckIntervalPref = val updateCheckIntervalPref =
findPreference<SeekBarPreference>(PREFERENCE_UPDATES_CHECK_INTERVAL) findPreference<SeekBarPreference>(PREFERENCE_UPDATES_CHECK_INTERVAL)
when (UpdateMode.entries[newValue.toString().toInt()]) { when (UpdateMode.entries[newValue.toString().toInt()]) {
UpdateMode.DISABLED -> { UpdateMode.DISABLED -> {
updateRestrictionsPref?.isEnabled = false
updateCheckIntervalPref?.isEnabled = false updateCheckIntervalPref?.isEnabled = false
viewModel.updateHelper.cancelAutomatedCheck() viewModel.updateHelper.cancelAutomatedCheck()
requireContext().save(PREFERENCE_UPDATES_AUTO, 0) requireContext().save(PREFERENCE_UPDATES_AUTO, 0)
@@ -62,12 +67,14 @@ class UpdatesPreference : BasePreferenceFragment() {
UpdateMode.CHECK_AND_NOTIFY -> { UpdateMode.CHECK_AND_NOTIFY -> {
if (permissionProvider.isGranted(PermissionType.POST_NOTIFICATIONS)) { if (permissionProvider.isGranted(PermissionType.POST_NOTIFICATIONS)) {
updateRestrictionsPref?.isEnabled = true
updateCheckIntervalPref?.isEnabled = true updateCheckIntervalPref?.isEnabled = true
viewModel.updateHelper.scheduleAutomatedCheck() viewModel.updateHelper.scheduleAutomatedCheck()
true true
} else { } else {
permissionProvider.request(PermissionType.POST_NOTIFICATIONS) { permissionProvider.request(PermissionType.POST_NOTIFICATIONS) {
if (it) { if (it) {
updateRestrictionsPref?.isEnabled = true
updateCheckIntervalPref?.isEnabled = true updateCheckIntervalPref?.isEnabled = true
requireContext().save(PREFERENCE_UPDATES_AUTO, 1) requireContext().save(PREFERENCE_UPDATES_AUTO, 1)
viewModel.updateHelper.scheduleAutomatedCheck() viewModel.updateHelper.scheduleAutomatedCheck()
@@ -80,12 +87,14 @@ class UpdatesPreference : BasePreferenceFragment() {
UpdateMode.CHECK_AND_INSTALL -> { UpdateMode.CHECK_AND_INSTALL -> {
if (permissionProvider.isGranted(PermissionType.DOZE_WHITELIST)) { if (permissionProvider.isGranted(PermissionType.DOZE_WHITELIST)) {
updateRestrictionsPref?.isEnabled = true
updateCheckIntervalPref?.isEnabled = true updateCheckIntervalPref?.isEnabled = true
viewModel.updateHelper.scheduleAutomatedCheck() viewModel.updateHelper.scheduleAutomatedCheck()
true true
} else { } else {
permissionProvider.request(PermissionType.DOZE_WHITELIST) { permissionProvider.request(PermissionType.DOZE_WHITELIST) {
if (it) { if (it) {
updateRestrictionsPref?.isEnabled = true
updateCheckIntervalPref?.isEnabled = true updateCheckIntervalPref?.isEnabled = true
requireContext().save(PREFERENCE_UPDATES_AUTO, 2) requireContext().save(PREFERENCE_UPDATES_AUTO, 2)
viewModel.updateHelper.scheduleAutomatedCheck() viewModel.updateHelper.scheduleAutomatedCheck()
@@ -100,6 +109,14 @@ class UpdatesPreference : BasePreferenceFragment() {
} }
} }
findPreference<Preference>(PREFERENCES_UPDATES_RESTRICTIONS)?.apply {
isEnabled = Preferences.getInteger(requireContext(), PREFERENCE_UPDATES_AUTO) != 0
setOnPreferenceClickListener {
findNavController().navigate(R.id.updatesRestrictionsDialog)
true
}
}
findPreference<SeekBarPreference>(PREFERENCE_UPDATES_CHECK_INTERVAL)?.apply { findPreference<SeekBarPreference>(PREFERENCE_UPDATES_CHECK_INTERVAL)?.apply {
isEnabled = Preferences.getInteger(requireContext(), PREFERENCE_UPDATES_AUTO) != 0 isEnabled = Preferences.getInteger(requireContext(), PREFERENCE_UPDATES_AUTO) != 0
setOnPreferenceChangeListener { _, _ -> setOnPreferenceChangeListener { _, _ ->

View File

@@ -0,0 +1,70 @@
/*
* SPDX-FileCopyrightText: 2025 The Calyx Institute
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.aurora.store.view.ui.preferences.updates
import android.app.Dialog
import android.content.Context
import android.os.Bundle
import androidx.fragment.app.DialogFragment
import androidx.fragment.app.viewModels
import com.aurora.store.R
import com.aurora.store.util.Preferences
import com.aurora.store.util.Preferences.PREFERENCES_UPDATES_RESTRICTIONS_BATTERY
import com.aurora.store.util.Preferences.PREFERENCES_UPDATES_RESTRICTIONS_IDLE
import com.aurora.store.util.Preferences.PREFERENCES_UPDATES_RESTRICTIONS_METERED
import com.aurora.store.viewmodel.preferences.UpdatesRestrictionsViewModel
import com.google.android.material.checkbox.MaterialCheckBox
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import dagger.hilt.android.AndroidEntryPoint
@AndroidEntryPoint
class UpdatesRestrictionsDialog : DialogFragment() {
private val viewModel: UpdatesRestrictionsViewModel by viewModels()
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val view = layoutInflater.inflate(R.layout.dialog_auto_updates_restrictions, null)
return MaterialAlertDialogBuilder(requireContext())
.setTitle(R.string.pref_updates_restrictions_title)
.setMessage(R.string.pref_updates_restrictions_desc)
.setView(view)
.setPositiveButton(getString(android.R.string.ok)) { _, _ -> dialog?.dismiss()}
.create()
}
override fun onResume() {
super.onResume()
context?.let { setupRestrictions(it) }
}
override fun onDestroy() {
viewModel.updateHelper.updateAutomatedCheck()
super.onDestroy()
}
private fun setupRestrictions(ctx: Context) {
dialog?.findViewById<MaterialCheckBox>(R.id.checkboxMetered)?.apply {
isChecked = Preferences.getBoolean(ctx, PREFERENCES_UPDATES_RESTRICTIONS_METERED, true)
setOnCheckedChangeListener { _, isChecked ->
Preferences.putBoolean(ctx, PREFERENCES_UPDATES_RESTRICTIONS_METERED, isChecked)
}
}
dialog?.findViewById<MaterialCheckBox>(R.id.checkboxIdle)?.apply {
isChecked = Preferences.getBoolean(ctx, PREFERENCES_UPDATES_RESTRICTIONS_IDLE, true)
setOnCheckedChangeListener { _, isChecked ->
Preferences.putBoolean(ctx, PREFERENCES_UPDATES_RESTRICTIONS_IDLE, isChecked)
}
}
dialog?.findViewById<MaterialCheckBox>(R.id.checkboxBattery)?.apply {
isChecked = Preferences.getBoolean(ctx, PREFERENCES_UPDATES_RESTRICTIONS_BATTERY, true)
setOnCheckedChangeListener { _, isChecked ->
Preferences.putBoolean(ctx, PREFERENCES_UPDATES_RESTRICTIONS_BATTERY, isChecked)
}
}
}
}

View File

@@ -0,0 +1,14 @@
/*
* SPDX-FileCopyrightText: 2025 The Calyx Institute
* SPDX-License-Identifier: GPL-3.0-or-later
*/
package com.aurora.store.viewmodel.preferences
import androidx.lifecycle.ViewModel
import com.aurora.store.data.helper.UpdateHelper
import dagger.hilt.android.lifecycle.HiltViewModel
import javax.inject.Inject
@HiltViewModel
class UpdatesRestrictionsViewModel @Inject constructor(val updateHelper: UpdateHelper) : ViewModel()

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ SPDX-FileCopyrightText: 2025 The Calyx Institute
~ SPDX-License-Identifier: GPL-3.0-or-later
-->
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingHorizontal="@dimen/padding_large">
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkboxMetered"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/pref_updates_restrictions_metered" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkboxBattery"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/pref_updates_restrictions_battery" />
<com.google.android.material.checkbox.MaterialCheckBox
android:id="@+id/checkboxIdle"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:checked="true"
android:text="@string/pref_updates_restrictions_idle" />
</LinearLayout>

View File

@@ -113,7 +113,7 @@
tools:layout="@layout/fragment_setting" /> tools:layout="@layout/fragment_setting" />
<fragment <fragment
android:id="@+id/updatesPreference" android:id="@+id/updatesPreference"
android:name="com.aurora.store.view.ui.preferences.UpdatesPreference" android:name="com.aurora.store.view.ui.preferences.updates.UpdatesPreference"
android:label="UpdatesPreference" android:label="UpdatesPreference"
tools:layout="@layout/fragment_setting" /> tools:layout="@layout/fragment_setting" />
<fragment <fragment
@@ -468,10 +468,14 @@
</dialog> </dialog>
<dialog <dialog
android:id="@+id/proxyURLDialog" android:id="@+id/proxyURLDialog"
android:name="com.aurora.store.view.ui.preferences.ProxyURLDialog" android:name="com.aurora.store.view.ui.preferences.network.ProxyURLDialog"
android:label="@string/pref_network_proxy_url" /> android:label="@string/pref_network_proxy_url" />
<dialog <dialog
android:id="@+id/forceRestartDialog" android:id="@+id/forceRestartDialog"
android:name="com.aurora.store.view.ui.commons.ForceRestartDialog" android:name="com.aurora.store.view.ui.commons.ForceRestartDialog"
android:label="@string/force_restart_title" /> android:label="@string/force_restart_title" />
<dialog
android:id="@+id/updatesRestrictionsDialog"
android:name="com.aurora.store.view.ui.preferences.updates.UpdatesRestrictionsDialog"
android:label="@string/pref_updates_restrictions_title" />
</navigation> </navigation>

View File

@@ -495,4 +495,11 @@
<string name="toast_proxy_disabled">Proxy disabled successfully</string> <string name="toast_proxy_disabled">Proxy disabled successfully</string>
<string name="pref_network_proxy_desc">View and manage proxy configuration</string> <string name="pref_network_proxy_desc">View and manage proxy configuration</string>
<string name="pref_network_proxy_url_hint" translatable="false">protocol://user:password@host:port</string> <string name="pref_network_proxy_url_hint" translatable="false">protocol://user:password@host:port</string>
<!-- UpdatesPreferences -->
<string name="pref_updates_restrictions_title">Automatic updates restrictions</string>
<string name="pref_updates_restrictions_desc">Configure device restrictions for automated updates.</string>
<string name="pref_updates_restrictions_metered">Only on unmetered networks</string>
<string name="pref_updates_restrictions_idle">When device is idle</string>
<string name="pref_updates_restrictions_battery">When battery is not low</string>
</resources> </resources>

View File

@@ -40,6 +40,13 @@
app:min="1" app:min="1"
app:showSeekBarValue="true" /> app:showSeekBarValue="true" />
<Preference
app:disableDependentsState="false"
app:iconSpaceReserved="false"
app:key="PREFERENCES_UPDATES_RESTRICTIONS"
app:summary="@string/pref_updates_restrictions_desc"
app:title="@string/pref_updates_restrictions_title" />
<PreferenceCategory <PreferenceCategory
app:iconSpaceReserved="false" app:iconSpaceReserved="false"
app:singleLineTitle="false" app:singleLineTitle="false"