Fixed: problems in handling a file that is still uploading but in the files list...
authorDavid A. Velasco <dvelasco@solidgear.es>
Fri, 27 Jul 2012 12:29:46 +0000 (14:29 +0200)
committerDavid A. Velasco <dvelasco@solidgear.es>
Fri, 27 Jul 2012 12:29:46 +0000 (14:29 +0200)
AndroidManifest.xml
res/drawable/uploading_file_indicator.png [new file with mode: 0644]
res/layout/list_layout.xml
src/eu/alefzero/owncloud/datamodel/FileDataStorageManager.java
src/eu/alefzero/owncloud/files/services/FileDownloader.java
src/eu/alefzero/owncloud/files/services/FileUploader.java
src/eu/alefzero/owncloud/ui/activity/FileDetailActivity.java
src/eu/alefzero/owncloud/ui/activity/FileDisplayActivity.java
src/eu/alefzero/owncloud/ui/adapter/FileListListAdapter.java
src/eu/alefzero/owncloud/ui/fragment/FileDetailFragment.java

index f6545ad..ab8bf89 100644 (file)
@@ -18,7 +18,7 @@
  -->\r
 <manifest package="eu.alefzero.owncloud"\r
     android:versionCode="1"\r
-    android:versionName="0.1.186B" xmlns:android="http://schemas.android.com/apk/res/android">\r
+    android:versionName="0.1.187B" xmlns:android="http://schemas.android.com/apk/res/android">\r
 \r
     <uses-permission android:name="android.permission.GET_ACCOUNTS" />\r
     <uses-permission android:name="android.permission.USE_CREDENTIALS" />\r
diff --git a/res/drawable/uploading_file_indicator.png b/res/drawable/uploading_file_indicator.png
new file mode 100644 (file)
index 0000000..b0b5634
Binary files /dev/null and b/res/drawable/uploading_file_indicator.png differ
index 39a3edd..a687307 100644 (file)
             android:layout_height="wrap_content"
             android:src="@drawable/local_file_indicator"/>
 
-        <ImageView
+        <!-- ImageView
             android:id="@+id/imageView4"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:src="@drawable/downloading_file_indicator"/>
+            android:src="@drawable/downloading_file_indicator"/ >
+
+        <ImageView
+            android:id="@+id/imageView5"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:src="@drawable/uploading_file_indicator"/ -->
 
         <ImageView
             android:id="@+id/imageView1"
index 43af746..b6fa918 100644 (file)
@@ -111,11 +111,12 @@ public class FileDataStorageManager implements DataStorageManager {
         cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
 
         if (fileExists(file.getRemotePath())) {
-            OCFile tmpfile = getFileByPath(file.getRemotePath());
-            file.setStoragePath(tmpfile.getStoragePath());
+            OCFile oldFile = getFileByPath(file.getRemotePath());
+            if (file.getStoragePath() == null && oldFile.getStoragePath() != null)
+                file.setStoragePath(oldFile.getStoragePath());
             if (!file.isDirectory());
                 cv.put(ProviderTableMeta.FILE_STORAGE_PATH, file.getStoragePath());
-            file.setFileId(tmpfile.getFileId());
+            file.setFileId(oldFile.getFileId());
 
             overriden = true;
             if (getContentResolver() != null) {
index 1b510cb..af327a5 100644 (file)
@@ -35,7 +35,8 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
     public static final String EXTRA_FILE_PATH = "FILE_PATH";\r
     public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";\r
     public static final String EXTRA_FILE_SIZE = "FILE_SIZE";\r
-    public static final String ACCOUNT_NAME = "ACCOUNT_NAME";    \r
+    public static final String ACCOUNT_NAME = "ACCOUNT_NAME";\r
+    \r
     private static final String TAG = "FileDownloader";\r
 \r
     private NotificationManager mNotificationMngr;\r
@@ -172,26 +173,29 @@ public class FileDownloader extends Service implements OnDatatransferProgressLis
         tmpFile.getParentFile().mkdirs();\r
         mDownloadsInProgress.put(buildRemoteName(mAccount.name, mRemotePath), tmpFile.getAbsolutePath());\r
         File newFile = null;\r
-        if (wdc.downloadFile(mRemotePath, tmpFile)) {\r
-            newFile = new File(getSavePath() + mAccount.name + mFilePath);\r
-            newFile.getParentFile().mkdirs();\r
-            boolean moved = tmpFile.renameTo(newFile);\r
+        try {\r
+            if (wdc.downloadFile(mRemotePath, tmpFile)) {\r
+                newFile = new File(getSavePath() + mAccount.name + mFilePath);\r
+                newFile.getParentFile().mkdirs();\r
+                boolean moved = tmpFile.renameTo(newFile);\r
             \r
-            if (moved) {\r
-                ContentValues cv = new ContentValues();\r
-                cv.put(ProviderTableMeta.FILE_STORAGE_PATH, newFile.getAbsolutePath());\r
-                getContentResolver().update(\r
-                    ProviderTableMeta.CONTENT_URI,\r
-                    cv,\r
-                    ProviderTableMeta.FILE_NAME + "=? AND "\r
-                            + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",\r
-                    new String[] {\r
-                            mFilePath.substring(mFilePath.lastIndexOf('/') + 1),\r
-                            mAccount.name });\r
-                downloadResult = true;\r
+                if (moved) {\r
+                    ContentValues cv = new ContentValues();\r
+                    cv.put(ProviderTableMeta.FILE_STORAGE_PATH, newFile.getAbsolutePath());\r
+                    getContentResolver().update(\r
+                            ProviderTableMeta.CONTENT_URI,\r
+                            cv,\r
+                            ProviderTableMeta.FILE_NAME + "=? AND "\r
+                                    + ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?",\r
+                            new String[] {\r
+                                mFilePath.substring(mFilePath.lastIndexOf('/') + 1),\r
+                                mAccount.name });\r
+                    downloadResult = true;\r
+                }\r
             }\r
+        } finally {\r
+            mDownloadsInProgress.remove(buildRemoteName(mAccount.name, mRemotePath));\r
         }\r
-        mDownloadsInProgress.remove(buildRemoteName(mAccount.name, mRemotePath));\r
 \r
         \r
         /// notify result\r
index 41c29fe..3f30f1b 100644 (file)
@@ -30,6 +30,9 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
 
     public static final String UPLOAD_FINISH_MESSAGE = "UPLOAD_FINISH";
     public static final String EXTRA_PARENT_DIR_ID = "PARENT_DIR_ID";
+    public static final String EXTRA_UPLOAD_RESULT = "RESULT";
+    public static final String EXTRA_REMOTE_PATH = "REMOTE_PATH";
+    public static final String EXTRA_FILE_PATH = "FILE_PATH";
     
     public static final String KEY_LOCAL_FILE = "LOCAL_FILE";
     public static final String KEY_REMOTE_FILE = "REMOTE_FILE";
@@ -184,29 +187,41 @@ public class FileUploader extends Service implements OnDatatransferProgressListe
             if (mimeType == null)
                 mimeType = "application/octet-stream";
             mCurrentIndexUpload = i;
-            mRemotePaths[i] = getAvailableRemotePath(wc, mRemotePaths[i]);
-            mUploadsInProgress.put(buildRemoteName(mAccount.name, mRemotePaths[i]), mLocalPaths[i]);
             long parentDirId = -1;
-            if (mRemotePaths[i] != null && wc.putFile(mLocalPaths[i], mRemotePaths[i], mimeType)) {
-                mSuccessCounter++;
-                OCFile new_file = new OCFile(mRemotePaths[i]);
-                new_file.setMimetype(mimeType);
-                new_file.setFileLength(localFiles[i].length());
-                new_file.setModificationTimestamp(System.currentTimeMillis());
-                new_file.setLastSyncDate(0);
-                new_file.setStoragePath(mLocalPaths[i]);         
+            boolean uploadResult = false;
+            String availablePath = getAvailableRemotePath(wc, mRemotePaths[i]);
+            try {
                 File f = new File(mRemotePaths[i]);
                 parentDirId = storageManager.getFileByPath(f.getParent().endsWith("/")?f.getParent():f.getParent()+"/").getFileId();
-                new_file.setParentId(parentDirId);
-                storageManager.saveFile(new_file);
+                if(availablePath != null) {
+                    mRemotePaths[i] = availablePath;
+                    mUploadsInProgress.put(buildRemoteName(mAccount.name, mRemotePaths[i]), mLocalPaths[i]);
+                    if (wc.putFile(mLocalPaths[i], mRemotePaths[i], mimeType)) {
+                        OCFile new_file = new OCFile(mRemotePaths[i]);
+                        new_file.setMimetype(mimeType);
+                        new_file.setFileLength(localFiles[i].length());
+                        new_file.setModificationTimestamp(System.currentTimeMillis());
+                        new_file.setLastSyncDate(0);
+                        new_file.setStoragePath(mLocalPaths[i]);         
+                        new_file.setParentId(parentDirId);
+                        storageManager.saveFile(new_file);
+                        mSuccessCounter++;
+                        uploadResult = true;
+                    }
+                }
+            } finally {
+                mUploadsInProgress.remove(buildRemoteName(mAccount.name, mRemotePaths[i]));
+                
+                /// notify upload (or fail) of EACH file to activities interested
+                Intent end = new Intent(UPLOAD_FINISH_MESSAGE);
+                end.putExtra(EXTRA_PARENT_DIR_ID, parentDirId);
+                end.putExtra(EXTRA_UPLOAD_RESULT, uploadResult);
+                end.putExtra(EXTRA_REMOTE_PATH, mRemotePaths[i]);
+                end.putExtra(EXTRA_FILE_PATH, mLocalPaths[i]);
+                end.putExtra(ACCOUNT_NAME, mAccount.name);
+                sendBroadcast(end);
             }
-            mUploadsInProgress.remove(buildRemoteName(mAccount.name, mRemotePaths[i]));
             
-            /// notify upload of EACH file to activities interested
-            Intent end = new Intent(UPLOAD_FINISH_MESSAGE);
-            end.putExtra(EXTRA_PARENT_DIR_ID, parentDirId);
-            end.putExtra(ACCOUNT_NAME, mAccount.name);
-            sendBroadcast(end);
         }
         
         /// notify final result
index 737c00f..e481cdb 100644 (file)
@@ -32,6 +32,7 @@ import eu.alefzero.owncloud.R;
 import eu.alefzero.owncloud.datamodel.OCFile;\r
 import eu.alefzero.owncloud.files.services.FileDownloader;\r
 import eu.alefzero.owncloud.ui.fragment.FileDetailFragment;\r
+import eu.alefzero.owncloud.ui.fragment.FileListFragment;\r
 \r
 /**\r
  * This activity displays the details of a file like its name, its size and so\r
@@ -40,7 +41,7 @@ import eu.alefzero.owncloud.ui.fragment.FileDetailFragment;
  * @author Bartek Przybylski\r
  * \r
  */\r
-public class FileDetailActivity extends SherlockFragmentActivity {\r
+public class FileDetailActivity extends SherlockFragmentActivity implements FileDetailFragment.ContainerActivity {\r
     \r
     private boolean mConfigurationChangedToLandscape = false;\r
 \r
@@ -108,5 +109,14 @@ public class FileDetailActivity extends SherlockFragmentActivity {
         startActivity(intent);\r
         finish();\r
     }\r
+    \r
+    /**\r
+     * {@inheritDoc}\r
+     */\r
+    @Override\r
+    public void onFileStateChanged() {\r
+        // nothing to do here!\r
+    }\r
+    \r
 \r
 }\r
index 163fea4..39d6e38 100644 (file)
@@ -80,7 +80,7 @@ import eu.alefzero.webdav.WebdavClient;
  */\r
 \r
 public class FileDisplayActivity extends SherlockFragmentActivity implements\r
-    FileListFragment.ContainerActivity, OnNavigationListener, OnClickListener, android.view.View.OnClickListener  {\r
+    FileListFragment.ContainerActivity, FileDetailFragment.ContainerActivity, OnNavigationListener, OnClickListener, android.view.View.OnClickListener  {\r
     \r
     private ArrayAdapter<String> mDirectories;\r
     private OCFile mCurrentDir;\r
@@ -788,6 +788,19 @@ public class FileDisplayActivity extends SherlockFragmentActivity implements
         }\r
     }\r
     \r
+    \r
+    /**\r
+     * {@inheritDoc}\r
+     */\r
+    @Override\r
+    public void onFileStateChanged() {\r
+        FileListFragment fileListFragment = (FileListFragment) getSupportFragmentManager().findFragmentById(R.id.fileList);\r
+        if (fileListFragment != null) { \r
+            fileListFragment.listDirectory();\r
+        }\r
+    }\r
+    \r
+    \r
     /**\r
      *  Operations in this method should be preferably performed in onCreate to have a lighter onResume method. \r
      * \r
index bcdce79..9ab68db 100644 (file)
@@ -25,6 +25,7 @@ import eu.alefzero.owncloud.R;
 import eu.alefzero.owncloud.datamodel.DataStorageManager;\r
 import eu.alefzero.owncloud.datamodel.OCFile;\r
 import eu.alefzero.owncloud.files.services.FileDownloader;\r
+import eu.alefzero.owncloud.files.services.FileUploader;\r
 \r
 import android.accounts.Account;\r
 import android.content.Context;\r
@@ -114,18 +115,40 @@ public class FileListListAdapter implements ListAdapter {
             } else {\r
                 fileIcon.setImageResource(R.drawable.ic_menu_archive);\r
             }\r
-            ImageView downloaded = (ImageView) view.findViewById(R.id.imageView2);\r
+            ImageView localStateView = (ImageView) view.findViewById(R.id.imageView2);\r
+            if (FileDownloader.isDownloading(mAccount, file.getRemotePath())) {\r
+                localStateView.setImageResource(R.drawable.downloading_file_indicator);\r
+                localStateView.setVisibility(View.VISIBLE);\r
+            } else if (FileUploader.isUploading(mAccount, file.getRemotePath())) {\r
+                localStateView.setImageResource(R.drawable.uploading_file_indicator);\r
+                localStateView.setVisibility(View.VISIBLE);\r
+            } else if (file.isDown()) {\r
+                localStateView.setImageResource(R.drawable.local_file_indicator);\r
+                localStateView.setVisibility(View.VISIBLE);\r
+            } else {\r
+                localStateView.setVisibility(View.INVISIBLE);\r
+            }\r
+                /*\r
+            ImageView down = (ImageView) view.findViewById(R.id.imageView2);\r
             ImageView downloading = (ImageView) view.findViewById(R.id.imageView4);\r
+            ImageView uploading = (ImageView) view.findViewById(R.id.imageView5);\r
             if (FileDownloader.isDownloading(mAccount, file.getRemotePath())) {\r
-                downloaded.setVisibility(View.INVISIBLE);\r
+                down.setVisibility(View.INVISIBLE);\r
                 downloading.setVisibility(View.VISIBLE);\r
+                uploading.setVisibility(View.INVISIBLE);\r
+            } else if (FileUploader.isUploading(mAccount, file.getRemotePath())) {\r
+                down.setVisibility(View.INVISIBLE);\r
+                downloading.setVisibility(View.INVISIBLE);\r
+                uploading.setVisibility(View.VISIBLE);\r
             } else if (file.isDown()) {\r
-                 downloaded.setVisibility(View.VISIBLE);\r
+                 down.setVisibility(View.VISIBLE);\r
                  downloading.setVisibility(View.INVISIBLE);\r
+                 uploading.setVisibility(View.INVISIBLE);\r
             } else {\r
-                downloaded.setVisibility(View.INVISIBLE);\r
+                down.setVisibility(View.INVISIBLE);\r
                 downloading.setVisibility(View.INVISIBLE);\r
-            }\r
+                uploading.setVisibility(View.INVISIBLE);\r
+            }*/\r
                 \r
             if (!file.isDirectory()) {\r
                 view.findViewById(R.id.file_size).setVisibility(View.VISIBLE);\r
index ad6f604..ce1ede9 100644 (file)
@@ -40,6 +40,8 @@ import org.json.JSONObject;
 \r
 import android.accounts.Account;\r
 import android.accounts.AccountManager;\r
+import android.annotation.SuppressLint;\r
+import android.app.Activity;\r
 import android.content.ActivityNotFoundException;\r
 import android.content.BroadcastReceiver;\r
 import android.content.Context;\r
@@ -97,6 +99,8 @@ public class FileDetailFragment extends SherlockFragment implements
     public static final String EXTRA_FILE = "FILE";\r
     public static final String EXTRA_ACCOUNT = "ACCOUNT";\r
 \r
+    private FileDetailFragment.ContainerActivity mContainerActivity;\r
+    \r
     private int mLayout;\r
     private View mView;\r
     private OCFile mFile;\r
@@ -104,6 +108,7 @@ public class FileDetailFragment extends SherlockFragment implements
     private ImageView mPreview;\r
     \r
     private DownloadFinishReceiver mDownloadFinishReceiver;\r
+    private UploadFinishReceiver mUploadFinishReceiver;\r
 \r
     private static final String TAG = "FileDetailFragment";\r
     public static final String FTAG = "FileDetails"; \r
@@ -140,6 +145,20 @@ public class FileDetailFragment extends SherlockFragment implements
         }\r
     }\r
     \r
+\r
+    /**\r
+     * {@inheritDoc}\r
+     */\r
+    @Override\r
+    public void onAttach(Activity activity) {\r
+        super.onAttach(activity);\r
+        try {\r
+            mContainerActivity = (ContainerActivity) activity;\r
+        } catch (ClassCastException e) {\r
+            throw new ClassCastException(activity.toString() + " must implement FileListFragment.ContainerActivity");\r
+        }\r
+    }\r
+    \r
     \r
     @Override\r
     public View onCreateView(LayoutInflater inflater, ViewGroup container,\r
@@ -183,18 +202,29 @@ public class FileDetailFragment extends SherlockFragment implements
     @Override\r
     public void onResume() {\r
         super.onResume();\r
+        \r
         mDownloadFinishReceiver = new DownloadFinishReceiver();\r
         IntentFilter filter = new IntentFilter(\r
                 FileDownloader.DOWNLOAD_FINISH_MESSAGE);\r
         getActivity().registerReceiver(mDownloadFinishReceiver, filter);\r
+        \r
+        mUploadFinishReceiver = new UploadFinishReceiver();\r
+        filter = new IntentFilter(FileUploader.UPLOAD_FINISH_MESSAGE);\r
+        getActivity().registerReceiver(mUploadFinishReceiver, filter);\r
+        \r
         mPreview = (ImageView)mView.findViewById(R.id.fdPreview);\r
     }\r
 \r
     @Override\r
     public void onPause() {\r
         super.onPause();\r
+        \r
         getActivity().unregisterReceiver(mDownloadFinishReceiver);\r
         mDownloadFinishReceiver = null;\r
+        \r
+        getActivity().unregisterReceiver(mUploadFinishReceiver);\r
+        mUploadFinishReceiver = null;\r
+        \r
         if (mPreview != null) {\r
             mPreview = null;\r
         }\r
@@ -218,9 +248,10 @@ public class FileDetailFragment extends SherlockFragment implements
                 i.putExtra(FileDownloader.EXTRA_FILE_SIZE, mFile.getFileLength());\r
                 \r
                 // update ui \r
-                setButtonsForDownloading();\r
+                setButtonsForTransferring();\r
                 \r
                 getActivity().startService(i);\r
+                mContainerActivity.onFileStateChanged();    // this is not working; it is performed before the fileDownloadService registers it as 'in progress'\r
                 break;\r
             }\r
             case R.id.fdKeepInSync: {\r
@@ -230,6 +261,8 @@ public class FileDetailFragment extends SherlockFragment implements
                 fdsm.saveFile(mFile);\r
                 if (mFile.keepInSync()) {\r
                     onClick(getView().findViewById(R.id.fdDownloadBtn));\r
+                } else {    \r
+                    mContainerActivity.onFileStateChanged();    // put inside 'else' to not call it twice (here, and in the virtual click on fdDownloadBtn)\r
                 }\r
                 break;\r
             }\r
@@ -361,8 +394,8 @@ public class FileDetailFragment extends SherlockFragment implements
             cb.setChecked(mFile.keepInSync());\r
 \r
             // configure UI for depending upon local state of the file\r
-            if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath())) {\r
-                setButtonsForDownloading();\r
+            if (FileDownloader.isDownloading(mAccount, mFile.getRemotePath()) || FileUploader.isUploading(mAccount, mFile.getRemotePath())) {\r
+                setButtonsForTransferring();\r
                 \r
             } else if (mFile.isDown()) {\r
                 // Update preview\r
@@ -483,10 +516,10 @@ public class FileDetailFragment extends SherlockFragment implements
     /**\r
      * Enables or disables buttons for a file being downloaded\r
      */\r
-    private void setButtonsForDownloading() {\r
+    private void setButtonsForTransferring() {\r
         if (!isEmpty()) {\r
             Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
-            downloadButton.setText(R.string.filedetails_download_in_progress);\r
+            //downloadButton.setText(R.string.filedetails_download_in_progress);    // ugly\r
             downloadButton.setEnabled(false);   // TODO replace it with a 'cancel download' button\r
         \r
             // let's protect the user from himself ;)\r
@@ -502,7 +535,7 @@ public class FileDetailFragment extends SherlockFragment implements
     private void setButtonsForDown() {\r
         if (!isEmpty()) {\r
             Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
-            downloadButton.setText(R.string.filedetails_redownload);\r
+            //downloadButton.setText(R.string.filedetails_redownload);      // ugly\r
             downloadButton.setEnabled(true);\r
         \r
             ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(true);\r
@@ -517,7 +550,7 @@ public class FileDetailFragment extends SherlockFragment implements
     private void setButtonsForRemote() {\r
         if (!isEmpty()) {\r
             Button downloadButton = (Button) getView().findViewById(R.id.fdDownloadBtn);\r
-            downloadButton.setText(R.string.filedetails_download);\r
+            //downloadButton.setText(R.string.filedetails_download);    // unnecessary\r
             downloadButton.setEnabled(true);\r
             \r
             ((Button) getView().findViewById(R.id.fdOpenBtn)).setEnabled(false);\r
@@ -545,6 +578,31 @@ public class FileDetailFragment extends SherlockFragment implements
         }*/\r
         return false;\r
     }\r
+    \r
+    \r
+    /**\r
+     * Interface to implement by any Activity that includes some instance of FileDetailFragment\r
+     * \r
+     * @author David A. Velasco\r
+     */\r
+    public interface ContainerActivity {\r
+\r
+        /**\r
+         * Callback method invoked when the detail fragment wants to notice its container \r
+         * activity about a relevant state the file shown by the fragment.\r
+         * \r
+         * Added to notify to FileDisplayActivity about the need of refresh the files list. \r
+         * \r
+         * Currently called when:\r
+         *  - a download is started;\r
+         *  - a rename is completed;\r
+         *  - a deletion is completed;\r
+         *  - the 'inSync' flag is changed;\r
+         */\r
+        public void onFileStateChanged();\r
+        \r
+    }\r
+    \r
 \r
     /**\r
      * Once the file download has finished -> update view\r
@@ -560,7 +618,7 @@ public class FileDetailFragment extends SherlockFragment implements
                 String downloadedRemotePath = intent.getStringExtra(FileDownloader.EXTRA_REMOTE_PATH);\r
                 if (mFile.getRemotePath().equals(downloadedRemotePath)) {\r
                     if (downloadWasFine) {\r
-                        mFile.setStoragePath(intent.getStringExtra(FileDownloader.EXTRA_FILE_PATH));\r
+                        mFile.setStoragePath(intent.getStringExtra(FileDownloader.EXTRA_FILE_PATH));    // updates the local object without accessing the database again\r
                     }\r
                     updateFileDetails();    // it updates the buttons; must be called although !downloadWasFine\r
                 }\r
@@ -568,6 +626,37 @@ public class FileDetailFragment extends SherlockFragment implements
         }\r
     }\r
     \r
+    \r
+    /**\r
+     * Once the file upload has finished -> update view\r
+     * \r
+     * Being notified about the finish of an upload is necessary for the next sequence:\r
+     *   1. Upload a big file.\r
+     *   2. Force a synchronization; if it finished before the upload, the file in transfer will be included in the local database and in the file list\r
+     *      of its containing folder; the the server includes it in the PROPFIND requests although it's not fully upload. \r
+     *   3. Click the file in the list to see its details.\r
+     *   4. Wait for the upload finishes; at this moment, the details view must be refreshed to enable the action buttons.\r
+     */\r
+    private class UploadFinishReceiver extends BroadcastReceiver {\r
+        @Override\r
+        public void onReceive(Context context, Intent intent) {\r
+            String accountName = intent.getStringExtra(FileUploader.ACCOUNT_NAME);\r
+\r
+            if (!isEmpty() && accountName.equals(mAccount.name)) {\r
+                boolean uploadWasFine = intent.getBooleanExtra(FileUploader.EXTRA_UPLOAD_RESULT, false);\r
+                String uploadRemotePath = intent.getStringExtra(FileUploader.EXTRA_REMOTE_PATH);\r
+                if (mFile.getRemotePath().equals(uploadRemotePath)) {\r
+                    if (uploadWasFine) {\r
+                        FileDataStorageManager fdsm = new FileDataStorageManager(mAccount, getActivity().getApplicationContext().getContentResolver());\r
+                        mFile = fdsm.getFileByPath(mFile.getRemotePath());\r
+                    }\r
+                    updateFileDetails();    // it updates the buttons; must be called although !uploadWasFine; interrupted uploads still leave an incomplete file in the server\r
+                }\r
+            }\r
+        }\r
+    }\r
+    \r
+\r
     // this is a temporary class for sharing purposes, it need to be replaced in transfer service\r
     private class ShareRunnable implements Runnable {\r
         private String mPath;\r
@@ -753,7 +842,10 @@ public class FileDetailFragment extends SherlockFragment implements
                     mFile = mNew;\r
                     mHandler.post(new Runnable() {\r
                         @Override\r
-                        public void run() { updateFileDetails(mFile, mAccount); }\r
+                        public void run() { \r
+                            updateFileDetails(mFile, mAccount);\r
+                            mContainerActivity.onFileStateChanged();\r
+                        }\r
                     });\r
                 }\r
                 Log.e("ASD", ""+move.getQueryString());\r
@@ -890,6 +982,7 @@ public class FileDetailFragment extends SherlockFragment implements
                                     FragmentTransaction transaction = getActivity().getSupportFragmentManager().beginTransaction();\r
                                     transaction.replace(R.id.file_details_container, new FileDetailFragment(null, null)); // empty FileDetailFragment\r
                                     transaction.commit();\r
+                                    mContainerActivity.onFileStateChanged();\r
                                     \r
                                 } else {\r
                                     getActivity().finish();\r
@@ -932,7 +1025,8 @@ public class FileDetailFragment extends SherlockFragment implements
     }\r
     \r
     class BitmapLoader extends AsyncTask<String, Void, Bitmap> {\r
-        @Override\r
+        @SuppressLint({ "NewApi", "NewApi", "NewApi" }) // to avoid Lint errors since Android SDK r20\r
+               @Override\r
         protected Bitmap doInBackground(String... params) {\r
             Bitmap result = null;\r
             if (params.length != 1) return result;\r
@@ -956,7 +1050,6 @@ public class FileDetailFragment extends SherlockFragment implements
                 int width = options.outWidth;\r
                 int height = options.outHeight;\r
                 int scale = 1;\r
-                boolean recycle = false;\r
                 if (width >= 2048 || height >= 2048) {\r
                     scale = (int) Math.ceil((Math.ceil(Math.max(height, width) / 2048.)));\r
                     options.inSampleSize = scale;\r