diff --git a/AndroidManifest.xml b/AndroidManifest.xml index 8ff6870bf0..465dec84ab 100644 --- a/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -151,6 +151,7 @@ + diff --git a/owncloud-android-library b/owncloud-android-library index 974e55a2b9..09b1c3c15a 160000 --- a/owncloud-android-library +++ b/owncloud-android-library @@ -1 +1 @@ -Subproject commit 974e55a2b95c652b794111254078b806f11fcf31 +Subproject commit 09b1c3c15aa2644635796c93ee918f8b0a20ff7c diff --git a/res/values/strings.xml b/res/values/strings.xml index 2669565eeb..fba0915c87 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -245,4 +245,7 @@ do nothing you are not online for instant upload Failure Message: Please check your server configuration,maybe your quota is exceeded. + + Sorry, sharing is not enabled on your server. Please contact your administrator. + Unable to share this file or folder. Please, make sure it exists diff --git a/src/com/owncloud/android/datamodel/FileDataStorageManager.java b/src/com/owncloud/android/datamodel/FileDataStorageManager.java index 0b35beaa8a..12390c3d45 100644 --- a/src/com/owncloud/android/datamodel/FileDataStorageManager.java +++ b/src/com/owncloud/android/datamodel/FileDataStorageManager.java @@ -29,6 +29,7 @@ import com.owncloud.android.MainApp; import com.owncloud.android.db.ProviderMeta.ProviderTableMeta; import com.owncloud.android.lib.operations.common.OCShare; import com.owncloud.android.lib.operations.common.ShareType; +import com.owncloud.android.lib.utils.FileUtils; import com.owncloud.android.utils.FileStorageUtils; import com.owncloud.android.utils.Log_OC; @@ -1098,4 +1099,36 @@ public class FileDataStorageManager { } } + + + public void saveSharesDB(ArrayList shares) { + + if (shares.size() > 0) { + // Save share file + saveShares(shares); + + ArrayList sharedFiles = new ArrayList(); + + for (OCShare share : shares) { + // Get the path + String path = share.getPath(); + if (share.isDirectory()) { + path = path + FileUtils.PATH_SEPARATOR; + } + + // Update OCFile with data from share: ShareByLink żand publicLink? + OCFile file = getFileByPath(path); + if (file != null) { + if (share.getShareType().equals(ShareType.PUBLIC_LINK)) { + file.setShareByLink(true); + sharedFiles.add(file); + } + } + } + + if (sharedFiles.size() > 0) { + updateSharedFiles(sharedFiles); + } + } + } } diff --git a/src/com/owncloud/android/operations/CreateShareOperation.java b/src/com/owncloud/android/operations/CreateShareOperation.java index 1582f8f0f9..7659d16d5f 100644 --- a/src/com/owncloud/android/operations/CreateShareOperation.java +++ b/src/com/owncloud/android/operations/CreateShareOperation.java @@ -25,14 +25,18 @@ package com.owncloud.android.operations; */ import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.network.OwnCloudClient; -import com.owncloud.android.lib.operations.common.RemoteOperation; +import com.owncloud.android.lib.operations.common.OCShare; import com.owncloud.android.lib.operations.common.RemoteOperationResult; import com.owncloud.android.lib.operations.common.ShareType; import com.owncloud.android.lib.operations.remote.CreateShareRemoteOperation; +import com.owncloud.android.lib.utils.FileUtils; +import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.utils.Log_OC; + +public class CreateShareOperation extends SyncOperation { -public class CreateShareOperation extends RemoteOperation { - private static final String TAG = CreateShareOperation.class.getSimpleName(); protected FileDataStorageManager mStorageManager; @@ -43,7 +47,7 @@ public class CreateShareOperation extends RemoteOperation { private boolean mPublicUpload; private String mPassword; private int mPermissions; - + /** * Constructor * @param path Full path of the file/folder being shared. Mandatory argument @@ -79,11 +83,35 @@ public class CreateShareOperation extends RemoteOperation { RemoteOperationResult result = operation.execute(client); if (result.isSuccess()) { - // TODO - // Update DB with the response + if (result.getData().size() > 0) { + OCShare share = (OCShare) result.getData().get(0); + + // Update DB with the response + if (mPath.endsWith(FileUtils.PATH_SEPARATOR)) { + share.setPath(mPath.substring(0, mPath.length()-1)); + share.setIsDirectory(true); + + } else { + share.setPath(mPath); + share.setIsDirectory(false); + } + share.setPermissions(mPermissions); + + getStorageManager().saveShare(share); + + // Update OCFile with data from share: ShareByLink and publicLink + OCFile file = getStorageManager().getFileByPath(mPath); + if (file!=null) { + file.setPublicLink(share.getShareLink()); + getStorageManager().saveFile(file); + Log_OC.d(TAG, "Public Link = " + file.getPublicLink()); + + } + } } + return result; } diff --git a/src/com/owncloud/android/operations/GetSharesForFileOperation.java b/src/com/owncloud/android/operations/GetSharesForFileOperation.java new file mode 100644 index 0000000000..fd2dab743c --- /dev/null +++ b/src/com/owncloud/android/operations/GetSharesForFileOperation.java @@ -0,0 +1,79 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + + +package com.owncloud.android.operations; + +import java.util.ArrayList; + +import com.owncloud.android.lib.network.OwnCloudClient; +import com.owncloud.android.lib.operations.common.OCShare; +import com.owncloud.android.lib.operations.common.RemoteOperationResult; +import com.owncloud.android.lib.operations.remote.GetSharesForFileRemoteOperation; +import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.utils.Log_OC; + +/** + * Provide a list shares for a specific file. + * + * @author masensio + * + */ +public class GetSharesForFileOperation extends SyncOperation { + + private static final String TAG = GetSharesForFileOperation.class.getSimpleName(); + + private String mPath; + private boolean mReshares; + private boolean mSubfiles; + + /** + * Constructor + * + * @param path Path to file or folder + * @param reshares If set to ‘false’ (default), only shares from the current user are returned + * If set to ‘true’, all shares from the given file are returned + * @param subfiles If set to ‘false’ (default), lists only the folder being shared + * If set to ‘true’, all shared files within the folder are returned. + */ + public GetSharesForFileOperation(String path, boolean reshares, boolean subfiles) { + mPath = path; + mReshares = reshares; + mSubfiles = subfiles; + } + + @Override + protected RemoteOperationResult run(OwnCloudClient client) { + GetSharesForFileRemoteOperation operation = new GetSharesForFileRemoteOperation(mPath, mReshares, mSubfiles); + RemoteOperationResult result = operation.execute(client); + + if (result.isSuccess()) { + + // Update DB with the response + Log_OC.d(TAG, "File = " + mPath + " Share list size " + result.getData().size()); + ArrayList shares = new ArrayList(); + for(Object obj: result.getData()) { + shares.add((OCShare) obj); + } + + getStorageManager().saveSharesDB(shares); + } + + return result; + } + +} diff --git a/src/com/owncloud/android/operations/GetSharesOperation.java b/src/com/owncloud/android/operations/GetSharesOperation.java index 3b879c0651..8f7a2ae88e 100644 --- a/src/com/owncloud/android/operations/GetSharesOperation.java +++ b/src/com/owncloud/android/operations/GetSharesOperation.java @@ -19,15 +19,11 @@ package com.owncloud.android.operations; import java.util.ArrayList; -import com.owncloud.android.datamodel.FileDataStorageManager; -import com.owncloud.android.datamodel.OCFile; import com.owncloud.android.lib.network.OwnCloudClient; -import com.owncloud.android.lib.operations.common.RemoteOperation; import com.owncloud.android.lib.operations.common.RemoteOperationResult; import com.owncloud.android.lib.operations.common.OCShare; -import com.owncloud.android.lib.operations.common.ShareType; import com.owncloud.android.lib.operations.remote.GetRemoteSharesOperation; -import com.owncloud.android.lib.utils.FileUtils; +import com.owncloud.android.operations.common.SyncOperation; import com.owncloud.android.utils.Log_OC; /** @@ -35,19 +31,13 @@ import com.owncloud.android.utils.Log_OC; * Save the data in Database * * @author masensio + * @author David A. Velasco */ -public class GetSharesOperation extends RemoteOperation { +public class GetSharesOperation extends SyncOperation { private static final String TAG = GetSharesOperation.class.getSimpleName(); - protected FileDataStorageManager mStorageManager; - - - public GetSharesOperation(FileDataStorageManager storageManager) { - mStorageManager = storageManager; - } - @Override protected RemoteOperationResult run(OwnCloudClient client) { GetRemoteSharesOperation operation = new GetRemoteSharesOperation(); @@ -62,41 +52,10 @@ public class GetSharesOperation extends RemoteOperation { shares.add((OCShare) obj); } - saveSharesDB(shares); + getStorageManager().saveSharesDB(shares); } return result; } - private void saveSharesDB(ArrayList shares) { - - if (shares.size() > 0) { - // Save share file - mStorageManager.saveShares(shares); - - ArrayList sharedFiles = new ArrayList(); - - for (OCShare share : shares) { - // Get the path - String path = share.getPath(); - if (share.isDirectory()) { - path = path + FileUtils.PATH_SEPARATOR; - } - - // Update OCFile with data from share: ShareByLink żand publicLink? - OCFile file = mStorageManager.getFileByPath(path); - if (file != null) { - if (share.getShareType().equals(ShareType.PUBLIC_LINK)) { - file.setShareByLink(true); - sharedFiles.add(file); - } - } - } - - if (sharedFiles.size() > 0) { - mStorageManager.updateSharedFiles(sharedFiles); - } - } - } - } diff --git a/src/com/owncloud/android/operations/common/SyncOperation.java b/src/com/owncloud/android/operations/common/SyncOperation.java new file mode 100644 index 0000000000..7a8e356a37 --- /dev/null +++ b/src/com/owncloud/android/operations/common/SyncOperation.java @@ -0,0 +1,129 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2014 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.owncloud.android.operations.common; + +import com.owncloud.android.datamodel.FileDataStorageManager; +import com.owncloud.android.lib.network.OwnCloudClient; +import com.owncloud.android.lib.operations.common.OnRemoteOperationListener; +import com.owncloud.android.lib.operations.common.RemoteOperation; +import com.owncloud.android.lib.operations.common.RemoteOperationResult; + +import android.app.Activity; +import android.content.Context; +import android.os.Handler; + + +/** + * Operation which execution involves both interactions with an ownCloud server and + * with local data in the device. + * + * Provides methods to execute the operation both synchronously or asynchronously. + * + * @author David A. Velasco + */ +public abstract class SyncOperation extends RemoteOperation { + + //private static final String TAG = SyncOperation.class.getSimpleName(); + + private FileDataStorageManager mStorageManager; + + public FileDataStorageManager getStorageManager() { + return mStorageManager; + } + + + /** + * Synchronously executes the operation on the received ownCloud account. + * + * Do not call this method from the main thread. + * + * This method should be used whenever an ownCloud account is available, instead of {@link #execute(OwnCloudClient)}. + * + * @param account ownCloud account in remote ownCloud server to reach during the execution of the operation. + * @param context Android context for the component calling the method. + * @return Result of the operation. + */ + public RemoteOperationResult execute(FileDataStorageManager storageManager, Context context) { + if (storageManager == null) { + throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); + } + if (storageManager.getAccount() == null) { + throw new IllegalArgumentException("Trying to execute a sync operation with a storage manager for a NULL account"); + } + mStorageManager = storageManager; + return super.execute(mStorageManager.getAccount(), context); + } + + + /** + * Synchronously executes the remote operation + * + * Do not call this method from the main thread. + * + * @param client Client object to reach an ownCloud server during the execution of the operation. + * @return Result of the operation. + */ + public RemoteOperationResult execute(OwnCloudClient client, FileDataStorageManager storageManager) { + if (storageManager == null) + throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); + mStorageManager = storageManager; + return super.execute(client); + } + + + /** + * Asynchronously executes the remote operation + * + * This method should be used whenever an ownCloud account is available, instead of {@link #execute(OwnCloudClient)}. + * + * @param account ownCloud account in remote ownCloud server to reach during the execution of the operation. + * @param context Android context for the component calling the method. + * @param listener Listener to be notified about the execution of the operation. + * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called. + * @return Thread were the remote operation is executed. + */ + public Thread execute(FileDataStorageManager storageManager, Context context, OnRemoteOperationListener listener, Handler listenerHandler, Activity callerActivity) { + if (storageManager == null) { + throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); + } + if (storageManager.getAccount() == null) { + throw new IllegalArgumentException("Trying to execute a sync operation with a storage manager for a NULL account"); + } + mStorageManager = storageManager; + return super.execute(storageManager.getAccount(), context, listener, listenerHandler, callerActivity); + } + + + /** + * Asynchronously executes the remote operation + * + * @param client Client object to reach an ownCloud server during the execution of the operation. + * @param listener Listener to be notified about the execution of the operation. + * @param listenerHandler Handler associated to the thread where the methods of the listener objects must be called. + * @return Thread were the remote operation is executed. + */ + public Thread execute(OwnCloudClient client, FileDataStorageManager storageManager, OnRemoteOperationListener listener, Handler listenerHandler) { + if (storageManager == null) { + throw new IllegalArgumentException("Trying to execute a sync operation with a NULL storage manager"); + } + mStorageManager = storageManager; + return super.execute(client, listener, listenerHandler); + } + + +} diff --git a/src/com/owncloud/android/services/OperationsService.java b/src/com/owncloud/android/services/OperationsService.java new file mode 100644 index 0000000000..316657c4e7 --- /dev/null +++ b/src/com/owncloud/android/services/OperationsService.java @@ -0,0 +1,287 @@ +/* ownCloud Android client application + * Copyright (C) 2012-2013 ownCloud Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2, + * as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + */ + +package com.owncloud.android.services; + +import java.io.IOException; +import java.util.concurrent.ConcurrentLinkedQueue; + +import com.owncloud.android.datamodel.FileDataStorageManager; + +import com.owncloud.android.lib.network.OwnCloudClientFactory; +import com.owncloud.android.lib.network.OwnCloudClient; +import com.owncloud.android.operations.GetSharesOperation; +import com.owncloud.android.operations.common.SyncOperation; +import com.owncloud.android.lib.operations.common.RemoteOperation; +import com.owncloud.android.lib.operations.common.RemoteOperationResult; +import com.owncloud.android.utils.Log_OC; + +import android.accounts.Account; +import android.accounts.AccountsException; +import android.app.Service; +import android.content.Intent; +import android.net.Uri; +import android.os.Binder; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.IBinder; +import android.os.Looper; +import android.os.Message; +import android.os.Process; +import android.support.v4.content.LocalBroadcastManager; +import android.util.Pair; + +public class OperationsService extends Service { + + private static final String TAG = OperationsService.class.getSimpleName(); + + public static final String EXTRA_ACCOUNT = "ACCOUNT"; + public static final String EXTRA_SERVER_URL = "SERVER_URL"; + public static final String EXTRA_RESULT = "RESULT"; + + public static final String ACTION_OPERATION_ADDED = OperationsService.class.getName() + ".OPERATION_ADDED"; + public static final String ACTION_OPERATION_FINISHED = OperationsService.class.getName() + ".OPERATION_FINISHED"; + + private ConcurrentLinkedQueue> mPendingOperations = new ConcurrentLinkedQueue>(); + + private static class Target { + public Uri mServerUrl = null; + public Account mAccount = null; + public Target(Account account, Uri serverUrl) { + mAccount = account; + mServerUrl = serverUrl; + } + } + + private Looper mServiceLooper; + private ServiceHandler mServiceHandler; + private IBinder mBinder; + private OwnCloudClient mOwnCloudClient = null; + private Target mLastTarget = null; + private FileDataStorageManager mStorageManager; + private RemoteOperation mCurrentOperation = null; + + + /** + * Service initialization + */ + @Override + public void onCreate() { + super.onCreate(); + HandlerThread thread = new HandlerThread("Operations service thread", Process.THREAD_PRIORITY_BACKGROUND); + thread.start(); + mServiceLooper = thread.getLooper(); + mServiceHandler = new ServiceHandler(mServiceLooper, this); + mBinder = new OperationsServiceBinder(); + } + + /** + * Entry point to add a new operation to the queue of operations. + * + * New operations are added calling to startService(), resulting in a call to this method. + * This ensures the service will keep on working although the caller activity goes away. + * + * IMPORTANT: the only operations performed here right now is {@link GetSharedFilesOperation}. The class + * is taking advantage of it due to time constraints. + */ + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (!intent.hasExtra(EXTRA_ACCOUNT) && !intent.hasExtra(EXTRA_SERVER_URL)) { + Log_OC.e(TAG, "Not enough information provided in intent"); + return START_NOT_STICKY; + } + try { + Account account = intent.getParcelableExtra(EXTRA_ACCOUNT); + String serverUrl = intent.getStringExtra(EXTRA_SERVER_URL); + Target target = new Target(account, (serverUrl == null) ? null : Uri.parse(serverUrl)); + GetSharesOperation operation = new GetSharesOperation(); + mPendingOperations.add(new Pair(target, operation)); + sendBroadcastNewOperation(target, operation); + + Message msg = mServiceHandler.obtainMessage(); + msg.arg1 = startId; + mServiceHandler.sendMessage(msg); + + } catch (IllegalArgumentException e) { + Log_OC.e(TAG, "Bad information provided in intent: " + e.getMessage()); + return START_NOT_STICKY; + } + + return START_NOT_STICKY; + } + + + /** + * Provides a binder object that clients can use to perform actions on the queue of operations, + * except the addition of new operations. + */ + @Override + public IBinder onBind(Intent intent) { + return mBinder; + } + + + /** + * Called when ALL the bound clients were unbound. + */ + @Override + public boolean onUnbind(Intent intent) { + //((OperationsServiceBinder)mBinder).clearListeners(); + return false; // not accepting rebinding (default behaviour) + } + + + /** + * Binder to let client components to perform actions on the queue of operations. + * + * It provides by itself the available operations. + */ + public class OperationsServiceBinder extends Binder { + // TODO + } + + + /** + * Operations worker. Performs the pending operations in the order they were requested. + * + * Created with the Looper of a new thread, started in {@link OperationsService#onCreate()}. + */ + private static class ServiceHandler extends Handler { + // don't make it a final class, and don't remove the static ; lint will warn about a possible memory leak + OperationsService mService; + public ServiceHandler(Looper looper, OperationsService service) { + super(looper); + if (service == null) { + throw new IllegalArgumentException("Received invalid NULL in parameter 'service'"); + } + mService = service; + } + + @Override + public void handleMessage(Message msg) { + mService.nextOperation(); + mService.stopSelf(msg.arg1); + } + } + + + /** + * Performs the next operation in the queue + */ + private void nextOperation() { + + Pair next = null; + synchronized(mPendingOperations) { + next = mPendingOperations.peek(); + } + + if (next != null) { + + mCurrentOperation = next.second; + RemoteOperationResult result = null; + try { + /// prepare client object to send the request to the ownCloud server + if (mLastTarget == null || !mLastTarget.equals(next.first)) { + mLastTarget = next.first; + if (mLastTarget.mAccount != null) { + mOwnCloudClient = OwnCloudClientFactory.createOwnCloudClient(mLastTarget.mAccount, getApplicationContext()); + mStorageManager = new FileDataStorageManager(mLastTarget.mAccount, getContentResolver()); + } else { + mOwnCloudClient = OwnCloudClientFactory.createOwnCloudClient(mLastTarget.mServerUrl, getApplicationContext(), true); // this is not good enough + mStorageManager = null; + } + } + + /// perform the operation + if (mCurrentOperation instanceof SyncOperation) { + result = ((SyncOperation)mCurrentOperation).execute(mOwnCloudClient, mStorageManager); + } else { + result = mCurrentOperation.execute(mOwnCloudClient); + } + + } catch (AccountsException e) { + if (mLastTarget.mAccount == null) { + Log_OC.e(TAG, "Error while trying to get autorization for a NULL account", e); + } else { + Log_OC.e(TAG, "Error while trying to get autorization for " + mLastTarget.mAccount.name, e); + } + result = new RemoteOperationResult(e); + + } catch (IOException e) { + if (mLastTarget.mAccount == null) { + Log_OC.e(TAG, "Error while trying to get autorization for a NULL account", e); + } else { + Log_OC.e(TAG, "Error while trying to get autorization for " + mLastTarget.mAccount.name, e); + } + result = new RemoteOperationResult(e); + + } finally { + synchronized(mPendingOperations) { + mPendingOperations.poll(); + } + } + + sendBroadcastOperationFinished(mLastTarget, mCurrentOperation, result); + } + } + + + /** + * Sends a LOCAL broadcast when a new operation is added to the queue. + * + * Local broadcasts are only delivered to activities in the same process. + * + * @param target Account or URL pointing to an OC server. + * @param operation Added operation. + */ + private void sendBroadcastNewOperation(Target target, RemoteOperation operation) { + Intent intent = new Intent(ACTION_OPERATION_ADDED); + if (target.mAccount != null) { + intent.putExtra(EXTRA_ACCOUNT, target.mAccount); + } else { + intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); + } + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); + lbm.sendBroadcast(intent); + } + + + // TODO - maybe add a notification for real start of operations + + /** + * Sends a LOCAL broadcast when an operations finishes in order to the interested activities can update their view + * + * Local broadcasts are only delivered to activities in the same process. + * + * @param target Account or URL pointing to an OC server. + * @param operation Finished operation. + * @param result Result of the operation. + */ + private void sendBroadcastOperationFinished(Target target, RemoteOperation operation, RemoteOperationResult result) { + Intent intent = new Intent(ACTION_OPERATION_FINISHED); + intent.putExtra(EXTRA_RESULT, result); + if (target.mAccount != null) { + intent.putExtra(EXTRA_ACCOUNT, target.mAccount); + } else { + intent.putExtra(EXTRA_SERVER_URL, target.mServerUrl); + } + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(this); + lbm.sendBroadcast(intent); + } + + +} diff --git a/src/com/owncloud/android/ui/activity/FileActivity.java b/src/com/owncloud/android/ui/activity/FileActivity.java index 471214b25e..4f42597f3e 100644 --- a/src/com/owncloud/android/ui/activity/FileActivity.java +++ b/src/com/owncloud/android/ui/activity/FileActivity.java @@ -35,6 +35,7 @@ import android.net.Uri; import android.os.Bundle; import android.os.Parcelable; import android.webkit.MimeTypeMap; +import android.widget.Toast; import com.actionbarsherlock.app.SherlockFragmentActivity; import com.owncloud.android.MainApp; @@ -370,36 +371,47 @@ public abstract class FileActivity extends SherlockFragmentActivity { */ public void shareFileWithLink(OCFile file) { - if (file != null) { - - //CreateShareOperation createShare = new CreateShareOperation(file.getRemotePath(), ShareType.PUBLIC_LINK, "", false, "", 1); - //createShare.execute(getAccount(), this, this, mHandler, this); - - String link = "https://fake.url.lolo"; - Intent chooserIntent = null; - List targetedShareIntents = new ArrayList(); - List resInfo = getPackageManager().queryIntentActivities(createShareWithLinkIntent(link), PackageManager.MATCH_DEFAULT_ONLY); - String myPackageName = getPackageName(); - if (!resInfo.isEmpty()) { - for (ResolveInfo info : resInfo) { - if (!info.activityInfo.packageName.equalsIgnoreCase(myPackageName)) { - Intent targetedShare = createTargetedShare(link, info.activityInfo.applicationInfo.packageName, info.activityInfo.name); - targetedShareIntents.add(targetedShare); + if (isSharedSupported()) { + if (file != null) { + + // Create the Share + //CreateShareOperation createShare = new CreateShareOperation(file.getRemotePath(), ShareType.PUBLIC_LINK, "", false, "", 1); + //createShare.execute(getStorageManager(), this, this, mHandler, this); + + // TODO + // Get the link --> when the operation is finished + + String link = "https://fake.url.lolo"; + Intent chooserIntent = null; + List targetedShareIntents = new ArrayList(); + List resInfo = getPackageManager().queryIntentActivities(createShareWithLinkIntent(link), PackageManager.MATCH_DEFAULT_ONLY); + String myPackageName = getPackageName(); + if (!resInfo.isEmpty()) { + for (ResolveInfo info : resInfo) { + if (!info.activityInfo.packageName.equalsIgnoreCase(myPackageName)) { + Intent targetedShare = createTargetedShare(link, info.activityInfo.applicationInfo.packageName, info.activityInfo.name); + targetedShareIntents.add(targetedShare); + } } } - } - if (targetedShareIntents.size() > 0) { - Intent firstTargeted = targetedShareIntents.remove(0); - chooserIntent = Intent.createChooser(firstTargeted, getString(R.string.action_share_file)); - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[] {})); + if (targetedShareIntents.size() > 0) { + Intent firstTargeted = targetedShareIntents.remove(0); + chooserIntent = Intent.createChooser(firstTargeted, getString(R.string.action_share_file)); + chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, targetedShareIntents.toArray(new Parcelable[] {})); + } else { + // to show standard message + chooserIntent = Intent.createChooser(null, getString(R.string.action_share_file)); + } + startActivity(chooserIntent); + } else { - // to show standard message - chooserIntent = Intent.createChooser(null, getString(R.string.action_share_file)); + Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); } - startActivity(chooserIntent); } else { - Log_OC.wtf(TAG, "Trying to open a NULL OCFile"); + // Show a Message + Toast t = Toast.makeText(this, getString(R.string.share_link_no_support_share_api), Toast.LENGTH_LONG); + t.show(); } } diff --git a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java index f684b790ff..237113d8ff 100644 --- a/src/com/owncloud/android/ui/activity/FileDisplayActivity.java +++ b/src/com/owncloud/android/ui/activity/FileDisplayActivity.java @@ -45,6 +45,7 @@ import android.provider.MediaStore; import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentTransaction; +import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.view.View; import android.view.ViewGroup; @@ -69,17 +70,16 @@ import com.owncloud.android.files.services.FileDownloader.FileDownloaderBinder; import com.owncloud.android.files.services.FileUploader.FileUploaderBinder; import com.owncloud.android.operations.CreateFolderOperation; -import com.owncloud.android.operations.GetSharesOperation; - import com.owncloud.android.lib.operations.common.OnRemoteOperationListener; import com.owncloud.android.lib.operations.common.RemoteOperation; import com.owncloud.android.lib.operations.common.RemoteOperationResult; import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode; - +import com.owncloud.android.operations.CreateShareOperation; import com.owncloud.android.operations.RemoveFileOperation; import com.owncloud.android.operations.RenameFileOperation; import com.owncloud.android.operations.SynchronizeFileOperation; import com.owncloud.android.operations.SynchronizeFolderOperation; +import com.owncloud.android.services.OperationsService; import com.owncloud.android.syncadapter.FileSyncService; import com.owncloud.android.ui.dialog.EditNameDialog; import com.owncloud.android.ui.dialog.EditNameDialog.EditNameDialogListener; @@ -114,6 +114,7 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa private SyncBroadcastReceiver mSyncBroadcastReceiver; private UploadFinishReceiver mUploadFinishReceiver; private DownloadFinishReceiver mDownloadFinishReceiver; + private OperationsServiceReceiver mOperationsServiceReceiver; private FileDownloaderBinder mDownloaderBinder = null; private FileUploaderBinder mUploaderBinder = null; private ServiceConnection mDownloadConnection = null, mUploadConnection = null; @@ -703,6 +704,12 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa downloadIntentFilter.addAction(FileDownloader.getDownloadFinishMessage()); mDownloadFinishReceiver = new DownloadFinishReceiver(); registerReceiver(mDownloadFinishReceiver, downloadIntentFilter); + + // Listen for messages from the OperationsService + IntentFilter operationsIntentFilter = new IntentFilter(OperationsService.ACTION_OPERATION_ADDED); + operationsIntentFilter.addAction(OperationsService.ACTION_OPERATION_FINISHED); + mOperationsServiceReceiver = new OperationsServiceReceiver(); + LocalBroadcastManager.getInstance(this).registerReceiver(mOperationsServiceReceiver, operationsIntentFilter); Log_OC.d(TAG, "onResume() end"); } @@ -724,7 +731,10 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa unregisterReceiver(mDownloadFinishReceiver); mDownloadFinishReceiver = null; } - + if (mOperationsServiceReceiver != null) { + LocalBroadcastManager.getInstance(this).unregisterReceiver(mOperationsServiceReceiver); + mOperationsServiceReceiver = null; + } Log_OC.d(TAG, "onPause() end"); } @@ -1031,6 +1041,45 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa return (accountName != null && getAccount() != null && accountName.equals(getAccount().name)); } } + + + /** + * Class waiting for broadcast events from the {@link OperationsService}. + * + * Updates the list of files when a get for shares is finished; at this moment the refresh of shares is the only + * operation performed in {@link OperationsService}. + * + * In the future will handle the progress or finalization of all the operations performed in {@link OperationsService}, + * probably all the operations associated to the app model. + */ + private class OperationsServiceReceiver extends BroadcastReceiver { + + @Override + public void onReceive(Context context, Intent intent) { + if (OperationsService.ACTION_OPERATION_ADDED.equals(intent.getAction())) { + + } else if (OperationsService.ACTION_OPERATION_FINISHED.equals(intent.getAction())) { + mRefreshSharesInProgress = false; + + Account account = intent.getParcelableExtra(OperationsService.EXTRA_ACCOUNT); + RemoteOperationResult getSharesResult = (RemoteOperationResult)intent.getSerializableExtra(OperationsService.EXTRA_RESULT); + if (getAccount() != null && account.name.equals(getAccount().name) + && mStorageManager != null + ) { + refeshListOfFilesFragment(); + } + if ((getSharesResult != null) && + RemoteOperationResult.ResultCode.SSL_RECOVERABLE_PEER_UNVERIFIED.equals(getSharesResult.getCode())) { + mLastSslUntrustedServerResult = getSharesResult; + showDialog(DIALOG_SSL_VALIDATOR); + } + + setSupportProgressBarIndeterminateVisibility(mRefreshSharesInProgress || mSyncInProgress); + } + + } + + } /** @@ -1295,27 +1344,23 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa } else if (operation instanceof CreateFolderOperation) { onCreateFolderOperationFinish((CreateFolderOperation)operation, result); - - } else if (operation instanceof GetSharesOperation) { - onGetSharesOperationFinish((GetSharesOperation) operation, result); + + } else if (operation instanceof CreateShareOperation) { + onCreateShareOperation((CreateShareOperation) operation, result); } + } - /** Updates the data about shared files - * - * @param operation Get Shared Files - * @param result Result of the operation - */ - private void onGetSharesOperationFinish(GetSharesOperation operation, RemoteOperationResult result) { - // Refresh the filelist with the information - refeshListOfFilesFragment(); - - mRefreshSharesInProgress = false; - - if (!mSyncInProgress) { - setSupportProgressBarIndeterminateVisibility(false); + private void onCreateShareOperation(CreateShareOperation operation, RemoteOperationResult result) { + if (result.getCode() == ResultCode.FILE_NOT_FOUND) { + // Show a Message + Toast t = Toast.makeText(this, getString(R.string.share_link_file_no_exist), Toast.LENGTH_LONG); + t.show(); } + + refeshListOfFilesFragment(); + } /** @@ -1529,23 +1574,13 @@ OCFileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNa private void startGetShares() { // Get shared files/folders - RemoteOperation getShares = new GetSharesOperation(mStorageManager); - getShares.execute(getAccount(), this, this, mHandler, this); + Intent intent = new Intent(this, OperationsService.class); + intent.putExtra(OperationsService.EXTRA_ACCOUNT, getAccount()); + startService(intent); mRefreshSharesInProgress = true; setSupportProgressBarIndeterminateVisibility(true); } -// public void enableDisableViewGroup(ViewGroup viewGroup, boolean enabled) { -// int childCount = viewGroup.getChildCount(); -// for (int i = 0; i < childCount; i++) { -// View view = viewGroup.getChildAt(i); -// view.setEnabled(enabled); -// view.setClickable(!enabled); -// if (view instanceof ViewGroup) { -// enableDisableViewGroup((ViewGroup) view, enabled); -// } -// } -// } } diff --git a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java index eebbef8d6b..0eacfe4403 100644 --- a/src/com/owncloud/android/ui/fragment/FileDetailFragment.java +++ b/src/com/owncloud/android/ui/fragment/FileDetailFragment.java @@ -55,9 +55,6 @@ import com.owncloud.android.lib.operations.common.OnRemoteOperationListener; import com.owncloud.android.lib.operations.common.RemoteOperation; import com.owncloud.android.lib.operations.common.RemoteOperationResult; import com.owncloud.android.lib.operations.common.RemoteOperationResult.ResultCode; -import com.owncloud.android.lib.operations.common.ShareType; -import com.owncloud.android.lib.operations.remote.CreateShareRemoteOperation; -import com.owncloud.android.operations.CreateShareOperation; import com.owncloud.android.operations.RemoveFileOperation; import com.owncloud.android.operations.RenameFileOperation; import com.owncloud.android.operations.SynchronizeFileOperation;