Browse Source

Finish delta sync functionality for media files

Signed-off-by: Jonas Mayer <jonas.a.mayer@gmx.net>
Jonas Mayer 1 year ago
parent
commit
68e9ecf578

+ 6 - 1
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManager.kt

@@ -133,7 +133,12 @@ interface BackgroundJobManager {
     fun startImmediateFilesExportJob(files: Collection<OCFile>): LiveData<JobInfo?>
 
     fun schedulePeriodicFilesSyncJob()
-    fun startImmediateFilesSyncJob(skipCustomFolders: Boolean = false, overridePowerSaving: Boolean = false)
+
+    fun startImmediateFilesSyncJob(
+        overridePowerSaving: Boolean = false,
+        changedFiles: Array<String> = arrayOf<String>()
+    )
+
     fun scheduleOfflineSync()
 
     fun scheduleMediaFoldersDetectionJob()

+ 5 - 2
app/src/main/java/com/nextcloud/client/jobs/BackgroundJobManagerImpl.kt

@@ -425,10 +425,13 @@ internal class BackgroundJobManagerImpl(
         workManager.enqueueUniquePeriodicWork(JOB_PERIODIC_FILES_SYNC, ExistingPeriodicWorkPolicy.REPLACE, request)
     }
 
-    override fun startImmediateFilesSyncJob(skipCustomFolders: Boolean, overridePowerSaving: Boolean) {
+    override fun startImmediateFilesSyncJob(
+        overridePowerSaving: Boolean,
+        changedFiles: Array<String>
+    ) {
         val arguments = Data.Builder()
-            .putBoolean(FilesSyncWork.SKIP_CUSTOM, skipCustomFolders)
             .putBoolean(FilesSyncWork.OVERRIDE_POWER_SAVING, overridePowerSaving)
+            .putStringArray(FilesSyncWork.CHANGED_FILES, changedFiles)
             .build()
 
         val request = oneTimeRequestBuilder(

+ 5 - 1
app/src/main/java/com/nextcloud/client/jobs/ContentObserverWork.kt

@@ -61,7 +61,11 @@ class ContentObserverWork(
     private fun checkAndStartFileSyncJob() {
         val syncFolders = syncerFolderProvider.countEnabledSyncedFolders() > 0
         if (!powerManagementService.isPowerSavingEnabled && syncFolders) {
-            backgroundJobManager.startImmediateFilesSyncJob(true, false)
+            val changedFiles = mutableListOf<String>();
+            for (uri in params.triggeredContentUris){
+                changedFiles.add(uri.toString())
+            }
+            backgroundJobManager.startImmediateFilesSyncJob(false, changedFiles.toTypedArray())
         }
     }
 

+ 17 - 15
app/src/main/java/com/nextcloud/client/jobs/FilesSyncWork.kt

@@ -119,7 +119,6 @@ class FilesSyncWork(
         }
         val resources = context.resources
         val lightVersion = resources.getBoolean(R.bool.syncedFolder_light)
-        val skipCustom = inputData.getBoolean(SKIP_CUSTOM, false)
         FilesSyncHelper.restartJobsIfNeeded(
             uploadsStorageManager,
             userAccountManager,
@@ -127,19 +126,10 @@ class FilesSyncWork(
             powerManagementService
         )
 
-        // Get changed files from ContentObserverWork or by scanning filesystem
+        // Get changed files from ContentObserverWork (only images and videos) or by scanning filesystem
         val changedFiles = inputData.getStringArray(CHANGED_FILES)
-        var useForegroundWorker = false
-        if (changedFiles != null) {
-            // TODO Handle single files
-            FilesSyncHelper.insertChangedEntries(skipCustom,syncedFolderProvider,changedFiles)
-        } else {
-            useForegroundWorker = true
-            updateForegroundWorker(5, true)
-            // Check every file in every synced folder for changes and update filesystemDataProvider database (expensive)
-            FilesSyncHelper.insertAllDBEntries(skipCustom, syncedFolderProvider)
-            updateForegroundWorker(50, true)
-        }
+        collectChangedFiles(changedFiles)
+
         // Create all the providers we'll need
         val filesystemDataProvider = FilesystemDataProvider(contentResolver)
         val currentLocale = resources.configuration.locale
@@ -151,9 +141,9 @@ class FilesSyncWork(
         for ((index, syncedFolder) in syncedFolders.withIndex()) {
             updateForegroundWorker(
                 (50 + (index.toDouble() / syncedFolders.size.toDouble()) * 50).toInt(),
-                useForegroundWorker
+                changedFiles.isNullOrEmpty()
             )
-            if (syncedFolder.isEnabled && (!skipCustom || MediaFolderType.CUSTOM != syncedFolder.type)) {
+            if (syncedFolder.isEnabled && (changedFiles.isNullOrEmpty() || MediaFolderType.CUSTOM != syncedFolder.type)) {
                 syncFolder(
                     context,
                     resources,
@@ -170,6 +160,18 @@ class FilesSyncWork(
         return result
     }
 
+    private fun collectChangedFiles(changedFiles: Array<String>?){
+        if (!changedFiles.isNullOrEmpty()) {
+            FilesSyncHelper.insertChangedEntries(syncedFolderProvider,changedFiles)
+        } else {
+            // Check every file in every synced folder for changes and update filesystemDataProvider database (expensive)
+            // Potentially needs a long time so use foreground worker
+            updateForegroundWorker(5, true)
+            FilesSyncHelper.insertAllDBEntries(syncedFolderProvider)
+            updateForegroundWorker(50, true)
+        }
+    }
+
     @Suppress("LongMethod") // legacy code
     private fun syncFolder(
         context: Context,

+ 1 - 1
app/src/main/java/com/owncloud/android/MainApp.java

@@ -556,7 +556,7 @@ public class MainApp extends MultiDexApplication implements HasAndroidInjector {
         }
 
         if (!preferences.isAutoUploadInitialized()) {
-            backgroundJobManager.startImmediateFilesSyncJob(false, false);
+            backgroundJobManager.startImmediateFilesSyncJob(false, new String[]{});
             preferences.setAutoUploadInit(true);
         }
 

+ 4 - 0
app/src/main/java/com/owncloud/android/datamodel/SyncedFolder.java

@@ -278,4 +278,8 @@ public class SyncedFolder implements Serializable, Cloneable {
     public void setExcludeHidden(boolean excludeHidden) {
         this.excludeHidden = excludeHidden;
     }
+
+    public boolean containsFile(String filePath){
+        return filePath.contains(localPath);
+    }
 }

+ 3 - 6
app/src/main/java/com/owncloud/android/ui/activity/SyncedFoldersActivity.kt

@@ -156,9 +156,6 @@ class SyncedFoldersActivity :
     @Inject
     lateinit var clock: Clock
 
-    @Inject
-    lateinit var backgroundJobManager: BackgroundJobManager
-
     @Inject
     lateinit var viewThemeUtils: ViewThemeUtils
 
@@ -584,7 +581,7 @@ class SyncedFoldersActivity :
             }
         }
         if (syncedFolderDisplayItem.isEnabled) {
-            backgroundJobManager.startImmediateFilesSyncJob(skipCustomFolders = false, overridePowerSaving = false)
+            backgroundJobManager.startImmediateFilesSyncJob(overridePowerSaving = false)
             showBatteryOptimizationInfo()
         }
     }
@@ -714,7 +711,7 @@ class SyncedFoldersActivity :
             // existing synced folder setup to be updated
             syncedFolderProvider.updateSyncFolder(item)
             if (item.isEnabled) {
-                backgroundJobManager.startImmediateFilesSyncJob(skipCustomFolders = false, overridePowerSaving = false)
+                backgroundJobManager.startImmediateFilesSyncJob(overridePowerSaving = false)
             } else {
                 val syncedFolderInitiatedKey = KEY_SYNCED_FOLDER_INITIATED_PREFIX + item.id
                 val arbitraryDataProvider =
@@ -731,7 +728,7 @@ class SyncedFoldersActivity :
         if (storedId != -1L) {
             item.id = storedId
             if (item.isEnabled) {
-                backgroundJobManager.startImmediateFilesSyncJob(skipCustomFolders = false, overridePowerSaving = false)
+                backgroundJobManager.startImmediateFilesSyncJob(overridePowerSaving = false)
             } else {
                 val syncedFolderInitiatedKey = KEY_SYNCED_FOLDER_INITIATED_PREFIX + item.id
                 arbitraryDataProvider.deleteKeyForAccount("global", syncedFolderInitiatedKey)

+ 1 - 1
app/src/main/java/com/owncloud/android/ui/activity/UploadListActivity.java

@@ -208,7 +208,7 @@ public class UploadListActivity extends FileActivity {
     }
 
     private void refresh() {
-        backgroundJobManager.startImmediateFilesSyncJob(false, true);
+        backgroundJobManager.startImmediateFilesSyncJob(true,new String[]{});
 
         if (uploadsStorageManager.getFailedUploads().length > 0) {
             new Thread(() -> {

+ 34 - 8
app/src/main/java/com/owncloud/android/utils/FilesSyncHelper.java

@@ -130,25 +130,51 @@ public final class FilesSyncHelper {
         }
     }
 
-    public static void insertAllDBEntries(boolean skipCustom,
-                                          SyncedFolderProvider syncedFolderProvider) {
+    public static void insertAllDBEntries(SyncedFolderProvider syncedFolderProvider) {
         for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
-            if (syncedFolder.isEnabled() && (!skipCustom || syncedFolder.getType() != MediaFolderType.CUSTOM)) {
+            if (syncedFolder.isEnabled()) {
                 insertAllDBEntriesForSyncedFolder(syncedFolder);
             }
         }
     }
 
-    public static void insertChangedEntries(boolean skipCustom,
-                                            SyncedFolderProvider syncedFolderProvider,
+    public static void insertChangedEntries(SyncedFolderProvider syncedFolderProvider,
                                             String[] changedFiles) {
-        for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
-            if (syncedFolder.isEnabled() && (!skipCustom || syncedFolder.getType() != MediaFolderType.CUSTOM)) {
-                insertAllDBEntriesForSyncedFolder(syncedFolder);
+        final ContentResolver contentResolver = MainApp.getAppContext().getContentResolver();
+        final FilesystemDataProvider filesystemDataProvider = new FilesystemDataProvider(contentResolver);
+        for (String changedFileURI : changedFiles){
+            String changedFile = getFileFromURI(changedFileURI);
+            for (SyncedFolder syncedFolder : syncedFolderProvider.getSyncedFolders()) {
+                if (syncedFolder.isEnabled() && syncedFolder.containsFile(changedFile)){
+                    File file = new File(changedFile);
+                    filesystemDataProvider.storeOrUpdateFileValue(changedFile,
+                                                                  file.lastModified(),file.isDirectory(),
+                                                                  syncedFolder);
+                    break;
+                }
             }
         }
     }
 
+    private static String getFileFromURI(String uri){
+        final Context context = MainApp.getAppContext();
+
+        Cursor cursor;
+        int column_index_data;
+        String filePath = null;
+
+        String[] projection = {MediaStore.MediaColumns.DATA};
+
+        cursor = context.getContentResolver().query(Uri.parse(uri), projection, null, null, null, null);
+
+        if (cursor != null && cursor.moveToFirst()) {
+            column_index_data = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
+            filePath = cursor.getString(column_index_data);
+            cursor.close();
+        }
+        return filePath;
+    }
+
     private static void insertContentIntoDB(Uri uri, SyncedFolder syncedFolder) {
         final Context context = MainApp.getAppContext();
         final ContentResolver contentResolver = context.getContentResolver();