Bläddra i källkod

Merge branch 'stable'

masensio 9 år sedan
förälder
incheckning
d0b5d397c4

+ 2 - 5
AndroidManifest.xml

@@ -19,8 +19,8 @@
 -->
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.owncloud.android"
-    android:versionCode="10800000"
-    android:versionName="1.8.0" >
+    android:versionCode="10900000"
+    android:versionName="1.9.0" >
 
     <uses-sdk
         android:minSdkVersion="14"
@@ -41,9 +41,6 @@
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 
-    <android:uses-permission android:name="android.permission.READ_PHONE_STATE" />
-    <android:uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
-
     <application
         android:name=".MainApp"
         android:icon="@drawable/icon"

+ 2 - 2
oc_jb_workaround/AndroidManifest.xml

@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     package="com.owncloud.android.workaround.accounts"
-    android:versionCode="0100025"
-    android:versionName="1.0.25" >
+    android:versionCode="0100026"
+    android:versionName="1.0.26" >
 
     <uses-sdk
         android:minSdkVersion="16"

+ 23 - 8
src/com/owncloud/android/datamodel/FileDataStorageManager.java

@@ -1735,18 +1735,33 @@ public class FileDataStorageManager {
                 Log_OC.d(TAG, "checking parents to remove conflict; STARTING with " + parentPath);
                 while (parentPath.length() > 0) {
 
-                    String where =
+                    String whereForDescencentsInConflict =
                             ProviderTableMeta.FILE_ETAG_IN_CONFLICT + " IS NOT NULL AND " +
                                     ProviderTableMeta.FILE_CONTENT_TYPE + " != 'DIR' AND " +
                                     ProviderTableMeta.FILE_ACCOUNT_OWNER + " = ? AND " +
                                     ProviderTableMeta.FILE_PATH + " LIKE ?";
-                    Cursor descendentsInConflict = getContentResolver().query(
-                            ProviderTableMeta.CONTENT_URI_FILE,
-                            new String[]{ProviderTableMeta._ID},
-                            where,
-                            new String[]{mAccount.name, parentPath + "%"},
-                            null
-                    );
+                    Cursor descendentsInConflict = null;
+                    if (getContentResolver() != null) {
+                        descendentsInConflict = getContentResolver().query(
+                                ProviderTableMeta.CONTENT_URI_FILE,
+                                new String[]{ProviderTableMeta._ID},
+                                whereForDescencentsInConflict,
+                                new String[]{mAccount.name, parentPath + "%"},
+                                null
+                        );
+                    } else {
+                        try {
+                            descendentsInConflict = getContentProviderClient().query(
+                                    ProviderTableMeta.CONTENT_URI_FILE,
+                                    new String[]{ProviderTableMeta._ID},
+                                    whereForDescencentsInConflict,
+                                    new String[]{mAccount.name, parentPath + "%"},
+                                    null
+                            );
+                        } catch (RemoteException e) {
+                            Log_OC.e(TAG, "Failed querying for descendents in conflict " + e.getMessage());
+                        }
+                    }
                     if (descendentsInConflict == null || descendentsInConflict.getCount() == 0) {
                         Log_OC.d(TAG, "NO MORE conflicts in " + parentPath);
                         if (getContentResolver() != null) {

+ 8 - 1
src/com/owncloud/android/datamodel/ThumbnailsCacheManager.java

@@ -278,12 +278,13 @@ public class ThumbnailsCacheManager {
                     OwnCloudVersion serverOCVersion = AccountUtils.getServerVersion(mAccount);
                     if (mClient != null && serverOCVersion != null) {
                         if (serverOCVersion.supportsRemoteThumbnails()) {
+                            GetMethod get = null;
                             try {
                                 String uri = mClient.getBaseUri() + "" +
                                         "/index.php/apps/files/api/v1/thumbnail/" +
                                         px + "/" + px + Uri.encode(file.getRemotePath(), "/");
                                 Log_OC.d("Thumbnail", "URI: " + uri);
-                                GetMethod get = new GetMethod(uri);
+                                get = new GetMethod(uri);
                                 int status = mClient.executeMethod(get);
                                 if (status == HttpStatus.SC_OK) {
                                     InputStream inputStream = get.getResponseBodyAsStream();
@@ -299,9 +300,15 @@ public class ThumbnailsCacheManager {
                                     if (thumbnail != null) {
                                         addBitmapToCache(imageKey, thumbnail);
                                     }
+                                } else {
+                                    mClient.exhaustResponse(get.getResponseBodyAsStream());
                                 }
                             } catch (Exception e) {
                                 e.printStackTrace();
+                            } finally {
+                                if (get != null) {
+                                    get.releaseConnection();
+                                }
                             }
                         } else {
                             Log_OC.d(TAG, "Server too old");

+ 5 - 4
src/com/owncloud/android/files/services/FileDownloader.java

@@ -174,10 +174,11 @@ public class FileDownloader extends Service
                 Pair<String, String> putResult = mPendingDownloads.putIfAbsent(
                         account, file.getRemotePath(), newDownload
                 );
-                String downloadKey = putResult.first;
-                requestedDownloads.add(downloadKey);
-
-                sendBroadcastNewDownload(newDownload, putResult.second);
+                if (putResult != null) {
+                    String downloadKey = putResult.first;
+                    requestedDownloads.add(downloadKey);
+                    sendBroadcastNewDownload(newDownload, putResult.second);
+                }   // else, file already in the queue of downloads; don't repeat the request
 
             } catch (IllegalArgumentException e) {
                 Log_OC.e(TAG, "Not enough information provided in intent: " + e.getMessage());

+ 4 - 2
src/com/owncloud/android/files/services/FileUploader.java

@@ -299,8 +299,10 @@ public class FileUploader extends Service
                 Pair<String, String> putResult = mPendingUploads.putIfAbsent(
                         account, files[i].getRemotePath(), newUpload
                 );
-                uploadKey = putResult.first;
-                requestedUploads.add(uploadKey);
+                if (putResult != null) {
+                    uploadKey = putResult.first;
+                    requestedUploads.add(uploadKey);
+                }   // else, file already in the queue of uploads; don't repeat the request
             }
 
         } catch (IllegalArgumentException e) {

+ 33 - 26
src/com/owncloud/android/files/services/IndexedForest.java

@@ -101,38 +101,45 @@ public class IndexedForest<V> {
     public /* synchronized */ Pair<String, String> putIfAbsent(Account account, String remotePath, V value) {
         String targetKey = buildKey(account, remotePath);
         Node<V> valuedNode = new Node(targetKey, value);
-        mMap.putIfAbsent(
-                targetKey,
-                valuedNode
+        Node<V> previousValue = mMap.putIfAbsent(
+            targetKey,
+            valuedNode
         );
+        if (previousValue != null) {
+            // remotePath already known; not replaced
+            return null;
 
-        String currentPath = remotePath, parentPath = null, parentKey = null;
-        Node<V> currentNode = valuedNode, parentNode = null;
-        boolean linked = false;
-        while (!OCFile.ROOT_PATH.equals(currentPath) && !linked) {
-            parentPath = new File(currentPath).getParent();
-            if (!parentPath.endsWith(OCFile.PATH_SEPARATOR)) {
-                parentPath += OCFile.PATH_SEPARATOR;
+        } else {
+            // value really added
+            String currentPath = remotePath, parentPath = null, parentKey = null;
+            Node<V> currentNode = valuedNode, parentNode = null;
+            boolean linked = false;
+            while (!OCFile.ROOT_PATH.equals(currentPath) && !linked) {
+                parentPath = new File(currentPath).getParent();
+                if (!parentPath.endsWith(OCFile.PATH_SEPARATOR)) {
+                    parentPath += OCFile.PATH_SEPARATOR;
+                }
+                parentKey = buildKey(account, parentPath);
+                parentNode = mMap.get(parentKey);
+                if (parentNode == null) {
+                    parentNode = new Node(parentKey, null);
+                    parentNode.addChild(currentNode);
+                    mMap.put(parentKey, parentNode);
+                } else {
+                    parentNode.addChild(currentNode);
+                    linked = true;
+                }
+                currentPath = parentPath;
+                currentNode = parentNode;
             }
-            parentKey = buildKey(account, parentPath);
-            parentNode = mMap.get(parentKey);
-            if (parentNode == null) {
-                parentNode = new Node(parentKey, null);
-                parentNode.addChild(currentNode);
-                mMap.put(parentKey, parentNode);
-            } else {
-                parentNode.addChild(currentNode);
-                linked = true;
+
+            String linkedTo = OCFile.ROOT_PATH;
+            if (linked) {
+                linkedTo = parentNode.getKey().substring(account.name.length());
             }
-            currentPath = parentPath;
-            currentNode = parentNode;
-        }
 
-        String linkedTo = OCFile.ROOT_PATH;
-        if (linked) {
-            linkedTo = parentNode.getKey().substring(account.name.length());
+            return new Pair<String, String>(targetKey, linkedTo);
         }
-        return new Pair<String, String>(targetKey, linkedTo);
     };
 
 

+ 9 - 11
src/com/owncloud/android/operations/CreateShareViaLinkOperation.java

@@ -41,8 +41,6 @@ import com.owncloud.android.lib.resources.shares.OCShare;
 import com.owncloud.android.lib.resources.shares.ShareType;
 import com.owncloud.android.operations.common.SyncOperation;
 
-import java.util.ArrayList;
-
 public class CreateShareViaLinkOperation extends SyncOperation {
 
     private String mPath;
@@ -76,19 +74,19 @@ public class CreateShareViaLinkOperation extends SyncOperation {
         RemoteOperation operation = new GetRemoteSharesForFileOperation(mPath, false, false);
         RemoteOperationResult result = operation.execute(client);
 
-        boolean shareByLink = false;
-        // Check if the file is shared by link
-        if (result.isSuccess() && result.getData().size() > 0){
-            ArrayList<Object> shares = result.getData();
-            for(Object object: shares){
-                if (((OCShare) object).getShareType() == ShareType.PUBLIC_LINK){
-                    shareByLink = true;
+        // Create public link if doesn't exist yet
+        boolean publicShareExists = false;
+        if (result.isSuccess()) {
+            OCShare share = null;
+            for (int i=0 ; i<result.getData().size(); i++) {
+                share = (OCShare) result.getData().get(i);
+                if (ShareType.PUBLIC_LINK.equals(share.getShareType())) {
+                    publicShareExists = true;
                     break;
                 }
             }
         }
-
-        if (!result.isSuccess() || !shareByLink) {
+        if (!publicShareExists) {
             CreateRemoteShareOperation createOp = new CreateRemoteShareOperation(
                     mPath,
                     ShareType.PUBLIC_LINK,

+ 32 - 0
src/com/owncloud/android/providers/UsersAndGroupsSearchProvider.java

@@ -29,14 +29,18 @@ import android.content.UriMatcher;
 import android.database.Cursor;
 import android.database.MatrixCursor;
 import android.net.Uri;
+import android.os.Handler;
+import android.os.Looper;
 import android.provider.BaseColumns;
 import android.support.annotation.Nullable;
+import android.widget.Toast;
 
 import com.owncloud.android.R;
 import com.owncloud.android.authentication.AccountUtils;
 import com.owncloud.android.lib.common.operations.RemoteOperationResult;
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.resources.shares.GetRemoteShareesOperation;
+import com.owncloud.android.utils.ErrorMessageAdapter;
 
 import org.json.JSONException;
 import org.json.JSONObject;
@@ -136,6 +140,8 @@ public class UsersAndGroupsSearchProvider extends ContentProvider {
                 // Get JSonObjects from response
                 names.add((JSONObject) o);
             }
+        } else {
+            showErrorMessage(result);
         }
 
         /// convert the responses from the OC server to the expected format
@@ -194,4 +200,30 @@ public class UsersAndGroupsSearchProvider extends ContentProvider {
         return 0;
     }
 
+    /**
+     * Show error message
+     *
+     * @param result    Result with the failure information.
+     */
+    public void showErrorMessage(final RemoteOperationResult result) {
+        Handler handler = new Handler(Looper.getMainLooper());
+        handler.post(new Runnable() {
+            @Override
+            public void run() {
+                // The Toast must be shown in the main thread to grant that will be hidden correctly; otherwise
+                // the thread may die before, an exception will occur, and the message will be left on the screen
+                // until the app dies
+                Toast.makeText(
+                        getContext().getApplicationContext(),
+                        ErrorMessageAdapter.getErrorCauseMessage(
+                                result,
+                                null,
+                                getContext().getResources()
+                        ),
+                        Toast.LENGTH_SHORT
+                ).show();
+            }
+        });
+    }
+
 }

+ 5 - 2
src/com/owncloud/android/services/SyncFolderHandler.java

@@ -138,8 +138,11 @@ class SyncFolderHandler extends Handler {
 
     public void add(Account account, String remotePath,
                     SynchronizeFolderOperation syncFolderOperation){
-        mPendingOperations.putIfAbsent(account, remotePath, syncFolderOperation);
-        sendBroadcastNewSyncFolder(account, remotePath);    // TODO upgrade!
+        Pair<String, String> putResult =
+                mPendingOperations.putIfAbsent(account, remotePath, syncFolderOperation);
+        if (putResult != null) {
+            sendBroadcastNewSyncFolder(account, remotePath);    // TODO upgrade!
+        }
     }
 
 

+ 5 - 2
src/com/owncloud/android/syncadapter/FileSyncAdapter.java

@@ -298,7 +298,7 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
                 syncChildren(children);
             }
             
-        } else {
+        } else if (result.getCode() != ResultCode.FILE_NOT_FOUND) {
             // in failures, the statistics for the global result are updated
             if (    result.getCode() == RemoteOperationResult.ResultCode.UNAUTHORIZED ||
                     result.isIdPRedirection()
@@ -313,7 +313,10 @@ public class FileSyncAdapter extends AbstractOwnCloudSyncAdapter {
             }
             mFailedResultsCounter++;
             mLastFailedResult = result;
-        }
+
+        } // else, ResultCode.FILE_NOT_FOUND is ignored, remote folder was
+          // removed from other thread or other client during the synchronization,
+          // before this thread fetched its contents
             
     }
 

+ 2 - 2
src/com/owncloud/android/ui/activity/FileDisplayActivity.java

@@ -1044,7 +1044,7 @@ public class FileDisplayActivity extends HookActivity
         @Override
         public void onReceive(Context context, Intent intent) {
             try {
-                String uploadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);
+                String uploadedRemotePath = intent.getStringExtra(FileUploader.EXTRA_REMOTE_PATH);
                 String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME);
                 boolean sameAccount = getAccount() != null && accountName.equals(getAccount().name);
                 OCFile currentDir = getCurrentDir();
@@ -1053,7 +1053,7 @@ public class FileDisplayActivity extends HookActivity
 
                 if (sameAccount && isDescendant) {
                     String linkedToRemotePath =
-                            intent.getStringExtra(FileDownloader.EXTRA_LINKED_TO_PATH);
+                            intent.getStringExtra(FileUploader.EXTRA_LINKED_TO_PATH);
                     if (linkedToRemotePath == null || isAscendant(linkedToRemotePath)) {
                         refreshListOfFilesFragment();
                     }

+ 4 - 2
src/com/owncloud/android/ui/activity/ShareActivity.java

@@ -102,8 +102,10 @@ public class ShareActivity extends FileActivity
 
         } else if (UsersAndGroupsSearchProvider.ACTION_SHARE_WITH.equals(intent.getAction())) {
             Uri data = intent.getData();
+            String dataString = intent.getDataString();
+            String shareWith = dataString.substring(dataString.lastIndexOf('/') + 1);
             doShareWith(
-                    data.getLastPathSegment(),
+                    shareWith,
                     UsersAndGroupsSearchProvider.DATA_GROUP.equals(data.getAuthority())
             );
 
@@ -170,7 +172,7 @@ public class ShareActivity extends FileActivity
             refreshSharesFromStorageManager();
         }
 
-        if (operation instanceof CreateShareViaLinkOperation) {
+        if (operation instanceof CreateShareViaLinkOperation && result.isSuccess()) {
             // Send link to the app
             String link = ((OCShare) (result.getData().get(0))).getShareLink();
             Log_OC.d(TAG, "Share link = " + link);