diff --git a/presentation/src/main/java/org/cryptomator/presentation/presenter/SettingsPresenter.kt b/presentation/src/main/java/org/cryptomator/presentation/presenter/SettingsPresenter.kt index 43cb4dc4..2a9602b9 100644 --- a/presentation/src/main/java/org/cryptomator/presentation/presenter/SettingsPresenter.kt +++ b/presentation/src/main/java/org/cryptomator/presentation/presenter/SettingsPresenter.kt @@ -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(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 // diff --git a/presentation/src/main/java/org/cryptomator/presentation/ui/activity/SettingsActivity.kt b/presentation/src/main/java/org/cryptomator/presentation/ui/activity/SettingsActivity.kt index b69f4c1e..301bf881 100644 --- a/presentation/src/main/java/org/cryptomator/presentation/ui/activity/SettingsActivity.kt +++ b/presentation/src/main/java/org/cryptomator/presentation/ui/activity/SettingsActivity.kt @@ -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()) } diff --git a/presentation/src/main/java/org/cryptomator/presentation/ui/dialog/AskIgnoreBatteryOptimizationsDialog.kt b/presentation/src/main/java/org/cryptomator/presentation/ui/dialog/AskIgnoreBatteryOptimizationsDialog.kt new file mode 100644 index 00000000..f09034a1 --- /dev/null +++ b/presentation/src/main/java/org/cryptomator/presentation/ui/dialog/AskIgnoreBatteryOptimizationsDialog.kt @@ -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() { + + 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() + } + } +} diff --git a/presentation/src/main/res/layout/dialog_ask_ignore_battery_optimizations.xml b/presentation/src/main/res/layout/dialog_ask_ignore_battery_optimizations.xml new file mode 100644 index 00000000..366b9b3d --- /dev/null +++ b/presentation/src/main/res/layout/dialog_ask_ignore_battery_optimizations.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 680b5bce..4e7b2353 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -394,6 +394,12 @@ Details This could be a security risk. I know what I am doing. + Disable battery optimizations + 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/dialog_unable_to_share_positive_button + @string/dialog_button_cancel + Don\'t ask again? + The usage of HTTP is insecure. We recommend to use HTTPS instead. If you know the risks, you can continue with HTTP. Change to HTTPS Use HTTPS? diff --git a/util/src/main/java/org/cryptomator/util/SharedPreferencesHandler.kt b/util/src/main/java/org/cryptomator/util/SharedPreferencesHandler.kt index ac60155f..c7ce8ce5 100644 --- a/util/src/main/java/org/cryptomator/util/SharedPreferencesHandler.kt +++ b/util/src/main/java/org/cryptomator/util/SharedPreferencesHandler.kt @@ -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"