X-Git-Url: http://git.linex4red.de/pub/Android/ownCloud.git/blobdiff_plain/92080afefcab6de830d6a5c099b04e3c3a7db47f..97dd59063ba1bf16fa2c176563614a9ce310b158:/src/com/owncloud/android/files/services/FileObserverService.java diff --git a/src/com/owncloud/android/files/services/FileObserverService.java b/src/com/owncloud/android/files/services/FileObserverService.java index 88bf0b91..cfd5fec8 100644 --- a/src/com/owncloud/android/files/services/FileObserverService.java +++ b/src/com/owncloud/android/files/services/FileObserverService.java @@ -18,15 +18,19 @@ package com.owncloud.android.files.services; +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.operations.RemoteOperationResult; +import com.owncloud.android.operations.RemoteOperationResult.ResultCode; import com.owncloud.android.ui.activity.ConflictsResolveActivity; +import com.owncloud.android.utils.FileStorageUtils; import android.accounts.Account; import android.accounts.AccountManager; @@ -43,14 +47,15 @@ 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; public final static int CMD_DEL_OBSERVED_FILE = 3; public final static int CMD_ADD_DOWNLOADING_FILE = 4; - private static String TAG = "FileObserverService"; + private static String TAG = FileObserverService.class.getSimpleName(); private static List mObservers; private static List mDownloadReceivers; private static Object mReceiverListLock = new Object(); @@ -86,13 +91,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"); @@ -144,66 +152,128 @@ 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. + * + * @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; - observer.setContext(getBaseContext()); + 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(getBaseContext()); - Account account = AccountUtils.getCurrentOwnCloudAccount(getBaseContext()); - observer.setAccount(account); - FileDataStorageManager storage = - new FileDataStorageManager(account, getContentResolver()); - observer.setStorageManager(storage); - observer.setOCFile(storage.getFileByLocalPath(path)); - 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)); + + } 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(); - return; } + 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); + 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; } } - Log.d(TAG, "Stopped watching " + path); - } - 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(); @@ -225,24 +295,21 @@ public class FileObserverService extends Service implements FileObserverStatusLi } @Override - public void OnObservedFileStatusUpdate(String localPath, String remotePath, Account account, Status status) { - switch (status) { - case CONFLICT: - { + public void onObservedFileStatusUpdate(String localPath, String remotePath, Account account, RemoteOperationResult result) { + if (!result.isSuccess()) { + if (result.getCode() == ResultCode.SYNC_CONFLICT) { + // ISSUE 5: if the user is not running the app (this is a service!), this can be very intrusive; a notification should be preferred Intent i = new Intent(getApplicationContext(), ConflictsResolveActivity.class); i.setFlags(i.getFlags() | Intent.FLAG_ACTIVITY_NEW_TASK); i.putExtra("remotepath", remotePath); i.putExtra("localpath", localPath); i.putExtra("account", account); startActivity(i); - break; + + } else { + // TODO send notification to the notification bar? } - case SENDING_TO_UPLOADER: - case INCORRECT_MASK: - break; - default: - Log.wtf(TAG, "Unhandled status " + status); - } + } // else, nothing else to do; now it's duty of FileUploader service } private class DownloadCompletedReceiver extends BroadcastReceiver { @@ -258,11 +325,15 @@ public class FileObserverService extends Service implements FileObserverStatusLi @Override public void onReceive(Context context, Intent intent) { if (mPath.equals(intent.getStringExtra(FileDownloader.EXTRA_FILE_PATH))) { - context.unregisterReceiver(this); - removeReceiverFromList(this); - mObserver.startWatching(); - Log.d(TAG, "Started watching " + mPath); - return; + if ((new File(mPath)).exists()) { + // the download could be successful, or not; in both cases, the file could be down, due to a former download or upload + context.unregisterReceiver(this); + removeReceiverFromList(this); + mObserver.startWatching(); + Log.d(TAG, "Started watching " + mPath); + return; + } // else - keep waiting for a future retry of the download ; + // mObserver.startWatching() won't ever work if the file is not in the device when it's called } }