From 3ff84814153171601ff7a950c86b354c46524926 Mon Sep 17 00:00:00 2001 From: VaiTon Date: Sun, 6 Nov 2022 16:40:02 +0100 Subject: [PATCH] feat: use system PowerManager API to query for low battery status (#4874) Closes https://github.com/openfoodfacts/openfoodfacts-androidapp/issues/4610 --- .../features/compare/ProductCompareAdapter.kt | 4 +- .../environment/EnvironmentProductFragment.kt | 6 +-- .../ingredients/IngredientsProductFragment.kt | 4 +- .../nutrition/NutritionProductFragment.kt | 6 +-- .../view/summary/SummaryProductFragment.kt | 6 +-- .../productlist/ProductListAdapter.kt | 37 ++++++++-------- .../scanhistory/ScanHistoryActivity.kt | 6 +-- .../features/search/ProductSearchActivity.kt | 6 +-- .../github/scrachx/openfood/utils/Context.kt | 42 +++++++++---------- 9 files changed, 56 insertions(+), 61 deletions(-) diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/compare/ProductCompareAdapter.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/compare/ProductCompareAdapter.kt index 77ac5fcfa103..f2f8a850fb80 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/compare/ProductCompareAdapter.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/compare/ProductCompareAdapter.kt @@ -52,7 +52,7 @@ import openfoodfacts.github.scrachx.openfood.utils.getEcoscoreResource import openfoodfacts.github.scrachx.openfood.utils.getNovaGroupResource import openfoodfacts.github.scrachx.openfood.utils.getNutriScoreResource import openfoodfacts.github.scrachx.openfood.utils.isHardwareCameraInstalled -import openfoodfacts.github.scrachx.openfood.utils.isLowBatteryMode +import openfoodfacts.github.scrachx.openfood.utils.shouldLoadImages import openfoodfacts.github.scrachx.openfood.utils.toPx import pl.aprilapps.easyphotopicker.EasyImage import java.io.File @@ -152,7 +152,7 @@ class ProductCompareAdapter( } if (!imageUrl.isNullOrBlank()) { holder.binding.productComparisonLabel.visibility = View.INVISIBLE - if (!activity.isLowBatteryMode()) { + if (activity.shouldLoadImages()) { picasso.load(imageUrl).into(holder.binding.productComparisonImage) } else { holder.binding.productComparisonImage.visibility = View.GONE diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/environment/EnvironmentProductFragment.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/environment/EnvironmentProductFragment.kt index 88bd4c708068..9f74a2351f13 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/environment/EnvironmentProductFragment.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/environment/EnvironmentProductFragment.kt @@ -35,8 +35,8 @@ import openfoodfacts.github.scrachx.openfood.repositories.ProductRepository import openfoodfacts.github.scrachx.openfood.utils.LocaleManager import openfoodfacts.github.scrachx.openfood.utils.PhotoReceiverHandler import openfoodfacts.github.scrachx.openfood.utils.getRoundNumber -import openfoodfacts.github.scrachx.openfood.utils.isBatteryLevelLow -import openfoodfacts.github.scrachx.openfood.utils.isDisableImageLoad +import openfoodfacts.github.scrachx.openfood.utils.isPowerSaveMode +import openfoodfacts.github.scrachx.openfood.utils.isImageLoadingDisabled import openfoodfacts.github.scrachx.openfood.utils.isUserSet import openfoodfacts.github.scrachx.openfood.utils.requireProductState import java.io.File @@ -90,7 +90,7 @@ class EnvironmentProductFragment : BaseFragment() { binding.imageViewPackaging.setOnClickListener { openFullScreenImage() } // If Battery Level is low and the user has checked the Disable Image in Preferences , then set isLowBatteryMode to true - if (requireContext().isDisableImageLoad() && requireContext().isBatteryLevelLow()) { + if (requireContext().isImageLoadingDisabled() && requireContext().isPowerSaveMode()) { isLowBatteryMode = true } diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/ingredients/IngredientsProductFragment.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/ingredients/IngredientsProductFragment.kt index 9bf5938aee0f..4f1c18ee6f4f 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/ingredients/IngredientsProductFragment.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/ingredients/IngredientsProductFragment.kt @@ -78,7 +78,7 @@ import openfoodfacts.github.scrachx.openfood.utils.SearchType import openfoodfacts.github.scrachx.openfood.utils.getNovaGroupExplanation import openfoodfacts.github.scrachx.openfood.utils.getNovaGroupResource import openfoodfacts.github.scrachx.openfood.utils.getSendProduct -import openfoodfacts.github.scrachx.openfood.utils.isBatteryLevelLow +import openfoodfacts.github.scrachx.openfood.utils.isPowerSaveMode import openfoodfacts.github.scrachx.openfood.utils.isUserSet import openfoodfacts.github.scrachx.openfood.utils.requireProductState import openfoodfacts.github.scrachx.openfood.utils.showBottomSheet @@ -270,7 +270,7 @@ class IngredientsProductFragment : BaseFragment() { binding.changeIngImg.visibility = View.VISIBLE // Load Image if isLowBatteryMode is false - if (!requireContext().isBatteryLevelLow()) { + if (!requireContext().isPowerSaveMode()) { picasso.load(product.getImageIngredientsUrl(langCode)).into(binding.imageViewIngredients) } else { binding.imageViewIngredients.visibility = View.GONE diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/nutrition/NutritionProductFragment.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/nutrition/NutritionProductFragment.kt index 2e3c4a5f55eb..d7ea1d3e14b4 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/nutrition/NutritionProductFragment.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/nutrition/NutritionProductFragment.kt @@ -101,8 +101,8 @@ import openfoodfacts.github.scrachx.openfood.utils.getRoundNumber import openfoodfacts.github.scrachx.openfood.utils.getServingInL import openfoodfacts.github.scrachx.openfood.utils.getServingInOz import openfoodfacts.github.scrachx.openfood.utils.hideKeyboard -import openfoodfacts.github.scrachx.openfood.utils.isBatteryLevelLow -import openfoodfacts.github.scrachx.openfood.utils.isDisableImageLoad +import openfoodfacts.github.scrachx.openfood.utils.isPowerSaveMode +import openfoodfacts.github.scrachx.openfood.utils.isImageLoadingDisabled import openfoodfacts.github.scrachx.openfood.utils.isPerServingInLiter import openfoodfacts.github.scrachx.openfood.utils.isUserSet import openfoodfacts.github.scrachx.openfood.utils.requireProductState @@ -143,7 +143,7 @@ class NutritionProductFragment : BaseFragment(), CustomTabActivityHelper.Connect * Boolean to determine if image should be loaded or not */ private val isLowBatteryMode by lazy { - requireContext().isDisableImageLoad() && requireContext().isBatteryLevelLow() + requireContext().isImageLoadingDisabled() && requireContext().isPowerSaveMode() } private var nutrientsImageUrl: String? = null diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/summary/SummaryProductFragment.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/summary/SummaryProductFragment.kt index 101730a711f0..5f6a3bd6291f 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/summary/SummaryProductFragment.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/product/view/summary/SummaryProductFragment.kt @@ -112,8 +112,8 @@ import openfoodfacts.github.scrachx.openfood.utils.getEcoscoreResource import openfoodfacts.github.scrachx.openfood.utils.getNovaGroupResource import openfoodfacts.github.scrachx.openfood.utils.getNutriScoreResource import openfoodfacts.github.scrachx.openfood.utils.getProductBrandsQuantityDetails -import openfoodfacts.github.scrachx.openfood.utils.isBatteryLevelLow -import openfoodfacts.github.scrachx.openfood.utils.isDisableImageLoad +import openfoodfacts.github.scrachx.openfood.utils.isPowerSaveMode +import openfoodfacts.github.scrachx.openfood.utils.isImageLoadingDisabled import openfoodfacts.github.scrachx.openfood.utils.isHardwareCameraInstalled import openfoodfacts.github.scrachx.openfood.utils.isPerServingInLiter import openfoodfacts.github.scrachx.openfood.utils.isUserSet @@ -173,7 +173,7 @@ class SummaryProductFragment : BaseFragment(), ISummaryProductPresenter.View { private var annotation: AnnotationAnswer? = null //boolean to determine if image should be loaded or not - private val isLowBatteryMode by lazy { requireContext().isDisableImageLoad() && requireContext().isBatteryLevelLow() } + private val isLowBatteryMode by lazy { requireContext().isImageLoadingDisabled() && requireContext().isPowerSaveMode() } private var mUrlImage: String? = null private var nutritionScoreUri: Uri? = null diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/productlist/ProductListAdapter.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/productlist/ProductListAdapter.kt index 750a63641e5c..d56ff0b99aa4 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/productlist/ProductListAdapter.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/productlist/ProductListAdapter.kt @@ -6,23 +6,22 @@ import android.view.View import android.view.ViewGroup import androidx.core.content.res.ResourcesCompat import androidx.recyclerview.widget.RecyclerView -import com.squareup.picasso.Callback import com.squareup.picasso.Picasso import openfoodfacts.github.scrachx.openfood.R import openfoodfacts.github.scrachx.openfood.databinding.YourListedProductsItemBinding -import openfoodfacts.github.scrachx.openfood.features.productlist.ProductListAdapter.ProductViewHolder import openfoodfacts.github.scrachx.openfood.models.entities.ListedProduct -import openfoodfacts.github.scrachx.openfood.utils.isLowBatteryMode +import openfoodfacts.github.scrachx.openfood.utils.into +import openfoodfacts.github.scrachx.openfood.utils.shouldLoadImages class ProductListAdapter( private val context: Context, - private val picasso: Picasso -) : RecyclerView.Adapter() { + private val picasso: Picasso, +) : RecyclerView.Adapter() { var products = mutableListOf() var onItemClickListener: (ListedProduct) -> Unit = { } - private val isLowBatteryMode by lazy { context.isLowBatteryMode() } + private val shouldLoadImages by lazy { context.shouldLoadImages() } override fun getItemCount() = products.size @@ -42,29 +41,27 @@ class ProductListAdapter( binding.imageProgressbarYourListedProduct.visibility = View.VISIBLE - if (isLowBatteryMode || product.imageUrl.isNullOrEmpty()) { - binding.imgProductYourListedProduct.background = ResourcesCompat.getDrawable( - context.resources, - R.drawable.placeholder_thumb, - context.theme - ) - binding.imageProgressbarYourListedProduct.visibility = View.INVISIBLE - } else { + if (shouldLoadImages && !product.imageUrl.isNullOrEmpty()) { picasso .load(product.imageUrl) .placeholder(R.drawable.placeholder_thumb) .error(R.drawable.ic_no_red_24dp) .fit() .centerCrop() - .into(binding.imgProductYourListedProduct, object : Callback { - override fun onSuccess() { + .into(binding.imgProductYourListedProduct, + onSuccess = { binding.imageProgressbarYourListedProduct.visibility = View.GONE - } - - override fun onError(ex: Exception) { + }, onError = { binding.imageProgressbarYourListedProduct.visibility = View.GONE } - }) + ) + } else { + binding.imgProductYourListedProduct.background = ResourcesCompat.getDrawable( + context.resources, + R.drawable.placeholder_thumb, + context.theme + ) + binding.imageProgressbarYourListedProduct.visibility = View.INVISIBLE } // Set on click listener diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/scanhistory/ScanHistoryActivity.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/scanhistory/ScanHistoryActivity.kt index cf6ce8c0a101..6c291761b26b 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/scanhistory/ScanHistoryActivity.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/scanhistory/ScanHistoryActivity.kt @@ -45,8 +45,8 @@ import openfoodfacts.github.scrachx.openfood.utils.SortType.TIME import openfoodfacts.github.scrachx.openfood.utils.SortType.TITLE import openfoodfacts.github.scrachx.openfood.utils.SwipeController import openfoodfacts.github.scrachx.openfood.utils.getCsvFolderName -import openfoodfacts.github.scrachx.openfood.utils.isBatteryLevelLow -import openfoodfacts.github.scrachx.openfood.utils.isDisableImageLoad +import openfoodfacts.github.scrachx.openfood.utils.isPowerSaveMode +import openfoodfacts.github.scrachx.openfood.utils.isImageLoadingDisabled import openfoodfacts.github.scrachx.openfood.utils.isHardwareCameraInstalled import openfoodfacts.github.scrachx.openfood.utils.writeHistoryToFile import java.io.File @@ -75,7 +75,7 @@ class ScanHistoryActivity : BaseActivity() { private var menuButtonsEnabled = false private val adapter by lazy { - ScanHistoryAdapter(isLowBatteryMode = isDisableImageLoad() && isBatteryLevelLow(), picasso) { + ScanHistoryAdapter(isLowBatteryMode = isImageLoadingDisabled() && isPowerSaveMode(), picasso) { productViewActivityStarter.openProduct(it.barcode, this) } } diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/search/ProductSearchActivity.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/search/ProductSearchActivity.kt index f774d842cc72..b518929f1e0a 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/search/ProductSearchActivity.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/features/search/ProductSearchActivity.kt @@ -66,8 +66,8 @@ import openfoodfacts.github.scrachx.openfood.utils.SearchType.SEARCH import openfoodfacts.github.scrachx.openfood.utils.SearchType.STATE import openfoodfacts.github.scrachx.openfood.utils.SearchType.STORE import openfoodfacts.github.scrachx.openfood.utils.SearchType.TRACE -import openfoodfacts.github.scrachx.openfood.utils.isBatteryLevelLow -import openfoodfacts.github.scrachx.openfood.utils.isDisableImageLoad +import openfoodfacts.github.scrachx.openfood.utils.isPowerSaveMode +import openfoodfacts.github.scrachx.openfood.utils.isImageLoadingDisabled import openfoodfacts.github.scrachx.openfood.utils.isGranted import java.text.NumberFormat import java.util.* @@ -103,7 +103,7 @@ class ProductSearchActivity : BaseActivity() { private lateinit var adapter: ProductSearchAdapter private var contributionType = 0 - private val lowBatteryMode by lazy { isDisableImageLoad() && isBatteryLevelLow() } + private val lowBatteryMode by lazy { isImageLoadingDisabled() && isPowerSaveMode() } /** * boolean to determine if image should be loaded or not diff --git a/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/Context.kt b/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/Context.kt index f83d0dfa63cc..834875ee8462 100644 --- a/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/Context.kt +++ b/app/src/main/java/openfoodfacts/github/scrachx/openfood/utils/Context.kt @@ -1,45 +1,43 @@ package openfoodfacts.github.scrachx.openfood.utils import android.content.Context -import android.content.Intent -import android.content.IntentFilter import android.content.pm.PackageManager import android.net.ConnectivityManager import android.net.NetworkCapabilities -import android.os.BatteryManager import android.os.Build +import android.os.PowerManager import android.util.Log +import androidx.core.content.getSystemService import androidx.preference.PreferenceManager.getDefaultSharedPreferences +import openfoodfacts.github.scrachx.openfood.R import java.io.File import java.io.IOException -import kotlin.math.ceil + private const val LOG_TAG = "ContextExt" /** - * Function which returns true if the battery level is low - * - * @return true if battery is low or false if battery in not low + * @return true if the device supports the [PowerManager] API and is + * set to power save mode. False otherwise. */ -fun Context.isBatteryLevelLow(percent: Int = 15): Boolean { - val filter = IntentFilter(Intent.ACTION_BATTERY_CHANGED) - val batteryStatus = registerReceiver(null, filter) ?: throw IllegalStateException("cannot get battery level") - - val level = batteryStatus.getIntExtra(BatteryManager.EXTRA_LEVEL, -1) - val scale = batteryStatus.getIntExtra(BatteryManager.EXTRA_SCALE, -1) - - val batteryPct = level.toFloat() / scale * 100 - Log.i("BATTERYSTATUS", batteryPct.toString()) - return ceil(batteryPct) <= percent +fun Context.isPowerSaveMode(): Boolean { + val powerManager = getSystemService() ?: return false + return powerManager.isPowerSaveMode } -fun Context.isLowBatteryMode() = isDisableImageLoad() && isBatteryLevelLow() +fun Context.shouldLoadImages() = !isImageLoadingDisabled() && !isPowerSaveMode() -fun Context.isDisableImageLoad(defValue: Boolean = false) = getDefaultSharedPreferences(this) - .getBoolean("disableImageLoad", defValue) +fun Context.isImageLoadingDisabled(): Boolean { + val preferences = getDefaultSharedPreferences(this) + val key = getString(R.string.pref_low_battery_key) + return preferences.getBoolean(key, false) +} -fun Context.isFastAdditionMode(defValue: Boolean = false) = getDefaultSharedPreferences(this) - .getBoolean("fastAdditionMode", defValue) +fun Context.isFastAdditionMode(defValue: Boolean = false): Boolean { + val preferences = getDefaultSharedPreferences(this) + val key = getString(R.string.pref_fast_addition_key) + return preferences.getBoolean(key, defValue) +} fun Context.dpsToPixel(dps: Int) = dps.toPx(this)