Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions src/main/java/com/nextcloud/client/di/ComponentsModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
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;
Expand Down Expand Up @@ -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();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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<BackgroundJobManager>,
private val deviceInfo: DeviceInfo
Expand All @@ -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(
Expand Down
37 changes: 22 additions & 15 deletions src/main/java/com/owncloud/android/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
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;
Expand Down Expand Up @@ -161,6 +162,9 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
@Inject
BackgroundJobManager backgroundJobManager;

@Inject
Clock clock;

private PassCodeManager passCodeManager;

@SuppressWarnings("unused")
Expand Down Expand Up @@ -268,7 +272,8 @@ public void onCreate() {
preferences,
uploadsStorageManager,
connectivityService,
powerManagementService
powerManagementService,
clock
)
);

Expand Down Expand Up @@ -304,7 +309,8 @@ public void onCreate() {
accountManager,
connectivityService,
powerManagementService,
backgroundJobManager);
backgroundJobManager,
clock);
initContactsBackup(accountManager);
notificationChannels();

Expand Down Expand Up @@ -462,23 +468,24 @@ public static void initSyncOperations(
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(
Expand Down Expand Up @@ -685,18 +692,18 @@ private static void updateToAutoUpload() {
}
}

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()) {
Expand All @@ -705,7 +712,7 @@ private static void splitOutAutoUploadEntries() {
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<MediaFolder> imageMediaFolders = MediaProvider.getImageFolders(contentResolver, 1, null, true);
final List<MediaFolder> videoMediaFolders = MediaProvider.getVideoFolders(contentResolver, 1, null, true);
Expand Down Expand Up @@ -751,12 +758,12 @@ private static void splitOutAutoUploadEntries() {
}
}

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()) {
Expand All @@ -770,7 +777,7 @@ private static void initiateExistingAutoUploadEntries() {
}).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

Expand All @@ -779,7 +786,7 @@ private static void cleanOldEntries() {

if (!preferences.isLegacyClean()) {
SyncedFolderProvider syncedFolderProvider =
new SyncedFolderProvider(context.getContentResolver(), preferences);
new SyncedFolderProvider(context.getContentResolver(), preferences, clock);

List<SyncedFolder> syncedFolderList = syncedFolderProvider.getSyncedFolders();
Map<Pair<String, String>, Long> syncedFolders = new HashMap<>();
Expand Down
50 changes: 36 additions & 14 deletions src/main/java/com/owncloud/android/datamodel/SyncedFolder.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,23 +30,23 @@
/**
* 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.
Expand All @@ -59,22 +59,44 @@ 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;
this.chargingOnly = chargingOnly;
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();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,18 +56,21 @@ 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<String> filePaths, String folderName, long numberOfFiles, MediaFolderType type)
long timestampMs, List<String> 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;
}

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;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
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;
Expand All @@ -47,20 +48,22 @@
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;
}

/**
Expand Down Expand Up @@ -162,7 +165,7 @@ public int updateSyncedFolderEnabled(long id, Boolean enabled) {
// 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);
Expand Down Expand Up @@ -347,11 +350,13 @@ private SyncedFolder createSyncedFolderFromCursor(Cursor cursor) {
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;
}
Expand All @@ -370,6 +375,7 @@ private ContentValues createContentValuesFromSyncedFolder(SyncedFolder syncedFol
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());
Expand Down
3 changes: 2 additions & 1 deletion src/main/java/com/owncloud/android/db/ProviderMeta.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
*/
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
Expand Down Expand Up @@ -220,6 +220,7 @@ static public class ProviderTableMeta implements BaseColumns {
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";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
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;
Expand All @@ -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.
Expand All @@ -69,7 +71,8 @@ public void onReceive(Context context, Intent intent) {
accountManager,
connectivityService,
powerManagementService,
backgroundJobManager);
backgroundJobManager,
clock);
MainApp.initContactsBackup(accountManager);
} else {
Log_OC.d(TAG, "Getting wrong intent: " + intent.getAction());
Expand Down
Loading