diff --git a/app/src/androidTest/java/com/owncloud/android/FileIT.java b/app/src/androidTest/java/com/owncloud/android/FileIT.java
index 9f251d65c857..2ba362250cdf 100644
--- a/app/src/androidTest/java/com/owncloud/android/FileIT.java
+++ b/app/src/androidTest/java/com/owncloud/android/FileIT.java
@@ -106,7 +106,8 @@ public void testRenameFolder() throws IOException {
assertTrue(new SynchronizeFolderOperation(targetContext,
folderPath,
user,
- fileDataStorageManager)
+ fileDataStorageManager,
+ false)
.execute(targetContext)
.isSuccess());
diff --git a/app/src/gplay/AndroidManifest.xml b/app/src/gplay/AndroidManifest.xml
index 8d9ec96b73c8..9e2d78552bcf 100644
--- a/app/src/gplay/AndroidManifest.xml
+++ b/app/src/gplay/AndroidManifest.xml
@@ -13,6 +13,11 @@
android:name="android.permission.REQUEST_INSTALL_PACKAGES"
tools:node="remove"/>
+
+
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+package com.nextcloud.utils
+
+object BuildHelper {
+ const val GPLAY: String = "gplay"
+}
diff --git a/app/src/main/java/com/owncloud/android/MainApp.java b/app/src/main/java/com/owncloud/android/MainApp.java
index be156896b52c..8751bf429c2e 100644
--- a/app/src/main/java/com/owncloud/android/MainApp.java
+++ b/app/src/main/java/com/owncloud/android/MainApp.java
@@ -834,6 +834,8 @@ private static void updateToAutoUpload(Context context) {
}
}
+
+
private static void showAutoUploadAlertDialog(Context context) {
new MaterialAlertDialogBuilder(context, R.style.Theme_ownCloud_Dialog)
.setTitle(R.string.drawer_synced_folders)
diff --git a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java
index d811ef55b7e5..0b272a671c29 100644
--- a/app/src/main/java/com/owncloud/android/datamodel/OCFile.java
+++ b/app/src/main/java/com/owncloud/android/datamodel/OCFile.java
@@ -20,6 +20,7 @@
import android.os.Parcelable;
import android.text.TextUtils;
+import com.nextcloud.utils.BuildHelper;
import com.owncloud.android.BuildConfig;
import com.owncloud.android.R;
import com.owncloud.android.lib.common.network.WebdavEntry;
@@ -1084,7 +1085,7 @@ public void setInternalFolderSyncResult(String internalFolderSyncResult) {
}
public boolean isAPKorAAB() {
- if ("gplay".equals(BuildConfig.FLAVOR)) {
+ if (BuildHelper.GPLAY.equals(BuildConfig.FLAVOR)) {
return getFileName().endsWith(".apk") || getFileName().endsWith(".aab");
} else {
return false;
diff --git a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
index f569a74fb0b7..52f5ad739879 100644
--- a/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
+++ b/app/src/main/java/com/owncloud/android/ui/activity/FileDisplayActivity.java
@@ -13,6 +13,7 @@
*/
package com.owncloud.android.ui.activity;
+import android.Manifest;
import android.accounts.Account;
import android.accounts.AuthenticatorException;
import android.annotation.SuppressLint;
@@ -50,6 +51,7 @@
import com.nextcloud.client.account.User;
import com.nextcloud.client.appinfo.AppInfo;
import com.nextcloud.client.core.AsyncRunner;
+import com.nextcloud.client.core.Clock;
import com.nextcloud.client.di.Injectable;
import com.nextcloud.client.editimage.EditImageActivity;
import com.nextcloud.client.files.DeepLinkHandler;
@@ -64,17 +66,21 @@
import com.nextcloud.client.utils.IntentUtil;
import com.nextcloud.model.WorkerState;
import com.nextcloud.model.WorkerStateLiveData;
+import com.nextcloud.utils.BuildHelper;
import com.nextcloud.utils.extensions.ActivityExtensionsKt;
import com.nextcloud.utils.extensions.BundleExtensionsKt;
import com.nextcloud.utils.extensions.FileExtensionsKt;
import com.nextcloud.utils.extensions.IntentExtensionsKt;
import com.nextcloud.utils.fileNameValidator.FileNameValidator;
import com.nextcloud.utils.view.FastScrollUtils;
+import com.owncloud.android.BuildConfig;
import com.owncloud.android.MainApp;
import com.owncloud.android.R;
import com.owncloud.android.databinding.FilesBinding;
import com.owncloud.android.datamodel.FileDataStorageManager;
import com.owncloud.android.datamodel.OCFile;
+import com.owncloud.android.datamodel.SyncedFolder;
+import com.owncloud.android.datamodel.SyncedFolderProvider;
import com.owncloud.android.datamodel.VirtualFolderType;
import com.owncloud.android.files.services.NameCollisionPolicy;
import com.owncloud.android.lib.common.OwnCloudClient;
@@ -241,6 +247,8 @@ public class FileDisplayActivity extends FileActivity
@Inject FastScrollUtils fastScrollUtils;
@Inject AsyncRunner asyncRunner;
+ @Inject Clock clock;
+ @Inject SyncedFolderProvider syncedFolderProvider;
public static Intent openFileIntent(Context context, User user, OCFile file) {
final Intent intent = new Intent(context, PreviewImageActivity.class);
@@ -275,12 +283,55 @@ protected void onCreate(Bundle savedInstanceState) {
mPlayerConnection = new PlayerServiceConnection(this);
checkStoragePath();
+ checkAutoUploadOnGPlay();
initSyncBroadcastReceiver();
observeWorkerState();
registerRefreshFolderEventReceiver();
}
+ private void checkAutoUploadOnGPlay() {
+ if (!BuildHelper.GPLAY.equals(BuildConfig.FLAVOR)) {
+ return;
+ }
+
+ // only show on Android11+
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.R) {
+ return;
+ }
+
+ if (PermissionUtil.checkSelfPermission(this, Manifest.permission.MANAGE_EXTERNAL_STORAGE)) {
+ return;
+ }
+
+ if (preferences.isAutoUploadGPlayWarningShown()) {
+ return;
+ }
+
+ boolean showInfoDialog = false;
+ for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
+ // move or delete after success
+ if (syncedFolder.getUploadAction() == 1 || syncedFolder.getUploadAction() == 2) {
+ showInfoDialog = true;
+ break;
+ }
+ }
+
+ if (showInfoDialog) {
+ new MaterialAlertDialogBuilder(this, R.style.Theme_ownCloud_Dialog)
+ .setTitle(R.string.auto_upload_gplay)
+ .setMessage(R.string.auto_upload_gplay_desc)
+ .setNegativeButton(R.string.dialog_close, (dialog, which) -> {
+ dialog.dismiss();
+ })
+ .setIcon(R.drawable.nav_synced_folders)
+ .create()
+ .show();
+ }
+
+ preferences.setAutoUploadGPlayWarningShown(true);
+ }
+
@SuppressWarnings("unchecked")
private void loadSavedInstanceState(Bundle savedInstanceState) {
if (savedInstanceState != null) {
diff --git a/app/src/main/java/com/owncloud/android/ui/activity/UploadFilesActivity.java b/app/src/main/java/com/owncloud/android/ui/activity/UploadFilesActivity.java
index 01d93439542a..09f537f66f31 100644
--- a/app/src/main/java/com/owncloud/android/ui/activity/UploadFilesActivity.java
+++ b/app/src/main/java/com/owncloud/android/ui/activity/UploadFilesActivity.java
@@ -50,6 +50,7 @@
import com.owncloud.android.ui.fragment.LocalFileListFragment;
import com.owncloud.android.utils.DisplayUtils;
import com.owncloud.android.utils.FileSortOrder;
+import com.owncloud.android.utils.FileStorageUtils;
import com.owncloud.android.utils.PermissionUtil;
import java.io.File;
@@ -567,7 +568,8 @@ public void onDirectoryClick(File directory) {
}
private void checkWritableFolder(File folder) {
- boolean canWriteIntoFolder = folder.canWrite();
+ boolean canWriteIntoFolder = FileStorageUtils.isFolderWritable(folder);
+
binding.uploadFilesSpinnerBehaviour.setEnabled(canWriteIntoFolder);
TextView textView = findViewById(R.id.upload_files_upload_files_behaviour_text);
diff --git a/app/src/main/java/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.kt b/app/src/main/java/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.kt
index aba0d565d8f6..556dac4db784 100644
--- a/app/src/main/java/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.kt
+++ b/app/src/main/java/com/owncloud/android/ui/dialog/SyncedFolderPreferencesDialogFragment.kt
@@ -277,7 +277,9 @@ class SyncedFolderPreferencesDialogFragment : DialogFragment(), Injectable {
binding?.settingInstantBehaviourContainer?.alpha = ALPHA_DISABLED
return
}
- if (syncedFolder!!.localPath != null && File(syncedFolder!!.localPath).canWrite()) {
+ if (syncedFolder!!.localPath != null &&
+ FileStorageUtils.isFolderWritable(File(syncedFolder!!.localPath))
+ ) {
binding?.settingInstantBehaviourContainer?.isEnabled = true
binding?.settingInstantBehaviourContainer?.alpha = ALPHA_ENABLED
binding?.settingInstantBehaviourSummary?.text =
diff --git a/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java b/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java
index eaf81854b867..11f95da1d19d 100644
--- a/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java
+++ b/app/src/main/java/com/owncloud/android/utils/FileStorageUtils.java
@@ -680,6 +680,16 @@ public static boolean checkIfEnoughSpace(OCFile file) {
return checkIfEnoughSpace(availableSpaceOnDevice, file);
}
+
+ public static boolean isFolderWritable(File folder) {
+ File[] children = folder.listFiles();
+
+ if (children != null && children.length > 0) {
+ return children[0].canWrite();
+ } else {
+ return folder.canWrite();
+ }
+ }
@VisibleForTesting
public static boolean checkIfEnoughSpace(long availableSpaceOnDevice, OCFile file) {
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index f43b79d34765..e541d34a9c19 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -1253,4 +1253,6 @@
To set up a two way sync folder, please enable it in the details tab of the folder in question.
Internal two way sync
Disable for all folders
+ Auto upload behaviour changed
+ Due to new restrictions imposed by Google, the auto upload feature will no longer be able to automatically remove uploaded files.