Fix auto upload does not catch all images due to battery optimization

Fixes #416
This commit is contained in:
Julian Raufelder 2022-03-18 17:58:53 +01:00
parent d42e0a8ec9
commit 9324bb5b15
No known key found for this signature in database
GPG Key ID: 17EE71F6634E381D
6 changed files with 129 additions and 3 deletions

View File

@ -5,6 +5,8 @@ import android.content.Context
import android.content.Intent
import android.os.AsyncTask
import android.os.Build
import android.os.PowerManager
import android.provider.Settings
import android.widget.Toast
import com.google.common.base.Optional
import org.cryptomator.data.util.NetworkConnectionCheck
@ -20,8 +22,9 @@ import org.cryptomator.presentation.exception.ExceptionHandlers
import org.cryptomator.presentation.logging.Logfiles
import org.cryptomator.presentation.logging.ReleaseLogger
import org.cryptomator.presentation.model.ProgressModel
import org.cryptomator.presentation.service.PhotoContentJob.Companion.scheduleJob
import org.cryptomator.presentation.service.PhotoContentJob
import org.cryptomator.presentation.ui.activity.view.SettingsView
import org.cryptomator.presentation.ui.dialog.AskIgnoreBatteryOptimizationsDialog
import org.cryptomator.presentation.ui.dialog.UpdateAppAvailableDialog
import org.cryptomator.presentation.ui.dialog.UpdateAppDialog
import org.cryptomator.presentation.util.EmailBuilder
@ -47,6 +50,12 @@ class SettingsPresenter @Inject internal constructor(
private val sharedPreferencesHandler: SharedPreferencesHandler
) : Presenter<SettingsView>(exceptionMappings) {
fun checkAutoUploadEnabledAndBatteryOptimizationDisabled() {
if (sharedPreferencesHandler.usePhotoUpload()) {
showAskIgnoreBatteryOptimizationsDialogWhenDisabled()
}
}
fun onSendErrorReportClicked() {
view?.showProgress(ProgressModel.GENERIC)
// no usecase here because the backend is not involved
@ -97,12 +106,32 @@ class SettingsPresenter @Inject internal constructor(
@Callback
fun onLocalStoragePermissionGranted(result: PermissionsResult) {
if (result.granted()) {
scheduleJob(context())
PhotoContentJob.scheduleJob(context())
showAskIgnoreBatteryOptimizationsDialogWhenDisabled()
} else {
view?.disableAutoUpload()
}
}
private fun showAskIgnoreBatteryOptimizationsDialogWhenDisabled() {
val powerManager = context().getSystemService(Context.POWER_SERVICE) as PowerManager
if (!powerManager.isIgnoringBatteryOptimizations(context().packageName) && !sharedPreferencesHandler.askBatteryOptimizationsDialogDisabled()) {
view?.showDialog(AskIgnoreBatteryOptimizationsDialog.newInstance())
}
}
fun askIgnoreBatteryOptimizationsAccepted() {
val intent = Intent()
intent.action = Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS
startIntent(intent)
}
fun onAskIgnoreBatteryOptimizationsRejected(askAgain: Boolean) {
if (!askAgain) {
sharedPreferencesHandler.setAskBatteryOptimizationsDialogDisabled(true)
}
}
fun onCheckUpdateClicked() {
if (networkConnectionCheck.isPresent) {
updateCheckUseCase //

View File

@ -8,6 +8,7 @@ import org.cryptomator.presentation.R
import org.cryptomator.presentation.model.ProgressModel
import org.cryptomator.presentation.presenter.SettingsPresenter
import org.cryptomator.presentation.ui.activity.view.SettingsView
import org.cryptomator.presentation.ui.dialog.AskIgnoreBatteryOptimizationsDialog
import org.cryptomator.presentation.ui.dialog.DebugModeDisclaimerDialog
import org.cryptomator.presentation.ui.dialog.DisableAppWhenObscuredDisclaimerDialog
import org.cryptomator.presentation.ui.dialog.DisableSecureScreenDisclaimerDialog
@ -20,10 +21,11 @@ import kotlinx.android.synthetic.main.toolbar_layout.toolbar
@Activity(layout = R.layout.activity_settings)
class SettingsActivity : BaseActivity(),
SettingsView,
AskIgnoreBatteryOptimizationsDialog.Callback,
DebugModeDisclaimerDialog.Callback,
DisableAppWhenObscuredDisclaimerDialog.Callback,
DisableSecureScreenDisclaimerDialog.Callback,
UpdateAppAvailableDialog.Callback, //
UpdateAppAvailableDialog.Callback,
UpdateAppDialog.Callback {
@Inject
@ -31,6 +33,7 @@ class SettingsActivity : BaseActivity(),
override fun setupView() {
setupToolbar()
presenter.checkAutoUploadEnabledAndBatteryOptimizationDisabled()
}
private fun setupToolbar() {
@ -40,6 +43,14 @@ class SettingsActivity : BaseActivity(),
fun presenter(): SettingsPresenter = presenter
override fun onAskIgnoreBatteryOptimizationsAccepted() {
presenter.askIgnoreBatteryOptimizationsAccepted()
}
override fun onAskIgnoreBatteryOptimizationsRejected(askAgain: Boolean) {
presenter.onAskIgnoreBatteryOptimizationsRejected(askAgain);
}
override fun onDisclaimerAccepted() {
presenter.onDebugModeChanged(accepted())
}

View File

@ -0,0 +1,41 @@
package org.cryptomator.presentation.ui.dialog
import android.content.DialogInterface
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
import org.cryptomator.generator.Dialog
import org.cryptomator.presentation.R
import kotlinx.android.synthetic.main.dialog_ask_ignore_battery_optimizations.cb_ask_ignore_battery_optimizations
import kotlinx.android.synthetic.main.dialog_ask_ignore_battery_optimizations.tv_ask_ignore_battery_optimizations
@Dialog(R.layout.dialog_ask_ignore_battery_optimizations)
class AskIgnoreBatteryOptimizationsDialog : BaseDialog<AskIgnoreBatteryOptimizationsDialog.Callback>() {
interface Callback {
fun onAskIgnoreBatteryOptimizationsAccepted()
fun onAskIgnoreBatteryOptimizationsRejected(askAgain: Boolean)
}
public override fun setupDialog(builder: AlertDialog.Builder): android.app.Dialog {
return builder //
.setTitle(R.string.dialog_ask_ignore_battery_optimizations_title) //
.setPositiveButton(getString(R.string.dialog_ask_ignore_battery_optimizations_neutral_button)) { _: DialogInterface, _: Int -> callback?.onAskIgnoreBatteryOptimizationsAccepted() } //
.setNegativeButton(getString(R.string.dialog_ask_ignore_battery_optimizations_negative_button)) { _: DialogInterface, _: Int -> callback?.onAskIgnoreBatteryOptimizationsRejected(!cb_ask_ignore_battery_optimizations.isChecked) } //
.create()
}
public override fun setupView() {
tv_ask_ignore_battery_optimizations.text = String.format(
getString(R.string.dialog_ask_ignore_battery_optimizations_hint),
getString(R.string.app_name),
getString(R.string.dialog_ask_ignore_battery_optimizations_neutral_button))
}
companion object {
fun newInstance(): DialogFragment {
return AskIgnoreBatteryOptimizationsDialog()
}
}
}

View File

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="@dimen/activity_vertical_margin">
<TextView
android:id="@+id/tv_ask_ignore_battery_optimizations"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/dialog_ask_ignore_battery_optimizations_hint" />
<CheckBox
android:id="@+id/cb_ask_ignore_battery_optimizations"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/tv_ask_ignore_battery_optimizations"
android:layout_marginTop="27dp"
android:checked="false"
android:paddingStart="16dp"
android:paddingEnd="16dp"
android:text="@string/dialog_ask_ignore_battery_optimizations_checkbox" />
</RelativeLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -394,6 +394,12 @@
<string name="dialog_accept_ssl_certificate_details">Details</string>
<string name="dialog_accept_ssl_certificate_security_checkbox">This could be a security risk. I know what I am doing.</string>
<string name="dialog_ask_ignore_battery_optimizations_title">Disable battery optimizations</string>
<string name="dialog_ask_ignore_battery_optimizations_hint">To retrieve new pictures and videos without running in the background, we need to opt-out from battery optimizations. But don\'t worry, %1$s doesn\'t consumes much energy.\n\nTo apply it, change \'Not optimized\' to \'All apps\', select %1$s and choose \'Don\'t optimize\' after clicking \'%2$s\' in this dialog.</string>
<string name="dialog_ask_ignore_battery_optimizations_neutral_button" translatable="false">@string/dialog_unable_to_share_positive_button</string>
<string name="dialog_ask_ignore_battery_optimizations_negative_button" translatable="false">@string/dialog_button_cancel</string>
<string name="dialog_ask_ignore_battery_optimizations_checkbox">Don\'t ask again?</string>
<string name="dialog_http_security_hint">The usage of HTTP is insecure. We recommend to use HTTPS instead. If you know the risks, you can continue with HTTP.</string>
<string name="dialog_http_security_checkbox">Change to HTTPS</string>
<string name="dialog_http_security_title">Use HTTPS?</string>

View File

@ -261,9 +261,18 @@ constructor(context: Context) : SharedPreferences.OnSharedPreferenceChangeListen
}
}
fun askBatteryOptimizationsDialogDisabled(): Boolean {
return defaultSharedPreferences.getBoolean(ASK_IGNORE_BATTERY_OPTIMIZATIONS_DIALOG_DISABLED, false)
}
fun setAskBatteryOptimizationsDialogDisabled(disable: Boolean) {
defaultSharedPreferences.setValue(ASK_IGNORE_BATTERY_OPTIMIZATIONS_DIALOG_DISABLED, disable)
}
companion object {
private const val SCREEN_LOCK_DIALOG_SHOWN = "askForScreenLockDialogShown"
private const val ASK_IGNORE_BATTERY_OPTIMIZATIONS_DIALOG_DISABLED = "askIgnoreBatteryOptimizationsDialogDisabled"
private const val SCREEN_BETA_DIALOG_SHOWN = "askForBetaConfirmationDialogShown"
private const val USE_BIOMETRIC_AUTHENTICATION = "useFingerprint"
private const val USE_CONFIRMATION_IN_FACE_UNLOCK_AUTHENTICATION = "useConfirmationInFaceUnlockBiometricAuthentication"