diff --git a/presentation/src/main/java/org/cryptomator/presentation/presenter/VaultListPresenter.kt b/presentation/src/main/java/org/cryptomator/presentation/presenter/VaultListPresenter.kt index 101e826b..4b19ef9d 100644 --- a/presentation/src/main/java/org/cryptomator/presentation/presenter/VaultListPresenter.kt +++ b/presentation/src/main/java/org/cryptomator/presentation/presenter/VaultListPresenter.kt @@ -1,5 +1,6 @@ package org.cryptomator.presentation.presenter +import android.Manifest import android.app.KeyguardManager import android.app.admin.DevicePolicyManager import android.content.ActivityNotFoundException @@ -56,6 +57,7 @@ import org.cryptomator.presentation.workflow.ActivityResult import org.cryptomator.presentation.workflow.AddExistingVaultWorkflow import org.cryptomator.presentation.workflow.AuthenticationExceptionHandler import org.cryptomator.presentation.workflow.CreateNewVaultWorkflow +import org.cryptomator.presentation.workflow.PermissionsResult import org.cryptomator.presentation.workflow.Workflow import org.cryptomator.util.SharedPreferencesHandler import javax.inject.Inject @@ -112,6 +114,10 @@ class VaultListPresenter @Inject constructor( // } checkLicense() + + if(sharedPreferencesHandler.usePhotoUpload()) { + checkLocalStoragePermissionRegardingAutoUpload() + } } private fun checkLicense() { @@ -185,6 +191,27 @@ class VaultListPresenter @Inject constructor( // } } + private fun checkLocalStoragePermissionRegardingAutoUpload() { + requestPermissions( + PermissionsResultCallbacks.onLocalStoragePermissionGrantedForAutoUpload(), // + R.string.permission_snackbar_auth_auto_upload, // + Manifest.permission.READ_EXTERNAL_STORAGE + ) + } + + @Callback + fun onLocalStoragePermissionGrantedForAutoUpload(result: PermissionsResult) { + if (!result.granted()) { + Timber.tag("VaultListPresenter").e("Local storage permission not granted, auto upload will not work") + } + } + + fun loadVaultList() { + view?.hideVaultCreationHint() + vaultList + assertUnlockingVaultIsLocked() + } + private fun assertUnlockingVaultIsLocked() { if (view?.isShowingDialog(EnterPasswordDialog::class) == true) { if (view?.currentDialog() != null) { @@ -196,12 +223,6 @@ class VaultListPresenter @Inject constructor( // } } - fun loadVaultList() { - view?.hideVaultCreationHint() - vaultList - assertUnlockingVaultIsLocked() - } - fun deleteVault(vaultModel: VaultModel) { deleteVaultUseCase // .withVault(vaultModel.toVault()) // diff --git a/presentation/src/main/java/org/cryptomator/presentation/service/AutoUploadNotification.kt b/presentation/src/main/java/org/cryptomator/presentation/service/AutoUploadNotification.kt index 232db6e1..d2f38f46 100644 --- a/presentation/src/main/java/org/cryptomator/presentation/service/AutoUploadNotification.kt +++ b/presentation/src/main/java/org/cryptomator/presentation/service/AutoUploadNotification.kt @@ -47,18 +47,15 @@ class AutoUploadNotification(private val context: Context, private val amountOfP } private fun cancelNowAction(): NotificationCompat.Action { + val intentAction = cancelAutoUploadIntent(context) + val cancelIntent = PendingIntent.getService(context, 0, intentAction, FLAG_CANCEL_CURRENT) return NotificationCompat.Action.Builder( // R.drawable.ic_lock, // getString(R.string.notification_cancel_auto_upload), // - cancelNowIntent() // + cancelIntent // ).build() } - private fun cancelNowIntent(): PendingIntent { - val intentAction = cancelAutoUploadIntent(context) - return PendingIntent.getService(context, 0, intentAction, FLAG_CANCEL_CURRENT) - } - private fun startTheActivity(): PendingIntent { val startTheActivity = Intent(context, VaultListActivity::class.java) startTheActivity.action = ACTION_MAIN @@ -67,8 +64,8 @@ class AutoUploadNotification(private val context: Context, private val amountOfP } fun update(progress: Int) { - builder.setContentIntent(startTheActivity()) builder // + .setContentIntent(startTheActivity()) .setContentText( // String.format( context.getString(R.string.notification_auto_upload_message), // @@ -105,27 +102,32 @@ class AutoUploadNotification(private val context: Context, private val amountOfP showErrorWithMessage(context.getString(R.string.notification_auto_upload_failed_due_to_vault_not_found)) } + fun showPermissionNotGrantedNotification() { + Timber.tag("AutoUploadNotification").i("Show storage permission required notification") + showErrorWithMessage(context.getString(R.string.notification_auto_upload_permission_not_granted)) + } + private fun showErrorWithMessage(message: String) { - builder.setContentIntent(startTheActivity()) - builder // + builder + .setContentIntent(startTheActivity()) .setContentTitle(context.getString(R.string.notification_auto_upload_failed_title)) .setContentText(message) // .setProgress(0, 0, false) .setAutoCancel(true) .setOngoing(false) - .mActions.clear() + .clearActions() show() } fun showUploadFinished(size: Int) { - builder.setContentIntent(startTheActivity()) - builder // + builder + .setContentIntent(startTheActivity()) .setContentTitle(context.getString(R.string.notification_auto_upload_finished_title)) - .setContentText(format(context.getString(R.string.notification_auto_upload_finished_message), size)) // + .setContentText(format(context.getString(R.string.notification_auto_upload_finished_message), size)) .setProgress(0, 0, false) .setAutoCancel(true) .setOngoing(false) - .mActions.clear() + .clearActions() show() } diff --git a/presentation/src/main/java/org/cryptomator/presentation/service/AutoUploadService.java b/presentation/src/main/java/org/cryptomator/presentation/service/AutoUploadService.java index b4a56aec..b760436d 100644 --- a/presentation/src/main/java/org/cryptomator/presentation/service/AutoUploadService.java +++ b/presentation/src/main/java/org/cryptomator/presentation/service/AutoUploadService.java @@ -10,6 +10,8 @@ import android.net.Uri; import android.os.Handler; import android.os.IBinder; import android.os.Looper; +import android.system.ErrnoException; +import android.system.OsConstants; import androidx.annotation.Nullable; @@ -37,6 +39,7 @@ import org.cryptomator.presentation.util.FileUtil; import org.cryptomator.util.SharedPreferencesHandler; import java.io.File; +import java.io.FileNotFoundException; import java.io.IOException; import java.util.ArrayList; import java.util.Date; @@ -111,6 +114,8 @@ public class AutoUploadService extends Service { notification.showVaultLockedDuringUpload(); } else if (e instanceof CancellationException) { Timber.tag("AutoUploadService").i("Upload canceled by user"); + } else if (wrappedStoragePermissionException(e)) { + notification.showPermissionNotGrantedNotification(); } else { notification.showGeneralErrorDuringUpload(); } @@ -122,6 +127,14 @@ public class AutoUploadService extends Service { worker.start(); } + private boolean wrappedStoragePermissionException(Exception e) { + return e.getCause() != null // + && e.getCause() instanceof FileNotFoundException // + && e.getCause().getCause() != null // + && e.getCause().getCause() instanceof ErrnoException // + && ((ErrnoException) e.getCause().getCause()).errno == OsConstants.EACCES; + } + private void updateNotification(int asPercentage) { if (elapsedTimeAutoUploadNotificationDelay > 200 && !cancelled) { new Handler(Looper.getMainLooper()).post(() -> { @@ -170,8 +183,7 @@ public class AutoUploadService extends Service { } catch (FileRemovedDuringUploadException e) { Timber.tag("AutoUploadService").i("Not uploading file because it was removed during upload"); Timber.tag("AutoUploadService").v(format("Not uploading file because it was removed during upload %s", file.getFileName())); - } - catch (Exception e) { + } catch (Exception e) { cancelled = true; fileUtil.removeImagesFromAutoUploads(uploadedCloudFileNames); throw e; @@ -200,7 +212,7 @@ public class AutoUploadService extends Service { private CloudFile writeCloudFile(String fileName, CancelAwareDataSource dataSource, boolean replacing, ProgressAware progressAware) throws BackendException { Long size = dataSource.size(context); - if(size == null) { + if (size == null) { throw new FileRemovedDuringUploadException(); } CloudFile source = cloudContentRepository.file(parent, fileName, size); diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml index 8ed8a1de..243af0ee 100644 --- a/presentation/src/main/res/values/strings.xml +++ b/presentation/src/main/res/values/strings.xml @@ -538,6 +538,7 @@ Selected folder for upload isn\'t available anymore. Go to settings and choose a new one Vault locked during upload, please reopen vault to continue Vault specified for auto upload doesn\'t exist anymore. + @string/permission_snackbar_auth_auto_upload @string/dialog_button_cancel Open writable file