Browse Source

Fixed lack of observance for files that are set as favourites when never were download before

David A. Velasco 12 years ago
parent
commit
bd38627e14

+ 1 - 1
src/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -123,7 +123,7 @@ public class FileDataStorageManager implements DataStorageManager {
 
         if (fileExists(file.getRemotePath())) {
             OCFile oldFile = getFileByPath(file.getRemotePath());
-            if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
+            if (file.getStoragePath() == null && oldFile.isDown())
                 file.setStoragePath(oldFile.getStoragePath());
             if (!file.isDirectory());
                 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());

+ 8 - 0
src/com/owncloud/android/files/OwnCloudFileObserver.java

@@ -136,5 +136,13 @@ public class OwnCloudFileObserver extends FileObserver {
                                                Account account,
                                                FileObserverStatusListener.Status status);
     }
+
+    public OCFile getOCFile() {
+        return mFile;
+    }
+
+    public Account getAccount() {
+        return mOCAccount;
+    }
     
 }

+ 112 - 35
src/com/owncloud/android/files/services/FileObserverService.java

@@ -22,12 +22,13 @@ import java.io.File;
 import java.util.ArrayList;
 import java.util.List;
 
-import com.owncloud.android.AccountUtils;
 import com.owncloud.android.datamodel.FileDataStorageManager;
+import com.owncloud.android.datamodel.OCFile;
 import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
 import com.owncloud.android.files.OwnCloudFileObserver;
 import com.owncloud.android.files.OwnCloudFileObserver.FileObserverStatusListener;
 import com.owncloud.android.ui.activity.ConflictsResolveActivity;
+import com.owncloud.android.utils.FileStorageUtils;
 
 import android.accounts.Account;
 import android.accounts.AccountManager;
@@ -44,7 +45,8 @@ import android.util.Log;
 public class FileObserverService extends Service implements FileObserverStatusListener {
 
     public final static String KEY_FILE_CMD = "KEY_FILE_CMD";
-    public final static String KEY_CMD_ARG = "KEY_CMD_ARG";
+    public final static String KEY_CMD_ARG_FILE = "KEY_CMD_ARG_FILE";
+    public final static String KEY_CMD_ARG_ACCOUNT = "KEY_CMD_ARG_ACCOUNT";
 
     public final static int CMD_INIT_OBSERVED_LIST = 1;
     public final static int CMD_ADD_OBSERVED_FILE = 2;
@@ -87,13 +89,16 @@ public class FileObserverService extends Service implements FileObserverStatusLi
                 initializeObservedList();
                 break;
             case CMD_ADD_OBSERVED_FILE:
-                addObservedFile(intent.getStringExtra(KEY_CMD_ARG));
+                addObservedFile( (OCFile)intent.getParcelableExtra(KEY_CMD_ARG_FILE), 
+                                 (Account)intent.getParcelableExtra(KEY_CMD_ARG_ACCOUNT));
                 break;
             case CMD_DEL_OBSERVED_FILE:
-                removeObservedFile(intent.getStringExtra(KEY_CMD_ARG));
+                removeObservedFile( (OCFile)intent.getParcelableExtra(KEY_CMD_ARG_FILE), 
+                                    (Account)intent.getParcelableExtra(KEY_CMD_ARG_ACCOUNT));
                 break;
             case CMD_ADD_DOWNLOADING_FILE:
-                addDownloadingFile(intent.getStringExtra(KEY_CMD_ARG));
+                addDownloadingFile( (OCFile)intent.getParcelableExtra(KEY_CMD_ARG_FILE),
+                                    (Account)intent.getParcelableExtra(KEY_CMD_ARG_ACCOUNT));
                 break;
             default:
                 Log.wtf(TAG, "Incorrect key given");
@@ -145,65 +150,137 @@ public class FileObserverService extends Service implements FileObserverStatusLi
         c.close();
     }
     
-    private void addObservedFile(String path) {
-        if (path == null) return;
+    /**
+     * Registers the local copy of a remote file to be observed for local changes,
+     * an automatically updated in the ownCloud server.
+     *
+     * If there is no local copy of the remote file, a request to download it is send
+     * to the FileDownloader service. The observation is delayed until the download
+     * is finished.
+     * 
+     * @param file      Object representing a remote file which local copy must be observed.
+     * @param account   OwnCloud account containing file.
+     */
+    private void addObservedFile(OCFile file, Account account) {
+        if (file == null) {
+            Log.e(TAG, "Trying to observe a NULL file");
+            return;
+        }
         if (mObservers == null) {
             // this is very rare case when service was killed by system
             // and observers list was deleted in that procedure
             initializeObservedList();
         }
-        boolean duplicate = false;
-        OwnCloudFileObserver observer = null;
+        String localPath = file.getStoragePath();
+        if (!file.isDown()) {
+            // this is a file downloading / to be download for the first time
+            localPath = FileStorageUtils.getDefaultSavePathFor(account.name, file);
+        }
+        OwnCloudFileObserver tmpObserver = null, observer = null;
         for (int i = 0; i < mObservers.size(); ++i) {
-            observer = mObservers.get(i);
-            if (observer.getPath().equals(path))
-                duplicate = true;
+            tmpObserver = mObservers.get(i);
+            if (tmpObserver.getPath().equals(localPath)) {
+                observer = tmpObserver;
+            }
+            tmpObserver.setContext(getApplicationContext());   // 'refreshing' context to all the observers? why?
+        }
+        if (observer == null) {
+            /// the local file was never registered to observe before
+            observer = new OwnCloudFileObserver(localPath, OwnCloudFileObserver.CHANGES_ONLY);
+            //Account account = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext());
+            observer.setAccount(account);
+            FileDataStorageManager storage =
+                    new FileDataStorageManager(account, getContentResolver());  // I don't trust in this resolver's life span...
+            observer.setStorageManager(storage);
+            //observer.setOCFile(storage.getFileByLocalPath(path));   // ISSUE 10 - the fix in FileDetailsFragment to avoid path == null was not enough; it the file was never down before, this sets a NULL OCFile in the observer
+            observer.setOCFile(file);
+            observer.addObserverStatusListener(this);
             observer.setContext(getApplicationContext());
+            
+        } else {
+            /* LET'S IGNORE THAT, CURRENTLY, A LOCAL FILE CAN BE LINKED TO DIFFERENT FILES IN OWNCLOUD;
+             * we should change that
+             * 
+            /// the local file is already observed for some other OCFile(s)
+            observer.addOCFile(account, file);  // OCFiles should have a reference to the account containing them to not be confused
+            */ 
         }
-        if (duplicate) return;
-        observer = new OwnCloudFileObserver(path, OwnCloudFileObserver.CHANGES_ONLY);
-        observer.setContext(getApplicationContext());
-        Account account = AccountUtils.getCurrentOwnCloudAccount(getApplicationContext());
-        observer.setAccount(account);
-        FileDataStorageManager storage =
-                new FileDataStorageManager(account, getContentResolver());
-        observer.setStorageManager(storage);
-        observer.setOCFile(storage.getFileByLocalPath(path));   // ISSUE 10 - the fix in FileDetailsFragment to avoid path == null was not enough; it the file was never down before, this sets a NULL OCFile in the observer 
-        observer.addObserverStatusListener(this);
-
-        DownloadCompletedReceiver receiver = new DownloadCompletedReceiver(path, observer);
-        registerReceiver(receiver, new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE));
 
         mObservers.add(observer);
-        Log.d(TAG, "Observer added for path " + path);
+        Log.d(TAG, "Observer added for path " + localPath);
+        
+        if (!file.isDown()) {
+            // if the file is not down, it can't be observed for changes
+            DownloadCompletedReceiver receiver = new DownloadCompletedReceiver(localPath, observer);
+            registerReceiver(receiver, new IntentFilter(FileDownloader.DOWNLOAD_FINISH_MESSAGE));
+
+            Intent i = new Intent(this, FileDownloader.class);
+            i.putExtra(FileDownloader.EXTRA_ACCOUNT, account);
+            i.putExtra(FileDownloader.EXTRA_FILE, file);
+            startService(i);
+            
+        } else {
+            observer.startWatching();
+            Log.d(TAG, "Started watching " + localPath);
+            
+        }
+        
     }
+
     
-    private void removeObservedFile(String path) {
-        if (path == null) return;
+    /**
+     * Unregisters the local copy of a remote file to be observed for local changes.
+     *
+     * @param file      Object representing a remote file which local copy must be not observed longer.
+     * @param account   OwnCloud account containing file.
+     */
+    private void removeObservedFile(OCFile file, Account account) {
+        if (file == null) {
+            Log.e(TAG, "Trying to unobserve a NULL file");
+            return;
+        }
         if (mObservers == null) {
             initializeObservedList();
         }
+        String localPath = file.getStoragePath();
+        if (!file.isDown()) {
+            // this happens when a file not in the device is set to be kept synchronized, and quickly unset again,
+            // while the download is not finished
+            localPath = FileStorageUtils.getDefaultSavePathFor(account.name, file);
+        }
+        
         for (int i = 0; i < mObservers.size(); ++i) {
             OwnCloudFileObserver observer = mObservers.get(i);
-            if (observer.getPath().equals(path)) {
+            if (observer.getPath().equals(localPath)) {
                 observer.stopWatching();
-                mObservers.remove(i);
-                Log.d(TAG, "Stopped watching " + path);
+                mObservers.remove(i);       // assuming, again, that a local file can be only linked to only ONE remote file; currently false
+                if (!file.isDown()) {
+                    // TODO unregister download receiver ;forget this until list of receivers is replaced for a single receiver
+                }
+                Log.d(TAG, "Stopped watching " + localPath);
                 break;
             }
         }
-    }
         
-    private void addDownloadingFile(String remotePath) {
+    }
+
+    
+    /**
+     * Temporarily disables the observance of a file that is going to be download.
+     *
+     * @param file      Object representing the remote file which local copy must not be observed temporarily.
+     * @param account   OwnCloud account containing file.
+     */
+    private void addDownloadingFile(OCFile file, Account account) {
         OwnCloudFileObserver observer = null;
         for (OwnCloudFileObserver o : mObservers) {
-            if (o.getRemotePath().equals(remotePath)) {
+            if (o.getRemotePath().equals(file.getRemotePath()) && o.getAccount().equals(account)) {
                 observer = o;
                 break;
             }
         }
         if (observer == null) {
-            Log.e(TAG, "Couldn't find observer for remote file " + remotePath);
+            Log.e(TAG, "Couldn't find observer for remote file " + file.getRemotePath());
             return;
         }
         observer.stopWatching();

+ 2 - 1
src/com/owncloud/android/operations/SynchronizeFolderOperation.java

@@ -213,7 +213,8 @@ public class SynchronizeFolderOperation extends RemoteOperation {
         Log.d(TAG, "Disabling observation of remote file" + file.getRemotePath());
         Intent intent = new Intent(mContext, FileObserverService.class);
         intent.putExtra(FileObserverService.KEY_FILE_CMD, FileObserverService.CMD_ADD_DOWNLOADING_FILE);
-        intent.putExtra(FileObserverService.KEY_CMD_ARG, file.getRemotePath());
+        intent.putExtra(FileObserverService.KEY_CMD_ARG_FILE, file);
+        intent.putExtra(FileObserverService.KEY_CMD_ARG_ACCOUNT, mAccount);
         mContext.startService(intent);
         
     }

+ 15 - 8
src/com/owncloud/android/ui/fragment/FileDetailFragment.java

@@ -87,7 +87,6 @@ import com.owncloud.android.ui.activity.FileDisplayActivity;
 import com.owncloud.android.ui.activity.TransferServiceGetter;
 import com.owncloud.android.ui.dialog.EditNameDialog;
 import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener;
-import com.owncloud.android.utils.FileStorageUtils;
 import com.owncloud.android.utils.OwnCloudVersion;
 
 import com.owncloud.android.R;
@@ -311,26 +310,34 @@ public class FileDetailFragment extends SherlockFragment implements
                 mFile.setKeepInSync(cb.isChecked());
                 FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());
                 fdsm.saveFile(mFile);
-                if (mFile.keepInSync()) {
+                
+                /* NOT HERE
+                 * now that FileObserverService is involved, the easiest way to coordinate it with the download service
+                 * in every possible case is let the FileObserverService decide if the download should be started at
+                 * this moment or not
+                 * 
+                 * see changes at FileObserverService#addObservedFile
+                 
+                   if (mFile.keepInSync()) {
                     onClick(getView().findViewById(R.id.fdDownloadBtn));
                 } else {
                     mContainerActivity.onFileStateChanged();    // put inside 'else' to not call it twice (here, and in the virtual click on fdDownloadBtn)
-                }
+                }*/
                 
+                /// register the OCFile instance in the observer service to monitor local updates;
+                /// if necessary, the file is download 
                 Intent intent = new Intent(getActivity().getApplicationContext(),
                                            FileObserverService.class);
                 intent.putExtra(FileObserverService.KEY_FILE_CMD,
                            (cb.isChecked()?
                                    FileObserverService.CMD_ADD_OBSERVED_FILE:
                                    FileObserverService.CMD_DEL_OBSERVED_FILE));
-                String localPath = mFile.getStoragePath();
-                if (localPath == null || localPath.length() <= 0) {
-                    localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, mFile);
-                }
-                intent.putExtra(FileObserverService.KEY_CMD_ARG, localPath);
+                intent.putExtra(FileObserverService.KEY_CMD_ARG_FILE, mFile);
+                intent.putExtra(FileObserverService.KEY_CMD_ARG_ACCOUNT, mAccount);
                 Log.e(TAG, "starting observer service");
                 getActivity().startService(intent);
                 
+                mContainerActivity.onFileStateChanged();                
                 break;
             }
             case R.id.fdRenameBtn: {