diff --git a/src/main/java/com/nextcloud/client/di/ComponentsModule.java b/src/main/java/com/nextcloud/client/di/ComponentsModule.java index a8eadc3641..558ef0afa9 100644 --- a/src/main/java/com/nextcloud/client/di/ComponentsModule.java +++ b/src/main/java/com/nextcloud/client/di/ComponentsModule.java @@ -32,6 +32,7 @@ import com.owncloud.android.files.services.FileDownloader; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.jobs.NotificationJob; import com.owncloud.android.providers.DiskLruImageCacheFileProvider; +import com.owncloud.android.providers.FileContentProvider; import com.owncloud.android.providers.UsersAndGroupsSearchProvider; import com.owncloud.android.services.AccountManagerService; import com.owncloud.android.services.OperationsService; @@ -148,6 +149,7 @@ abstract class ComponentsModule { @ContributesAndroidInjector abstract BootupBroadcastReceiver bootupBroadcastReceiver(); @ContributesAndroidInjector abstract NotificationJob.NotificationReceiver notificationJobBroadcastReceiver(); + @ContributesAndroidInjector abstract FileContentProvider fileContentProvider(); @ContributesAndroidInjector abstract UsersAndGroupsSearchProvider usersAndGroupsSearchProvider(); @ContributesAndroidInjector abstract DiskLruImageCacheFileProvider diskLruImageCacheFileProvider(); diff --git a/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt b/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt index 3ddd997114..38a6a57c81 100644 --- a/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt +++ b/src/main/java/com/nextcloud/client/jobs/BackgroundJobFactory.kt @@ -26,6 +26,7 @@ import androidx.annotation.RequiresApi import androidx.work.ListenableWorker import androidx.work.WorkerFactory import androidx.work.WorkerParameters +import com.nextcloud.client.core.Clock import com.nextcloud.client.device.DeviceInfo import com.nextcloud.client.device.PowerManagementService import com.nextcloud.client.preferences.AppPreferences @@ -40,6 +41,7 @@ import javax.inject.Provider class BackgroundJobFactory @Inject constructor( private val preferences: AppPreferences, private val contentResolver: ContentResolver, + private val clock: Clock, private val powerManagerService: PowerManagementService, private val backgroundJobManager: Provider, private val deviceInfo: DeviceInfo @@ -58,13 +60,14 @@ class BackgroundJobFactory @Inject constructor( } return when (workerClass) { - ContentObserverWork::class -> createContentObserverJob(context, workerParameters) + ContentObserverWork::class -> createContentObserverJob(context, workerParameters, clock) else -> null // falls back to default factory } } - private fun createContentObserverJob(context: Context, workerParameters: WorkerParameters): ListenableWorker? { - val folderResolver = SyncedFolderProvider(contentResolver, preferences) + private fun createContentObserverJob(context: Context, workerParameters: WorkerParameters, clock: Clock): + ListenableWorker? { + val folderResolver = SyncedFolderProvider(contentResolver, preferences, clock) @RequiresApi(Build.VERSION_CODES.N) if (deviceInfo.apiLevel >= Build.VERSION_CODES.N) { return ContentObserverWork( diff --git a/src/main/java/com/owncloud/android/MainApp.java b/src/main/java/com/owncloud/android/MainApp.java index 05c90f3cae..3b7f088efe 100644 --- a/src/main/java/com/owncloud/android/MainApp.java +++ b/src/main/java/com/owncloud/android/MainApp.java @@ -45,6 +45,7 @@ import com.evernote.android.job.JobManager; import com.evernote.android.job.JobRequest; import com.nextcloud.client.account.UserAccountManager; import com.nextcloud.client.appinfo.AppInfo; +import com.nextcloud.client.core.Clock; import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.di.ActivityInjector; import com.nextcloud.client.di.DaggerAppComponent; @@ -161,6 +162,9 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { @Inject BackgroundJobManager backgroundJobManager; + @Inject + Clock clock; + private PassCodeManager passCodeManager; @SuppressWarnings("unused") @@ -268,7 +272,8 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { preferences, uploadsStorageManager, connectivityService, - powerManagementService + powerManagementService, + clock ) ); @@ -304,7 +309,8 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { accountManager, connectivityService, powerManagementService, - backgroundJobManager); + backgroundJobManager, + clock); initContactsBackup(accountManager); notificationChannels(); @@ -462,23 +468,24 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { final UserAccountManager accountManager, final ConnectivityService connectivityService, final PowerManagementService powerManagementService, - final BackgroundJobManager jobManager + final BackgroundJobManager jobManager, + final Clock clock ) { updateToAutoUpload(); - cleanOldEntries(); - updateAutoUploadEntries(); + cleanOldEntries(clock); + updateAutoUploadEntries(clock); if (getAppContext() != null) { if (PermissionUtil.checkSelfPermission(getAppContext(), Manifest.permission.WRITE_EXTERNAL_STORAGE)) { - splitOutAutoUploadEntries(); + splitOutAutoUploadEntries(clock); } else { AppPreferences preferences = AppPreferencesImpl.fromContext(getAppContext()); preferences.setAutoUploadSplitEntriesEnabled(true); } } - initiateExistingAutoUploadEntries(); + initiateExistingAutoUploadEntries(clock); FilesSyncHelper.scheduleFilesSyncIfNeeded(mContext, jobManager); FilesSyncHelper.restartJobsIfNeeded( @@ -685,18 +692,18 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { } } - private static void updateAutoUploadEntries() { + private static void updateAutoUploadEntries(Clock clock) { // updates entries to reflect their true paths Context context = getAppContext(); AppPreferences preferences = AppPreferencesImpl.fromContext(context); if (!preferences.isAutoUploadPathsUpdateEnabled()) { SyncedFolderProvider syncedFolderProvider = - new SyncedFolderProvider(MainApp.getAppContext().getContentResolver(), preferences); + new SyncedFolderProvider(MainApp.getAppContext().getContentResolver(), preferences, clock); syncedFolderProvider.updateAutoUploadPaths(mContext); } } - private static void splitOutAutoUploadEntries() { + private static void splitOutAutoUploadEntries(Clock clock) { Context context = getAppContext(); AppPreferences preferences = AppPreferencesImpl.fromContext(context); if (!preferences.isAutoUploadSplitEntriesEnabled()) { @@ -705,7 +712,7 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { Log_OC.i(TAG, "Migrate synced_folders records for image/video split"); ContentResolver contentResolver = context.getContentResolver(); - SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver, preferences); + SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver, preferences, clock); final List imageMediaFolders = MediaProvider.getImageFolders(contentResolver, 1, null, true); final List videoMediaFolders = MediaProvider.getVideoFolders(contentResolver, 1, null, true); @@ -751,12 +758,12 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { } } - private static void initiateExistingAutoUploadEntries() { + private static void initiateExistingAutoUploadEntries(Clock clock) { new Thread(() -> { AppPreferences preferences = AppPreferencesImpl.fromContext(getAppContext()); if (!preferences.isAutoUploadInitialized()) { SyncedFolderProvider syncedFolderProvider = - new SyncedFolderProvider(MainApp.getAppContext().getContentResolver(), preferences); + new SyncedFolderProvider(MainApp.getAppContext().getContentResolver(), preferences, clock); for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) { if (syncedFolder.isEnabled()) { @@ -770,7 +777,7 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { }).start(); } - private static void cleanOldEntries() { + private static void cleanOldEntries(Clock clock) { // previous versions of application created broken entries in the SyncedFolderProvider // database, and this cleans all that and leaves 1 (newest) entry per synced folder @@ -779,7 +786,7 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector { if (!preferences.isLegacyClean()) { SyncedFolderProvider syncedFolderProvider = - new SyncedFolderProvider(context.getContentResolver(), preferences); + new SyncedFolderProvider(context.getContentResolver(), preferences, clock); List syncedFolderList = syncedFolderProvider.getSyncedFolders(); Map, Long> syncedFolders = new HashMap<>(); diff --git a/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java b/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java index 24aaa1f3f7..91b42b8134 100644 --- a/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java +++ b/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java @@ -30,23 +30,23 @@ import lombok.Setter; /** * Synced folder entity containing all information per synced folder. */ -@Getter -@Setter @AllArgsConstructor public class SyncedFolder implements Serializable, Cloneable { public static final long UNPERSISTED_ID = Long.MIN_VALUE; + public static final long EMPTY_ENABLED_TIMESTAMP_MS = -1; private static final long serialVersionUID = -793476118299906429L; - private long id = UNPERSISTED_ID; - private String localPath; - private String remotePath; - private Boolean wifiOnly; - private Boolean chargingOnly; - private Boolean subfolderByDate; - private String account; - private Integer uploadAction; - private boolean enabled; - private MediaFolderType type; + @Getter @Setter private long id; + @Getter @Setter private String localPath; + @Getter @Setter private String remotePath; + @Getter @Setter private Boolean wifiOnly; + @Getter @Setter private Boolean chargingOnly; + @Getter @Setter private Boolean subfolderByDate; + @Getter @Setter private String account; + @Getter @Setter private Integer uploadAction; + @Getter private boolean enabled; + @Getter private long enabledTimestampMs; + @Getter @Setter private MediaFolderType type; /** * constructor for new, to be persisted entity. @@ -59,11 +59,25 @@ public class SyncedFolder implements Serializable, Cloneable { * @param account the account owning the synced folder * @param uploadAction the action to be done after the upload * @param enabled flag if synced folder config is active + * @param timestampMs the current timestamp in milliseconds * @param type the type of the folder */ public SyncedFolder(String localPath, String remotePath, Boolean wifiOnly, Boolean chargingOnly, Boolean subfolderByDate, String account, Integer uploadAction, Boolean enabled, - MediaFolderType type) { + long timestampMs, MediaFolderType type) { + this(UNPERSISTED_ID, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate, account, uploadAction, + enabled, timestampMs, type); + } + + /** + * constructor for wrapping existing folders. + * + * @param id id + */ + protected SyncedFolder(long id, String localPath, String remotePath, Boolean wifiOnly, Boolean chargingOnly, + Boolean subfolderByDate, String account, Integer uploadAction, Boolean enabled, + long timestampMs, MediaFolderType type) { + this.id = id; this.localPath = localPath; this.remotePath = remotePath; this.wifiOnly = wifiOnly; @@ -71,10 +85,18 @@ public class SyncedFolder implements Serializable, Cloneable { this.subfolderByDate = subfolderByDate; this.account = account; this.uploadAction = uploadAction; - this.enabled = enabled; + this.setEnabled(enabled, timestampMs); this.type = type; } + /** + * @param timestampMs the current timestamp in milliseconds + */ + public void setEnabled(boolean enabled, long timestampMs) { + this.enabled = enabled; + this.enabledTimestampMs = enabled ? timestampMs : EMPTY_ENABLED_TIMESTAMP_MS; + } + public Object clone() { try { return super.clone(); diff --git a/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java b/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java index cac3df7a14..7420b18892 100644 --- a/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java +++ b/src/main/java/com/owncloud/android/datamodel/SyncedFolderDisplayItem.java @@ -56,9 +56,11 @@ public class SyncedFolderDisplayItem extends SyncedFolder { */ public SyncedFolderDisplayItem(long id, String localPath, String remotePath, Boolean wifiOnly, Boolean chargingOnly, Boolean subfolderByDate, String account, Integer uploadAction, Boolean enabled, - List filePaths, String folderName, long numberOfFiles, MediaFolderType type) + long timestampMs, List filePaths, String folderName, long numberOfFiles, + MediaFolderType type) { - super(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate, account, uploadAction, enabled, type); + super(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate, account, uploadAction, enabled, + timestampMs, type); this.filePaths = filePaths; this.folderName = folderName; this.numberOfFiles = numberOfFiles; @@ -66,8 +68,9 @@ public class SyncedFolderDisplayItem extends SyncedFolder { public SyncedFolderDisplayItem(long id, String localPath, String remotePath, Boolean wifiOnly, Boolean chargingOnly, Boolean subfolderByDate, String account, Integer uploadAction, Boolean enabled, - String folderName, MediaFolderType type) { - super(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate, account, uploadAction, enabled, type); + long timestampMs, String folderName, MediaFolderType type) { + super(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate, account, uploadAction, enabled, + timestampMs, type); this.folderName = folderName; } } diff --git a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java index 07712a9e34..8a66a4058a 100644 --- a/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java +++ b/src/main/java/com/owncloud/android/datamodel/SyncedFolderProvider.java @@ -27,6 +27,7 @@ import android.content.Context; import android.database.Cursor; import android.net.Uri; +import com.nextcloud.client.core.Clock; import com.nextcloud.client.preferences.AppPreferences; import com.nextcloud.client.preferences.AppPreferencesImpl; import com.owncloud.android.db.ProviderMeta; @@ -47,20 +48,22 @@ import static com.owncloud.android.datamodel.OCFile.PATH_SEPARATOR; public class SyncedFolderProvider extends Observable { static private final String TAG = SyncedFolderProvider.class.getSimpleName(); - private ContentResolver mContentResolver; - private AppPreferences preferences; + private final ContentResolver mContentResolver; + private final AppPreferences preferences; + private final Clock clock; /** * constructor. * * @param contentResolver the ContentResolver to work with. */ - public SyncedFolderProvider(ContentResolver contentResolver, AppPreferences preferences) { + public SyncedFolderProvider(ContentResolver contentResolver, AppPreferences preferences, Clock clock) { if (contentResolver == null) { throw new IllegalArgumentException("Cannot create an instance with a NULL contentResolver"); } mContentResolver = contentResolver; this.preferences = preferences; + this.clock = clock; } /** @@ -162,7 +165,7 @@ public class SyncedFolderProvider extends Observable { // read sync folder object and update SyncedFolder syncedFolder = createSyncedFolderFromCursor(cursor); - syncedFolder.setEnabled(enabled); + syncedFolder.setEnabled(enabled, clock.getCurrentTime()); // update sync folder object in db result = updateSyncFolder(syncedFolder); @@ -347,11 +350,13 @@ public class SyncedFolderProvider extends Observable { ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION)); Boolean enabled = cursor.getInt(cursor.getColumnIndex( ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED)) == 1; + long enabledTimestampMs = cursor.getLong(cursor.getColumnIndex( + ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS)); MediaFolderType type = MediaFolderType.getById(cursor.getInt(cursor.getColumnIndex( ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_TYPE))); syncedFolder = new SyncedFolder(id, localPath, remotePath, wifiOnly, chargingOnly, subfolderByDate, - accountName, uploadAction, enabled, type); + accountName, uploadAction, enabled, enabledTimestampMs, type); } return syncedFolder; } @@ -370,6 +375,7 @@ public class SyncedFolderProvider extends Observable { cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_WIFI_ONLY, syncedFolder.getWifiOnly()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_CHARGING_ONLY, syncedFolder.getChargingOnly()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED, syncedFolder.isEnabled()); + cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS, syncedFolder.getEnabledTimestampMs()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE, syncedFolder.getSubfolderByDate()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_ACCOUNT, syncedFolder.getAccount()); cv.put(ProviderMeta.ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION, syncedFolder.getUploadAction()); diff --git a/src/main/java/com/owncloud/android/db/ProviderMeta.java b/src/main/java/com/owncloud/android/db/ProviderMeta.java index 093d36b9f2..8bbe982b15 100644 --- a/src/main/java/com/owncloud/android/db/ProviderMeta.java +++ b/src/main/java/com/owncloud/android/db/ProviderMeta.java @@ -31,7 +31,7 @@ import com.owncloud.android.MainApp; */ public class ProviderMeta { public static final String DB_NAME = "filelist"; - public static final int DB_VERSION = 49; + public static final int DB_VERSION = 50; private ProviderMeta() { // No instance @@ -220,6 +220,7 @@ public class ProviderMeta { public static final String SYNCED_FOLDER_WIFI_ONLY = "wifi_only"; public static final String SYNCED_FOLDER_CHARGING_ONLY = "charging_only"; public static final String SYNCED_FOLDER_ENABLED = "enabled"; + public static final String SYNCED_FOLDER_ENABLED_TIMESTAMP_MS = "enabled_timestamp_ms"; public static final String SYNCED_FOLDER_TYPE = "type"; public static final String SYNCED_FOLDER_SUBFOLDER_BY_DATE = "subfolder_by_date"; public static final String SYNCED_FOLDER_ACCOUNT = "account"; diff --git a/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java b/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java index 77f1535f07..311d45240a 100644 --- a/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java +++ b/src/main/java/com/owncloud/android/files/BootupBroadcastReceiver.java @@ -28,6 +28,7 @@ import android.content.Context; import android.content.Intent; import com.nextcloud.client.account.UserAccountManager; +import com.nextcloud.client.core.Clock; import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.jobs.BackgroundJobManager; import com.nextcloud.client.network.ConnectivityService; @@ -53,6 +54,7 @@ public class BootupBroadcastReceiver extends BroadcastReceiver { @Inject ConnectivityService connectivityService; @Inject PowerManagementService powerManagementService; @Inject BackgroundJobManager backgroundJobManager; + @Inject Clock clock; /** * Receives broadcast intent reporting that the system was just boot up. @@ -69,7 +71,8 @@ public class BootupBroadcastReceiver extends BroadcastReceiver { accountManager, connectivityService, powerManagementService, - backgroundJobManager); + backgroundJobManager, + clock); MainApp.initContactsBackup(accountManager); } else { Log_OC.d(TAG, "Getting wrong intent: " + intent.getAction()); diff --git a/src/main/java/com/owncloud/android/jobs/AccountRemovalJob.java b/src/main/java/com/owncloud/android/jobs/AccountRemovalJob.java index b87d3e99de..a63793d129 100644 --- a/src/main/java/com/owncloud/android/jobs/AccountRemovalJob.java +++ b/src/main/java/com/owncloud/android/jobs/AccountRemovalJob.java @@ -38,6 +38,7 @@ import com.evernote.android.job.Job; import com.evernote.android.job.util.support.PersistableBundleCompat; import com.google.gson.Gson; import com.nextcloud.client.account.UserAccountManager; +import com.nextcloud.client.core.Clock; import com.nextcloud.client.preferences.AppPreferencesImpl; import com.owncloud.android.MainApp; import com.owncloud.android.R; @@ -57,7 +58,6 @@ import com.owncloud.android.ui.activity.ContactsPreferenceActivity; import com.owncloud.android.ui.events.AccountRemovedEvent; import com.owncloud.android.utils.EncryptionUtils; import com.owncloud.android.utils.FileStorageUtils; -import com.owncloud.android.utils.FilesSyncHelper; import com.owncloud.android.utils.PushUtils; import org.greenrobot.eventbus.EventBus; @@ -81,12 +81,14 @@ public class AccountRemovalJob extends Job implements AccountManagerCallback syncedFolders = syncedFolderProvider.getSyncedFolders(); List syncedFolderIds = new ArrayList<>(); for (SyncedFolder syncedFolder : syncedFolders) { if (syncedFolder.getAccount().equals(account.name)) { - arbitraryDataProvider.deleteKeyForAccount(FilesSyncHelper.GLOBAL, - FilesSyncHelper.SYNCEDFOLDERINITIATED + syncedFolder.getId()); syncedFolderIds.add(syncedFolder.getId()); } } diff --git a/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java b/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java index 0a254580a0..5c7a9771aa 100644 --- a/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java +++ b/src/main/java/com/owncloud/android/jobs/FilesSyncJob.java @@ -34,6 +34,7 @@ import android.text.TextUtils; import com.evernote.android.job.Job; import com.evernote.android.job.util.support.PersistableBundleCompat; import com.nextcloud.client.account.UserAccountManager; +import com.nextcloud.client.core.Clock; import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.network.ConnectivityService; import com.nextcloud.client.preferences.AppPreferences; @@ -76,22 +77,25 @@ public class FilesSyncJob extends Job { public static final String OVERRIDE_POWER_SAVING = "overridePowerSaving"; private static final String WAKELOCK_TAG_SEPARATION = ":"; - private UserAccountManager userAccountManager; - private AppPreferences preferences; - private UploadsStorageManager uploadsStorageManager; - private ConnectivityService connectivityService; - private PowerManagementService powerManagementService; + private final UserAccountManager userAccountManager; + private final AppPreferences preferences; + private final UploadsStorageManager uploadsStorageManager; + private final ConnectivityService connectivityService; + private final PowerManagementService powerManagementService; + private final Clock clock; FilesSyncJob(final UserAccountManager userAccountManager, final AppPreferences preferences, final UploadsStorageManager uploadsStorageManager, final ConnectivityService connectivityService, - final PowerManagementService powerManagementService) { + final PowerManagementService powerManagementService, + final Clock clock) { this.userAccountManager = userAccountManager; this.preferences = preferences; this.uploadsStorageManager = uploadsStorageManager; this.connectivityService = connectivityService; this.powerManagementService = powerManagementService; + this.clock = clock; } @NonNull @@ -126,13 +130,12 @@ public class FilesSyncJob extends Job { userAccountManager, connectivityService, powerManagementService); - FilesSyncHelper.insertAllDBEntries(preferences, skipCustom); + FilesSyncHelper.insertAllDBEntries(preferences, clock, skipCustom); // Create all the providers we'll need final ContentResolver contentResolver = context.getContentResolver(); final FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver); - SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver, - preferences); + SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver, preferences, clock); Locale currentLocale = context.getResources().getConfiguration().locale; SimpleDateFormat sFormatter = new SimpleDateFormat("yyyy:MM:dd HH:mm:ss", currentLocale); diff --git a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java index 43e0736088..e421b9365a 100644 --- a/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java +++ b/src/main/java/com/owncloud/android/jobs/MediaFoldersDetectionJob.java @@ -39,6 +39,7 @@ import android.text.TextUtils; import com.evernote.android.job.Job; import com.google.gson.Gson; import com.nextcloud.client.account.UserAccountManager; +import com.nextcloud.client.core.Clock; import com.nextcloud.client.preferences.AppPreferences; import com.nextcloud.client.preferences.AppPreferencesImpl; import com.owncloud.android.R; @@ -74,11 +75,13 @@ public class MediaFoldersDetectionJob extends Job { private static final String DISABLE_DETECTION_CLICK = "DISABLE_DETECTION_CLICK"; - private UserAccountManager userAccountManager; - private Random randomId = new Random(); + private final UserAccountManager userAccountManager; + private final Clock clock; + private final Random randomId = new Random(); - MediaFoldersDetectionJob(UserAccountManager accountManager) { + MediaFoldersDetectionJob(UserAccountManager accountManager, Clock clock) { this.userAccountManager = accountManager; + this.clock = clock; } @NonNull @@ -88,7 +91,8 @@ public class MediaFoldersDetectionJob extends Job { ContentResolver contentResolver = context.getContentResolver(); ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(contentResolver); SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver, - AppPreferencesImpl.fromContext(context)); + AppPreferencesImpl.fromContext(context), + clock); Gson gson = new Gson(); String arbitraryDataString; MediaFoldersModel mediaFoldersModel; diff --git a/src/main/java/com/owncloud/android/jobs/NCJobCreator.java b/src/main/java/com/owncloud/android/jobs/NCJobCreator.java index c0894a59e1..010ae26689 100644 --- a/src/main/java/com/owncloud/android/jobs/NCJobCreator.java +++ b/src/main/java/com/owncloud/android/jobs/NCJobCreator.java @@ -29,6 +29,7 @@ import android.content.Context; import com.evernote.android.job.Job; import com.evernote.android.job.JobCreator; import com.nextcloud.client.account.UserAccountManager; +import com.nextcloud.client.core.Clock; import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.network.ConnectivityService; import com.nextcloud.client.preferences.AppPreferences; @@ -48,6 +49,7 @@ public class NCJobCreator implements JobCreator { private final UploadsStorageManager uploadsStorageManager; private final ConnectivityService connectivityService; private final PowerManagementService powerManagementService; + private final Clock clock; public NCJobCreator( Context context, @@ -55,7 +57,8 @@ public class NCJobCreator implements JobCreator { AppPreferences preferences, UploadsStorageManager uploadsStorageManager, ConnectivityService connectivityServices, - PowerManagementService powerManagementService + PowerManagementService powerManagementService, + Clock clock ) { this.context = context; this.accountManager = accountManager; @@ -63,6 +66,7 @@ public class NCJobCreator implements JobCreator { this.uploadsStorageManager = uploadsStorageManager; this.connectivityService = connectivityServices; this.powerManagementService = powerManagementService; + this.clock = clock; } @Override @@ -73,19 +77,20 @@ public class NCJobCreator implements JobCreator { case ContactsImportJob.TAG: return new ContactsImportJob(); case AccountRemovalJob.TAG: - return new AccountRemovalJob(uploadsStorageManager, accountManager); + return new AccountRemovalJob(uploadsStorageManager, accountManager, clock); case FilesSyncJob.TAG: return new FilesSyncJob(accountManager, preferences, uploadsStorageManager, connectivityService, - powerManagementService); + powerManagementService, + clock); case OfflineSyncJob.TAG: return new OfflineSyncJob(accountManager, connectivityService, powerManagementService); case NotificationJob.TAG: return new NotificationJob(context, accountManager); case MediaFoldersDetectionJob.TAG: - return new MediaFoldersDetectionJob(accountManager); + return new MediaFoldersDetectionJob(accountManager, clock); default: return null; } diff --git a/src/main/java/com/owncloud/android/providers/FileContentProvider.java b/src/main/java/com/owncloud/android/providers/FileContentProvider.java index bcfe381e53..78824925e4 100644 --- a/src/main/java/com/owncloud/android/providers/FileContentProvider.java +++ b/src/main/java/com/owncloud/android/providers/FileContentProvider.java @@ -42,9 +42,11 @@ import android.net.Uri; import android.os.Binder; import android.text.TextUtils; +import com.nextcloud.client.core.Clock; import com.owncloud.android.MainApp; import com.owncloud.android.R; import com.owncloud.android.datamodel.OCFile; +import com.owncloud.android.datamodel.SyncedFolder; import com.owncloud.android.db.ProviderMeta; import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; import com.owncloud.android.lib.common.accounts.AccountUtils; @@ -58,7 +60,10 @@ import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; +import javax.inject.Inject; + import androidx.annotation.NonNull; +import dagger.android.AndroidInjection; /** * The ContentProvider for the ownCloud App. @@ -91,6 +96,7 @@ public class FileContentProvider extends ContentProvider { public static final int ARBITRARY_DATA_TABLE_INTRODUCTION_VERSION = 20; public static final int MINIMUM_PATH_SEGMENTS_SIZE = 1; + @Inject protected Clock clock; private DataBaseHelper mDbHelper; private Context mContext; private UriMatcher mUriMatcher; @@ -414,6 +420,7 @@ public class FileContentProvider extends ContentProvider { @Override public boolean onCreate() { + AndroidInjection.inject(this); mDbHelper = new DataBaseHelper(getContext()); mContext = getContext(); @@ -822,6 +829,7 @@ public class FileContentProvider extends ContentProvider { + ProviderTableMeta.SYNCED_FOLDER_WIFI_ONLY + " INTEGER, " // wifi_only + ProviderTableMeta.SYNCED_FOLDER_CHARGING_ONLY + " INTEGER, " // charging only + ProviderTableMeta.SYNCED_FOLDER_ENABLED + " INTEGER, " // enabled + + ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS + " INTEGER, " // enable date + ProviderTableMeta.SYNCED_FOLDER_SUBFOLDER_BY_DATE + " INTEGER, " // subfolder by date + ProviderTableMeta.SYNCED_FOLDER_ACCOUNT + " TEXT, " // account + ProviderTableMeta.SYNCED_FOLDER_UPLOAD_ACTION + " INTEGER, " // upload action @@ -2013,6 +2021,30 @@ public class FileContentProvider extends ContentProvider { if (!upgraded) { Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion)); } + + if (oldVersion < 50 && newVersion >= 50) { + Log_OC.i(SQL, "Entering in the #50 add persistent enable date to synced_folders table"); + db.beginTransaction(); + try { + db.execSQL(ALTER_TABLE + ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME + + ADD_COLUMN + ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS + " INTEGER "); + + db.execSQL("UPDATE " + ProviderTableMeta.SYNCED_FOLDERS_TABLE_NAME + " SET " + + ProviderTableMeta.SYNCED_FOLDER_ENABLED_TIMESTAMP_MS + " = CASE " + + " WHEN enabled = 0 THEN " + SyncedFolder.EMPTY_ENABLED_TIMESTAMP_MS + " " + + " ELSE " + clock.getCurrentTime() + + " END "); + + upgraded = true; + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } + } + + if (!upgraded) { + Log_OC.i(SQL, String.format(Locale.ENGLISH, UPGRADE_VERSION_MSG, oldVersion, newVersion)); + } } @Override diff --git a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java index 0bf20965b4..85506e0652 100644 --- a/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java +++ b/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.java @@ -41,13 +41,13 @@ import android.view.View; import android.widget.LinearLayout; import android.widget.TextView; +import com.nextcloud.client.core.Clock; import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.di.Injectable; import com.nextcloud.client.preferences.AppPreferences; import com.owncloud.android.BuildConfig; import com.owncloud.android.MainApp; import com.owncloud.android.R; -import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.MediaFolder; import com.owncloud.android.datamodel.MediaFolderType; import com.owncloud.android.datamodel.MediaProvider; @@ -113,6 +113,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA private int type; @Inject AppPreferences preferences; @Inject PowerManagementService powerManagementService; + @Inject Clock clock; @Override protected void onCreate(Bundle savedInstanceState) { @@ -223,8 +224,8 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA final int gridWidth = getResources().getInteger(R.integer.media_grid_width); boolean lightVersion = getResources().getBoolean(R.bool.syncedFolder_light); - mAdapter = new SyncedFolderAdapter(this, gridWidth, this, lightVersion); - mSyncedFolderProvider = new SyncedFolderProvider(getContentResolver(), preferences); + mAdapter = new SyncedFolderAdapter(this, clock, gridWidth, this, lightVersion); + mSyncedFolderProvider = new SyncedFolderProvider(getContentResolver(), preferences, clock); final GridLayoutManager lm = new GridLayoutManager(this, gridWidth); mAdapter.setLayoutManager(lm); @@ -386,6 +387,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA syncedFolder.getAccount(), syncedFolder.getUploadAction(), syncedFolder.isEnabled(), + clock.getCurrentTime(), filePaths, localFolder.getName(), files.length, @@ -411,6 +413,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA syncedFolder.getAccount(), syncedFolder.getUploadAction(), syncedFolder.isEnabled(), + clock.getCurrentTime(), mediaFolder.filePaths, mediaFolder.folderName, mediaFolder.numberOfFiles, @@ -432,9 +435,10 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA true, false, false, - getAccount().name, + getAccount().name, FileUploader.LOCAL_BEHAVIOUR_FORGET, false, + clock.getCurrentTime(), mediaFolder.filePaths, mediaFolder.folderName, mediaFolder.numberOfFiles, @@ -519,7 +523,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA SyncedFolderDisplayItem emptyCustomFolder = new SyncedFolderDisplayItem( SyncedFolder.UNPERSISTED_ID, null, null, true, false, false, getAccount().name, - FileUploader.LOCAL_BEHAVIOUR_FORGET, false, null, MediaFolderType.CUSTOM); + FileUploader.LOCAL_BEHAVIOUR_FORGET, false, clock.getCurrentTime(), null, MediaFolderType.CUSTOM); onSyncFolderSettingsClick(0, emptyCustomFolder); } @@ -548,9 +552,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA @Override public void onSyncStatusToggleClick(int section, SyncedFolderDisplayItem syncedFolderDisplayItem) { - ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(MainApp.getAppContext(). - getContentResolver()); - if (syncedFolderDisplayItem.getId() > UNPERSISTED_ID) { mSyncedFolderProvider.updateSyncedFolderEnabled(syncedFolderDisplayItem.getId(), syncedFolderDisplayItem.isEnabled()); @@ -565,9 +566,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA FilesSyncHelper.insertAllDBEntriesForSyncedFolder(syncedFolderDisplayItem); showBatteryOptimizationInfo(); - } else { - String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + syncedFolderDisplayItem.getId(); - arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey); } } @@ -600,9 +598,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA @Override public void onSaveSyncedFolderPreference(SyncedFolderParcelable syncedFolder) { - ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(MainApp.getAppContext(). - getContentResolver()); - // custom folders newly created aren't in the list already, // so triggering a refresh if (MediaFolderType.CUSTOM == syncedFolder.getType() && syncedFolder.getId() == UNPERSISTED_ID) { @@ -610,15 +605,12 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA SyncedFolder.UNPERSISTED_ID, syncedFolder.getLocalPath(), syncedFolder.getRemotePath(), syncedFolder.getWifiOnly(), syncedFolder.getChargingOnly(), syncedFolder.getSubfolderByDate(), syncedFolder.getAccount(), syncedFolder.getUploadAction(), syncedFolder.getEnabled(), - new File(syncedFolder.getLocalPath()).getName(), syncedFolder.getType()); + clock.getCurrentTime(), new File(syncedFolder.getLocalPath()).getName(), syncedFolder.getType()); long storedId = mSyncedFolderProvider.storeSyncedFolder(newCustomFolder); if (storedId != -1) { newCustomFolder.setId(storedId); if (newCustomFolder.isEnabled()) { FilesSyncHelper.insertAllDBEntriesForSyncedFolder(newCustomFolder); - } else { - String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + newCustomFolder.getId(); - arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey); } } mAdapter.addSyncFolderItem(newCustomFolder); @@ -635,9 +627,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA item.setId(storedId); if (item.isEnabled()) { FilesSyncHelper.insertAllDBEntriesForSyncedFolder(item); - } else { - String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + item.getId(); - arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey); } } } else { @@ -645,9 +634,6 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA mSyncedFolderProvider.updateSyncFolder(item); if (item.isEnabled()) { FilesSyncHelper.insertAllDBEntriesForSyncedFolder(item); - } else { - String syncedFolderInitiatedKey = "syncedFolderIntitiated_" + item.getId(); - arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey); } } @@ -699,7 +685,7 @@ public class SyncedFoldersActivity extends FileActivity implements SyncedFolderA item.setChargingOnly(chargingOnly); item.setSubfolderByDate(subfolderByDate); item.setUploadAction(uploadAction); - item.setEnabled(enabled); + item.setEnabled(enabled, clock.getCurrentTime()); return item; } diff --git a/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java b/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java index 8a8176e54e..7588b323da 100644 --- a/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java +++ b/src/main/java/com/owncloud/android/ui/adapter/SyncedFolderAdapter.java @@ -33,6 +33,7 @@ import android.widget.TextView; import com.afollestad.sectionedrecyclerview.SectionedRecyclerViewAdapter; import com.afollestad.sectionedrecyclerview.SectionedViewHolder; +import com.nextcloud.client.core.Clock; import com.owncloud.android.R; import com.owncloud.android.datamodel.MediaFolderType; import com.owncloud.android.datamodel.SyncedFolderDisplayItem; @@ -54,14 +55,16 @@ import butterknife.ButterKnife; public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter { private final Context mContext; + private final Clock clock; private final int mGridWidth; private final int mGridTotal; private final ClickListener mListener; private final List mSyncFolderItems; private final boolean mLight; - public SyncedFolderAdapter(Context context, int gridWidth, ClickListener listener, boolean light) { + public SyncedFolderAdapter(Context context, Clock clock, int gridWidth, ClickListener listener, boolean light) { mContext = context; + this.clock = clock; mGridWidth = gridWidth; mGridTotal = gridWidth * 2; mListener = listener; @@ -148,7 +151,7 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter { - mSyncFolderItems.get(section).setEnabled(!mSyncFolderItems.get(section).isEnabled()); + mSyncFolderItems.get(section).setEnabled(!mSyncFolderItems.get(section).isEnabled(), clock.getCurrentTime()); setSyncButtonActiveIcon(holder.syncStatusButton, mSyncFolderItems.get(section).isEnabled()); mListener.onSyncStatusToggleClick(section, mSyncFolderItems.get(section)); }); @@ -157,7 +160,7 @@ public class SyncedFolderAdapter extends SectionedRecyclerViewAdapter { - mSyncFolderItems.get(section).setEnabled(!mSyncFolderItems.get(section).isEnabled()); + mSyncFolderItems.get(section).setEnabled(!mSyncFolderItems.get(section).isEnabled(), clock.getCurrentTime()); setSyncButtonActiveIcon(holder.syncStatusButton, mSyncFolderItems.get(section).isEnabled()); mListener.onSyncStatusToggleClick(section, mSyncFolderItems.get(section)); }); diff --git a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java index 9116a3d570..e2074b3139 100644 --- a/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java +++ b/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java @@ -30,18 +30,16 @@ import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.provider.MediaStore; -import android.text.TextUtils; -import android.util.Log; import com.evernote.android.job.JobManager; import com.evernote.android.job.JobRequest; import com.nextcloud.client.account.UserAccountManager; +import com.nextcloud.client.core.Clock; import com.nextcloud.client.device.PowerManagementService; import com.nextcloud.client.jobs.BackgroundJobManager; import com.nextcloud.client.network.ConnectivityService; import com.nextcloud.client.preferences.AppPreferences; import com.owncloud.android.MainApp; -import com.owncloud.android.datamodel.ArbitraryDataProvider; import com.owncloud.android.datamodel.FilesystemDataProvider; import com.owncloud.android.datamodel.MediaFolderType; import com.owncloud.android.datamodel.SyncedFolder; @@ -51,6 +49,7 @@ import com.owncloud.android.db.OCUpload; import com.owncloud.android.files.services.FileUploader; import com.owncloud.android.jobs.FilesSyncJob; import com.owncloud.android.jobs.OfflineSyncJob; +import com.owncloud.android.lib.common.utils.Log_OC; import org.lukhnos.nnio.file.FileVisitResult; import org.lukhnos.nnio.file.Files; @@ -73,7 +72,6 @@ public final class FilesSyncHelper { public static final String TAG = "FileSyncHelper"; public static final String GLOBAL = "global"; - public static final String SYNCEDFOLDERINITIATED = "syncedFolderIntitiated_"; public static final int ContentSyncJobId = 315; @@ -84,59 +82,34 @@ public final class FilesSyncHelper { public static void insertAllDBEntriesForSyncedFolder(SyncedFolder syncedFolder) { final Context context = MainApp.getAppContext(); final ContentResolver contentResolver = context.getContentResolver(); - ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(contentResolver); - Long currentTime = System.currentTimeMillis(); - double currentTimeInSeconds = currentTime / 1000.0; - String currentTimeString = Long.toString((long) currentTimeInSeconds); + final long enabledTimestampMs = syncedFolder.getEnabledTimestampMs(); - String syncedFolderInitiatedKey = SYNCEDFOLDERINITIATED + syncedFolder.getId(); - boolean dryRun = TextUtils.isEmpty(arbitraryDataProvider.getValue - (GLOBAL, syncedFolderInitiatedKey)); - - if (MediaFolderType.IMAGE == syncedFolder.getType()) { - if (dryRun) { - arbitraryDataProvider.storeOrUpdateKeyValue(GLOBAL, syncedFolderInitiatedKey, - currentTimeString); - } else { - FilesSyncHelper.insertContentIntoDB(android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI - , syncedFolder); + if (syncedFolder.isEnabled() && enabledTimestampMs >= 0) { + MediaFolderType mediaType = syncedFolder.getType(); + if (mediaType == MediaFolderType.IMAGE) { + FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.INTERNAL_CONTENT_URI + , syncedFolder); FilesSyncHelper.insertContentIntoDB(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, - syncedFolder); - } - - } else if (MediaFolderType.VIDEO == syncedFolder.getType()) { - - if (dryRun) { - arbitraryDataProvider.storeOrUpdateKeyValue(GLOBAL, syncedFolderInitiatedKey, - currentTimeString); - } else { - FilesSyncHelper.insertContentIntoDB(android.provider.MediaStore.Video.Media.INTERNAL_CONTENT_URI, - syncedFolder); + syncedFolder); + } else if (mediaType == MediaFolderType.VIDEO) { + FilesSyncHelper.insertContentIntoDB(MediaStore.Video.Media.INTERNAL_CONTENT_URI, + syncedFolder); FilesSyncHelper.insertContentIntoDB(MediaStore.Video.Media.EXTERNAL_CONTENT_URI, - syncedFolder); - } - - } else { - try { - if (dryRun) { - arbitraryDataProvider.storeOrUpdateKeyValue(GLOBAL, syncedFolderInitiatedKey, - currentTimeString); - } else { + syncedFolder); + } else { + try { FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver); Path path = Paths.get(syncedFolder.getLocalPath()); - String dateInitiated = arbitraryDataProvider.getValue(GLOBAL, - syncedFolderInitiatedKey); - Files.walkFileTree(path, new SimpleFileVisitor() { @Override public FileVisitResult visitFile(Path path, BasicFileAttributes attrs) { - File file = path.toFile(); - if (attrs.lastModifiedTime().toMillis() >= Long.parseLong(dateInitiated) * 1000) { + if (attrs.lastModifiedTime().toMillis() >= enabledTimestampMs) { filesystemDataProvider.storeOrUpdateFileValue(path.toAbsolutePath().toString(), - attrs.lastModifiedTime().toMillis(), file.isDirectory(), syncedFolder); + attrs.lastModifiedTime().toMillis(), + file.isDirectory(), syncedFolder); } return FileVisitResult.CONTINUE; @@ -147,20 +120,17 @@ public final class FilesSyncHelper { return FileVisitResult.CONTINUE; } }); - + } catch (IOException e) { + Log_OC.e(TAG, "Something went wrong while indexing files for auto upload", e); } - - } catch (IOException e) { - Log.e(TAG, "Something went wrong while indexing files for auto upload " + e.getLocalizedMessage()); } } } - public static void insertAllDBEntries(AppPreferences preferences, boolean skipCustom) { + public static void insertAllDBEntries(AppPreferences preferences, Clock clock, boolean skipCustom) { final Context context = MainApp.getAppContext(); final ContentResolver contentResolver = context.getContentResolver(); - SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver, - preferences); + SyncedFolderProvider syncedFolderProvider = new SyncedFolderProvider(contentResolver, preferences, clock); for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) { if (syncedFolder.isEnabled() && (MediaFolderType.CUSTOM != syncedFolder.getType() || !skipCustom)) { @@ -172,7 +142,6 @@ public final class FilesSyncHelper { private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder) { final Context context = MainApp.getAppContext(); final ContentResolver contentResolver = context.getContentResolver(); - ArbitraryDataProvider arbitraryDataProvider = new ArbitraryDataProvider(contentResolver); Cursor cursor; int column_index_data; @@ -191,11 +160,10 @@ public final class FilesSyncHelper { } path = path + "%"; - String syncedFolderInitiatedKey = SYNCEDFOLDERINITIATED + syncedFolder.getId(); - String dateInitiated = arbitraryDataProvider.getValue(GLOBAL, syncedFolderInitiatedKey); + long enabledTimestampMs = syncedFolder.getEnabledTimestampMs(); cursor = context.getContentResolver().query(uri, projection, MediaStore.MediaColumns.DATA + " LIKE ?", - new String[]{path}, null); + new String[]{path}, null); if (cursor != null) { column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA); @@ -203,9 +171,10 @@ public final class FilesSyncHelper { while (cursor.moveToNext()) { contentPath = cursor.getString(column_index_data); isFolder = new File(contentPath).isDirectory(); - if (cursor.getLong(column_index_date_modified) >= Long.parseLong(dateInitiated)) { + if (cursor.getLong(column_index_date_modified) >= enabledTimestampMs / 1000.0) { filesystemDataProvider.storeOrUpdateFileValue(contentPath, - cursor.getLong(column_index_date_modified), isFolder, syncedFolder); + cursor.getLong(column_index_date_modified), isFolder, + syncedFolder); } } cursor.close(); diff --git a/src/test/java/com/nextcloud/client/jobs/BackgroundJobFactoryTest.kt b/src/test/java/com/nextcloud/client/jobs/BackgroundJobFactoryTest.kt index 826d5a8621..23a5f88eed 100644 --- a/src/test/java/com/nextcloud/client/jobs/BackgroundJobFactoryTest.kt +++ b/src/test/java/com/nextcloud/client/jobs/BackgroundJobFactoryTest.kt @@ -24,6 +24,7 @@ import android.content.ContentResolver import android.content.Context import android.os.Build import androidx.work.WorkerParameters +import com.nextcloud.client.core.Clock import com.nextcloud.client.device.DeviceInfo import com.nextcloud.client.device.PowerManagementService import com.nextcloud.client.preferences.AppPreferences @@ -59,6 +60,9 @@ class BackgroundJobFactoryTest { @Mock private lateinit var deviceInfo: DeviceInfo + @Mock + private lateinit var clock: Clock + private lateinit var factory: BackgroundJobFactory @Before @@ -67,6 +71,7 @@ class BackgroundJobFactoryTest { factory = BackgroundJobFactory( preferences, contentResolver, + clock, powerManagementService, Provider { backgroundJobManager }, deviceInfo diff --git a/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java b/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java index b29b06c6bc..2861b3e3c0 100644 --- a/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java +++ b/src/test/java/com/owncloud/android/ui/activity/SyncedFoldersActivityTest.java @@ -177,6 +177,7 @@ public class SyncedFoldersActivityTest { "test@nextcloud.com", 1, enabled, + System.currentTimeMillis(), new ArrayList(), folderName, 2,