Respect battery optimization setting when auto-updating

* Don't enable auto-install for updates if battery optimization permission
  is not granted during onboarding.
* Drop showing warning in toolbar, show it instead if they want auto-install
* Don't check for the same during downloads. Failing is better instead.

Signed-off-by: Aayush Gupta <aayushgupta219@gmail.com>
This commit is contained in:
Aayush Gupta
2024-03-18 19:43:28 +05:30
parent c72b860b4d
commit d030a7ac2e
9 changed files with 67 additions and 49 deletions

View File

@@ -177,7 +177,9 @@ fun Context.accentColor(): Int {
} }
fun Context.isIgnoringBatteryOptimizations(): Boolean { fun Context.isIgnoringBatteryOptimizations(): Boolean {
if (!isMAndAbove()) return true return if (isMAndAbove()) {
return !(getSystemService(Context.POWER_SERVICE) as PowerManager) (getSystemService(Context.POWER_SERVICE) as PowerManager).isIgnoringBatteryOptimizations(packageName)
.isIgnoringBatteryOptimizations(packageName) } else {
true
}
} }

View File

@@ -20,13 +20,11 @@
package com.aurora.store package com.aurora.store
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Environment import android.os.Environment
import android.os.PowerManager
import android.provider.Settings import android.provider.Settings
import android.view.Menu import android.view.Menu
import android.view.MenuItem import android.view.MenuItem
@@ -51,7 +49,6 @@ import coil.transform.RoundedCornersTransformation
import com.aurora.Constants import com.aurora.Constants
import com.aurora.extensions.accentColor import com.aurora.extensions.accentColor
import com.aurora.extensions.applyThemeAccent import com.aurora.extensions.applyThemeAccent
import com.aurora.extensions.isMAndAbove
import com.aurora.store.data.model.NetworkStatus import com.aurora.store.data.model.NetworkStatus
import com.aurora.store.data.providers.NetworkProvider import com.aurora.store.data.providers.NetworkProvider
import com.aurora.store.databinding.ActivityMainBinding import com.aurora.store.databinding.ActivityMainBinding
@@ -171,12 +168,6 @@ class MainActivity : AppCompatActivity() {
override fun onCreateOptionsMenu(menu: Menu): Boolean { override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.menu_main, menu) menuInflater.inflate(R.menu.menu_main, menu)
// Show warning if battery optimizations is enabled
val powerManager = getSystemService(Context.POWER_SERVICE) as PowerManager
if (isMAndAbove() && !powerManager.isIgnoringBatteryOptimizations(packageName)) {
menu.findItem(R.id.menu_doze_info)?.isVisible = true
}
return true return true
} }
@@ -186,11 +177,6 @@ class MainActivity : AppCompatActivity() {
navController.navigate(R.id.downloadFragment) navController.navigate(R.id.downloadFragment)
return true return true
} }
R.id.menu_doze_info -> {
navController.navigate(R.id.dozeWarningSheet)
return true
}
} }
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
} }

View File

@@ -15,6 +15,7 @@ import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.aurora.Constants import com.aurora.Constants
import com.aurora.extensions.isIgnoringBatteryOptimizations
import com.aurora.extensions.isMAndAbove import com.aurora.extensions.isMAndAbove
import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.App
import com.aurora.gplayapi.data.models.AuthData import com.aurora.gplayapi.data.models.AuthData
@@ -32,6 +33,7 @@ import com.aurora.store.util.PackageUtil
import com.aurora.store.util.Preferences import com.aurora.store.util.Preferences
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.save
import com.google.gson.Gson import com.google.gson.Gson
import dagger.assisted.Assisted import dagger.assisted.Assisted
import dagger.assisted.AssistedInject import dagger.assisted.AssistedInject
@@ -150,6 +152,7 @@ class UpdateWorker @AssistedInject constructor(
override suspend fun doWork(): Result { override suspend fun doWork(): Result {
val autoUpdatesMode = Preferences.getInteger(appContext, PREFERENCE_UPDATES_AUTO, 3) val autoUpdatesMode = Preferences.getInteger(appContext, PREFERENCE_UPDATES_AUTO, 3)
val notifyManager = appContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Exit if auto-updates is turned off in settings // Exit if auto-updates is turned off in settings
if (autoUpdatesMode == 0) { if (autoUpdatesMode == 0) {
@@ -214,16 +217,23 @@ class UpdateWorker @AssistedInject constructor(
if (updatesList.isNotEmpty()) { if (updatesList.isNotEmpty()) {
if (autoUpdatesMode == 1) { if (autoUpdatesMode == 1) {
Log.i(TAG,"Found updates, notifying!") Log.i(TAG,"Found updates, notifying!")
val notifyManager =
appContext.getSystemService(Context.NOTIFICATION_SERVICE)
as NotificationManager
notifyManager.notify( notifyManager.notify(
notificationID, notificationID,
NotificationUtil.getUpdateNotification(appContext, updatesList) NotificationUtil.getUpdateNotification(appContext, updatesList)
) )
} else { } else {
Log.i(TAG,"Found updates, updating!") if (appContext.isIgnoringBatteryOptimizations()) {
updatesList.forEach { downloadWorkerUtil.enqueueApp(it) } Log.i(TAG,"Found updates, updating!")
updatesList.forEach { downloadWorkerUtil.enqueueApp(it) }
} else {
// Fallback to notification if battery optimizations are enabled
Log.i(TAG,"Found updates, but battery optimizations are enabled!")
notifyManager.notify(
notificationID,
NotificationUtil.getUpdateNotification(appContext, updatesList)
)
appContext.save(PREFERENCE_UPDATES_AUTO, 1)
}
} }
return@withContext Result.success() return@withContext Result.success()
} }

View File

@@ -7,7 +7,6 @@ import androidx.work.ExistingWorkPolicy
import androidx.work.OneTimeWorkRequestBuilder import androidx.work.OneTimeWorkRequestBuilder
import androidx.work.OutOfQuotaPolicy import androidx.work.OutOfQuotaPolicy
import androidx.work.WorkManager import androidx.work.WorkManager
import com.aurora.extensions.isIgnoringBatteryOptimizations
import com.aurora.gplayapi.data.models.App import com.aurora.gplayapi.data.models.App
import com.aurora.store.data.model.DownloadStatus import com.aurora.store.data.model.DownloadStatus
import com.aurora.store.data.room.download.Download import com.aurora.store.data.room.download.Download
@@ -18,7 +17,6 @@ import dagger.hilt.android.qualifiers.ApplicationContext
import javax.inject.Inject import javax.inject.Inject
import kotlinx.coroutines.DelicateCoroutinesApi import kotlinx.coroutines.DelicateCoroutinesApi
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.cancel
import kotlinx.coroutines.flow.SharingStarted import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.collectLatest import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.flow.filter import kotlinx.coroutines.flow.filter
@@ -64,16 +62,11 @@ class DownloadWorkerUtil @Inject constructor(
val enqueuedDownloads = list.filter { it.downloadStatus == DownloadStatus.QUEUED } val enqueuedDownloads = list.filter { it.downloadStatus == DownloadStatus.QUEUED }
enqueuedDownloads.firstOrNull()?.let { enqueuedDownloads.firstOrNull()?.let {
try { try {
if (context.isIgnoringBatteryOptimizations() || CommonUtil.inForeground()) { Log.i(DOWNLOAD_WORKER, "Downloading ${it.packageName}")
Log.i(DOWNLOAD_WORKER, "Downloading ${it.packageName}") trigger(it)
trigger(it)
} else {
Log.i(TAG, "Not in foreground or ignoring battery optimization")
cancel()
}
} catch (exception: Exception) { } catch (exception: Exception) {
Log.i(DOWNLOAD_WORKER, "Failed to download app", exception) Log.i(DOWNLOAD_WORKER, "Failed to download app", exception)
downloadDao.delete(it.packageName) downloadDao.updateStatus(it.packageName, DownloadStatus.FAILED)
} }
} }
} }

View File

@@ -27,6 +27,7 @@ import androidx.lifecycle.Lifecycle
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.viewpager2.adapter.FragmentStateAdapter import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback import androidx.viewpager2.widget.ViewPager2.OnPageChangeCallback
import com.aurora.extensions.isIgnoringBatteryOptimizations
import com.aurora.store.R import com.aurora.store.R
import com.aurora.store.data.work.UpdateWorker import com.aurora.store.data.work.UpdateWorker
import com.aurora.store.databinding.FragmentOnboardingBinding import com.aurora.store.databinding.FragmentOnboardingBinding
@@ -127,8 +128,8 @@ class OnboardingFragment : Fragment(R.layout.fragment_onboarding) {
binding.btnForward.text = getString(R.string.action_finish) binding.btnForward.text = getString(R.string.action_finish)
binding.btnForward.isEnabled = true binding.btnForward.isEnabled = true
binding.btnForward.setOnClickListener { binding.btnForward.setOnClickListener {
setupAutoUpdates()
save(PREFERENCE_INTRO, true) save(PREFERENCE_INTRO, true)
UpdateWorker.scheduleAutomatedCheck(requireContext())
findNavController().navigate( findNavController().navigate(
OnboardingFragmentDirections.actionOnboardingFragmentToSplashFragment() OnboardingFragmentDirections.actionOnboardingFragmentToSplashFragment()
) )
@@ -165,7 +166,11 @@ class OnboardingFragment : Fragment(R.layout.fragment_onboarding) {
/*Updates*/ /*Updates*/
save(PREFERENCE_UPDATES_EXTENDED, false) save(PREFERENCE_UPDATES_EXTENDED, false)
save(PREFERENCE_UPDATES_AUTO, 2)
save(PREFERENCE_UPDATES_CHECK_INTERVAL, 3) save(PREFERENCE_UPDATES_CHECK_INTERVAL, 3)
} }
private fun setupAutoUpdates() {
save(PREFERENCE_UPDATES_AUTO, if (requireContext().isIgnoringBatteryOptimizations()) 2 else 1)
UpdateWorker.scheduleAutomatedCheck(requireContext())
}
} }

View File

@@ -25,6 +25,8 @@ import androidx.appcompat.widget.Toolbar
import androidx.navigation.fragment.findNavController import androidx.navigation.fragment.findNavController
import androidx.preference.ListPreference import androidx.preference.ListPreference
import androidx.preference.SeekBarPreference import androidx.preference.SeekBarPreference
import com.aurora.extensions.isIgnoringBatteryOptimizations
import com.aurora.store.MobileNavigationDirections
import com.aurora.store.R import com.aurora.store.R
import com.aurora.store.data.work.UpdateWorker import com.aurora.store.data.work.UpdateWorker
import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_AUTO import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_AUTO
@@ -39,11 +41,22 @@ class UpdatesPreference : BasePreferenceFragment() {
findPreference<ListPreference>(PREFERENCE_UPDATES_AUTO) findPreference<ListPreference>(PREFERENCE_UPDATES_AUTO)
?.setOnPreferenceChangeListener { _, newValue -> ?.setOnPreferenceChangeListener { _, newValue ->
when (newValue.toString().toInt()) { val value = newValue.toString().toInt()
when (value) {
0 -> UpdateWorker.cancelAutomatedCheck(requireContext()) 0 -> UpdateWorker.cancelAutomatedCheck(requireContext())
else -> UpdateWorker.scheduleAutomatedCheck(requireContext()) 1 -> UpdateWorker.scheduleAutomatedCheck(requireContext())
else -> {
if (requireContext().isIgnoringBatteryOptimizations()) {
UpdateWorker.scheduleAutomatedCheck(requireContext())
return@setOnPreferenceChangeListener true
} else {
findNavController().navigate(
MobileNavigationDirections.actionGlobalDozeWarningSheet(true)
)
}
}
} }
true value != 2
} }
findPreference<SeekBarPreference>(PREFERENCE_UPDATES_CHECK_INTERVAL) findPreference<SeekBarPreference>(PREFERENCE_UPDATES_CHECK_INTERVAL)

View File

@@ -1,27 +1,35 @@
package com.aurora.store.view.ui.sheets package com.aurora.store.view.ui.sheets
import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.os.Bundle import android.os.Bundle
import android.os.PowerManager
import android.provider.Settings import android.provider.Settings
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.navigation.fragment.navArgs
import com.aurora.extensions.isIgnoringBatteryOptimizations
import com.aurora.extensions.isMAndAbove import com.aurora.extensions.isMAndAbove
import com.aurora.extensions.toast import com.aurora.extensions.toast
import com.aurora.store.R import com.aurora.store.R
import com.aurora.store.data.work.UpdateWorker
import com.aurora.store.databinding.SheetDozeWarningBinding import com.aurora.store.databinding.SheetDozeWarningBinding
import com.aurora.store.util.Preferences.PREFERENCE_UPDATES_AUTO
import com.aurora.store.util.save
class DozeWarningSheet : BaseBottomSheet() { class DozeWarningSheet : BaseBottomSheet() {
private val args: DozeWarningSheetArgs by navArgs()
private val startForDozeResult = private val startForDozeResult =
registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { registerForActivityResult(ActivityResultContracts.StartActivityForResult()) {
context?.let { context?.let {
val powerManager = it.getSystemService(Context.POWER_SERVICE) as PowerManager if (it.isIgnoringBatteryOptimizations()) {
if (isMAndAbove() && powerManager.isIgnoringBatteryOptimizations(it.packageName)) { if (args.enableAutoUpdate) {
requireContext().save(PREFERENCE_UPDATES_AUTO, 2)
UpdateWorker.scheduleAutomatedCheck(requireContext())
}
toast(R.string.toast_permission_granted) toast(R.string.toast_permission_granted)
activity?.recreate() activity?.recreate()
} else { } else {

View File

@@ -25,11 +25,4 @@
android:icon="@drawable/ic_download_manager" android:icon="@drawable/ic_download_manager"
android:title="@string/title_download_manager" android:title="@string/title_download_manager"
app:showAsAction="always" /> app:showAsAction="always" />
<item
android:id="@+id/menu_doze_info"
android:icon="@drawable/ic_menu_about"
android:title="@string/device_doze_title"
android:visible="false"
app:showAsAction="always" />
</menu> </menu>

View File

@@ -47,6 +47,9 @@
<action <action
android:id="@+id/action_global_appMenuSheet" android:id="@+id/action_global_appMenuSheet"
app:destination="@id/appMenuSheet" /> app:destination="@id/appMenuSheet" />
<action
android:id="@+id/action_global_dozeWarningSheet"
app:destination="@id/dozeWarningSheet" />
<fragment <fragment
android:id="@+id/appsContainerFragment" android:id="@+id/appsContainerFragment"
android:name="com.aurora.store.view.ui.apps.AppsContainerFragment" android:name="com.aurora.store.view.ui.apps.AppsContainerFragment"
@@ -468,5 +471,10 @@
android:id="@+id/dozeWarningSheet" android:id="@+id/dozeWarningSheet"
android:name="com.aurora.store.view.ui.sheets.DozeWarningSheet" android:name="com.aurora.store.view.ui.sheets.DozeWarningSheet"
android:label="DozeWarningSheet" android:label="DozeWarningSheet"
tools:layout="@layout/sheet_doze_warning"/> tools:layout="@layout/sheet_doze_warning">
<argument
android:name="enableAutoUpdate"
app:argType="boolean"
android:defaultValue="false" />
</dialog>
</navigation> </navigation>