Merge pull request #1048 from owncloud/shareWithYou_icon_in_fileList
[pub/Android/ownCloud.git] / src / com / owncloud / android / datamodel / FileDataStorageManager.java
index 7fb1604..7db0a63 100644 (file)
@@ -1,6 +1,8 @@
-/* ownCloud Android client application
+/**
+ *   ownCloud Android client application
+ *
  *   Copyright (C) 2012  Bartek Przybylski
  *   Copyright (C) 2012  Bartek Przybylski
- *   Copyright (C) 2012-2014 ownCloud Inc.
+ *   Copyright (C) 2015 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,
  *
  *   This program is free software: you can redistribute it and/or modify
  *   it under the terms of the GNU General Public License version 2,
@@ -23,17 +25,9 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Iterator;
+import java.util.List;
 import java.util.Vector;
 
 import java.util.Vector;
 
-import com.owncloud.android.MainApp;
-import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
-import com.owncloud.android.lib.common.utils.Log_OC;
-import com.owncloud.android.lib.resources.shares.OCShare;
-import com.owncloud.android.lib.resources.shares.ShareType;
-import com.owncloud.android.lib.resources.files.FileUtils;
-import com.owncloud.android.utils.FileStorageUtils;
-
-
 import android.accounts.Account;
 import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
 import android.accounts.Account;
 import android.content.ContentProviderClient;
 import android.content.ContentProviderOperation;
@@ -41,10 +35,20 @@ import android.content.ContentProviderResult;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.ContentResolver;
 import android.content.ContentUris;
 import android.content.ContentValues;
+import android.content.Intent;
 import android.content.OperationApplicationException;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.content.OperationApplicationException;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.RemoteException;
+import android.provider.MediaStore;
+
+import com.owncloud.android.MainApp;
+import com.owncloud.android.db.ProviderMeta.ProviderTableMeta;
+import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.lib.resources.files.FileUtils;
+import com.owncloud.android.lib.resources.shares.OCShare;
+import com.owncloud.android.lib.resources.shares.ShareType;
+import com.owncloud.android.utils.FileStorageUtils;
 
 public class FileDataStorageManager {
 
 
 public class FileDataStorageManager {
 
@@ -138,9 +142,10 @@ public class FileDataStorageManager {
     }
 
     
     }
 
     
-    public Vector<OCFile> getFolderContent(OCFile f) {
+    public Vector<OCFile> getFolderContent(OCFile f/*, boolean onlyOnDevice*/) {
         if (f != null && f.isFolder() && f.getFileId() != -1) {
         if (f != null && f.isFolder() && f.getFileId() != -1) {
-            return getFolderContent(f.getFileId());
+            // TODO Enable when "On Device" is recovered ?
+            return getFolderContent(f.getFileId()/*, onlyOnDevice*/);
 
         } else {
             return new Vector<OCFile>();
 
         } else {
             return new Vector<OCFile>();
@@ -148,11 +153,12 @@ public class FileDataStorageManager {
     }
     
     
     }
     
     
-    public Vector<OCFile> getFolderImages(OCFile folder) {
+    public Vector<OCFile> getFolderImages(OCFile folder/*, boolean onlyOnDevice*/) {
         Vector<OCFile> ret = new Vector<OCFile>(); 
         if (folder != null) {
         Vector<OCFile> ret = new Vector<OCFile>(); 
         if (folder != null) {
-            // TODO better implementation, filtering in the access to database (if possible) instead of here 
-            Vector<OCFile> tmp = getFolderContent(folder);
+            // TODO better implementation, filtering in the access to database instead of here
+            // TODO Enable when "On Device" is recovered ?
+            Vector<OCFile> tmp = getFolderContent(folder/*, onlyOnDevice*/);
             OCFile current = null; 
             for (int i=0; i<tmp.size(); i++) {
                 current = tmp.get(i);
             OCFile current = null; 
             for (int i=0; i<tmp.size(); i++) {
                 current = tmp.get(i);
@@ -164,12 +170,14 @@ public class FileDataStorageManager {
         return ret;
     }
 
         return ret;
     }
 
-    
     public boolean saveFile(OCFile file) {
         boolean overriden = false;
         ContentValues cv = new ContentValues();
         cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
     public boolean saveFile(OCFile file) {
         boolean overriden = false;
         ContentValues cv = new ContentValues();
         cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
-        cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
+        cv.put( 
+            ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, 
+            file.getModificationTimestampAtLastSyncForData()
+        );
         cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
         cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
         cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
         cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
         cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
         cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
@@ -189,10 +197,11 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
         cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
         cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
         cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
         cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
         cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
+        cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
         
         boolean sameRemotePath = fileExists(file.getRemotePath());
         if (sameRemotePath ||
         
         boolean sameRemotePath = fileExists(file.getRemotePath());
         if (sameRemotePath ||
-                fileExists(file.getFileId())        ) {           // for renamed files; no more delete and create
+                fileExists(file.getFileId())        ) {  // for renamed files
 
             OCFile oldFile = null;
             if (sameRemotePath) {
 
             OCFile oldFile = null;
             if (sameRemotePath) {
@@ -257,20 +266,27 @@ public class FileDataStorageManager {
      * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
      *  
      * @param folder
      * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
      *  
      * @param folder
-     * @param files
-     * @param removeNotUpdated
+     * @param updatedFiles
+     * @param filesToRemove
      */
      */
-    public void saveFolder(OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove) {
+    public void saveFolder(
+            OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
+        ) {
         
         
-        Log_OC.d(TAG,  "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() + " children and " + filesToRemove.size() + " files to remove");
+        Log_OC.d(TAG,  "Saving folder " + folder.getRemotePath() + " with " + updatedFiles.size() 
+                + " children and " + filesToRemove.size() + " files to remove");
 
 
-        ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(updatedFiles.size());
+        ArrayList<ContentProviderOperation> operations = 
+                new ArrayList<ContentProviderOperation>(updatedFiles.size());
 
         // prepare operations to insert or update files to save in the given folder
         for (OCFile file : updatedFiles) {
             ContentValues cv = new ContentValues();
             cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
 
         // prepare operations to insert or update files to save in the given folder
         for (OCFile file : updatedFiles) {
             ContentValues cv = new ContentValues();
             cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
-            cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
+            cv.put(
+                ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, 
+                file.getModificationTimestampAtLastSyncForData()
+            );
             cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
             cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
             cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
             cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
             cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
             cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
@@ -290,6 +306,8 @@ public class FileDataStorageManager {
             cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
             cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
             cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
             cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
             cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
             cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
+            cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail());
+            cv.put(ProviderTableMeta.FILE_IS_DOWNLOADING, file.isDownloading());
 
             boolean existsByPath = fileExists(file.getRemotePath());
             if (existsByPath || fileExists(file.getFileId())) {
 
             boolean existsByPath = fileExists(file.getRemotePath());
             if (existsByPath || fileExists(file.getFileId())) {
@@ -302,29 +320,42 @@ public class FileDataStorageManager {
 
             } else {
                 // adding a new file
 
             } else {
                 // adding a new file
-                operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
+                operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
+                        withValues(cv).build());
             }
         }
         
         // prepare operations to remove files in the given folder
             }
         }
         
         // prepare operations to remove files in the given folder
-        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
+        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + 
+                ProviderTableMeta.FILE_PATH + "=?";
         String [] whereArgs = null;
         for (OCFile file : filesToRemove) {
             if (file.getParentId() == folder.getFileId()) {
                 whereArgs = new String[]{mAccount.name, file.getRemotePath()};
                 //Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
                 if (file.isFolder()) {
         String [] whereArgs = null;
         for (OCFile file : filesToRemove) {
             if (file.getParentId() == folder.getFileId()) {
                 whereArgs = new String[]{mAccount.name, file.getRemotePath()};
                 //Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, "" + file.getFileId());
                 if (file.isFolder()) {
-                    operations.add(ContentProviderOperation
-                                    .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_DIR, file.getFileId())).withSelection(where, whereArgs)
-                                        .build());
-                    // TODO remove local folder
+                    operations.add(ContentProviderOperation.newDelete(
+                            ContentUris.withAppendedId(
+                                    ProviderTableMeta.CONTENT_URI_DIR, file.getFileId()
+                            )
+                    ).withSelection(where, whereArgs).build());
+                    
+                    File localFolder = 
+                            new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
+                    if (localFolder.exists()) {
+                        removeLocalFolder(localFolder);
+                    }
                 } else {
                 } else {
-                    operations.add(ContentProviderOperation
-                                    .newDelete(ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId())).withSelection(where, whereArgs)
-                                        .build());
+                    operations.add(ContentProviderOperation.newDelete(
+                            ContentUris.withAppendedId(
+                                    ProviderTableMeta.CONTENT_URI_FILE, file.getFileId()
+                            )
+                    ).withSelection(where, whereArgs).build());
+                    
                     if (file.isDown()) {
                     if (file.isDown()) {
-                        new File(file.getStoragePath()).delete();
-                        // TODO move the deletion of local contents after success of deletions
+                        String path = file.getStoragePath();
+                        new File(path).delete();
+                        triggerMediaScan(path); // notify MediaScanner about removed file
                     }
                 }
             }
                     }
                 }
             }
@@ -333,9 +364,12 @@ public class FileDataStorageManager {
         // update metadata of folder
         ContentValues cv = new ContentValues();
         cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
         // update metadata of folder
         ContentValues cv = new ContentValues();
         cv.put(ProviderTableMeta.FILE_MODIFIED, folder.getModificationTimestamp());
-        cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, folder.getModificationTimestampAtLastSyncForData());
+        cv.put(
+            ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, 
+            folder.getModificationTimestampAtLastSyncForData()
+        );
         cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
         cv.put(ProviderTableMeta.FILE_CREATION, folder.getCreationTimestamp());
-        cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);   // FileContentProvider calculates the right size
+        cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, 0);
         cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
         cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
         cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
         cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, folder.getMimetype());
         cv.put(ProviderTableMeta.FILE_NAME, folder.getFileName());
         cv.put(ProviderTableMeta.FILE_PARENT, folder.getParentId());
@@ -409,18 +443,21 @@ public class FileDataStorageManager {
 //            Log_OC.d(TAG, "Updating size of " + id);
 //            if (getContentResolver() != null) {
 //                getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR, 
 //            Log_OC.d(TAG, "Updating size of " + id);
 //            if (getContentResolver() != null) {
 //                getContentResolver().update(ProviderTableMeta.CONTENT_URI_DIR, 
-//                        new ContentValues(),    // won't be used, but cannot be null; crashes in KLP
+//                        new ContentValues(),    
+                            // won't be used, but cannot be null; crashes in KLP
 //                        ProviderTableMeta._ID + "=?",
 //                        new String[] { String.valueOf(id) });
 //            } else {
 //                try {
 //                    getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR, 
 //                        ProviderTableMeta._ID + "=?",
 //                        new String[] { String.valueOf(id) });
 //            } else {
 //                try {
 //                    getContentProviderClient().update(ProviderTableMeta.CONTENT_URI_DIR, 
-//                            new ContentValues(),    // won't be used, but cannot be null; crashes in KLP
+//                            new ContentValues(),    
+                                // won't be used, but cannot be null; crashes in KLP
 //                            ProviderTableMeta._ID + "=?",
 //                            new String[] { String.valueOf(id) });
 //                    
 //                } catch (RemoteException e) {
 //                            ProviderTableMeta._ID + "=?",
 //                            new String[] { String.valueOf(id) });
 //                    
 //                } catch (RemoteException e) {
-//                    Log_OC.e(TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
+//                    Log_OC.e(
+//    TAG, "Exception in update of folder size through compatibility patch " + e.getMessage());
 //                }
 //            }
 //        } else {
 //                }
 //            }
 //        } else {
@@ -437,9 +474,12 @@ public class FileDataStorageManager {
                 
             } else {
                 if (removeDBData) {
                 
             } else {
                 if (removeDBData) {
-                    //Uri file_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_FILE, ""+file.getFileId());
-                    Uri file_uri = ContentUris.withAppendedId(ProviderTableMeta.CONTENT_URI_FILE, file.getFileId());
-                    String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
+                    Uri file_uri = ContentUris.withAppendedId(
+                        ProviderTableMeta.CONTENT_URI_FILE, 
+                        file.getFileId()
+                    );
+                    String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + 
+                            ProviderTableMeta.FILE_PATH + "=?";
                     String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
                     int deleted = 0;
                     if (getContentProviderClient() != null) {
                     String [] whereArgs = new String[]{mAccount.name, file.getRemotePath()};
                     int deleted = 0;
                     if (getContentProviderClient() != null) {
@@ -453,8 +493,12 @@ public class FileDataStorageManager {
                     }
                     success &= (deleted > 0); 
                 }
                     }
                     success &= (deleted > 0); 
                 }
-                if (removeLocalCopy && file.isDown() && file.getStoragePath() != null && success) {
-                    success = new File(file.getStoragePath()).delete();
+                String localPath = file.getStoragePath();
+                if (removeLocalCopy && file.isDown() && localPath != null && success) {
+                    success = new File(localPath).delete();
+                    if (success) {
+                        deleteFileInMediaScan(localPath);
+                    }
                     if (!removeDBData && success) {
                         // maybe unnecessary, but should be checked TODO remove if unnecessary
                         file.setStoragePath(null);
                     if (!removeDBData && success) {
                         // maybe unnecessary, but should be checked TODO remove if unnecessary
                         file.setStoragePath(null);
@@ -481,8 +525,10 @@ public class FileDataStorageManager {
     }
 
     private boolean removeFolderInDb(OCFile folder) {
     }
 
     private boolean removeFolderInDb(OCFile folder) {
-        Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, ""+ folder.getFileId());   // URI for recursive deletion
-        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
+        Uri folder_uri = Uri.withAppendedPath(ProviderTableMeta.CONTENT_URI_DIR, "" + 
+                folder.getFileId());   // URI for recursive deletion
+        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=?" + " AND " + 
+                ProviderTableMeta.FILE_PATH + "=?";
         String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
         int deleted = 0;
         if (getContentProviderClient() != null) {
         String [] whereArgs = new String[]{mAccount.name, folder.getRemotePath()};
         int deleted = 0;
         if (getContentProviderClient() != null) {
@@ -499,10 +545,12 @@ public class FileDataStorageManager {
 
     private boolean removeLocalFolder(OCFile folder) {
         boolean success = true;
 
     private boolean removeLocalFolder(OCFile folder) {
         boolean success = true;
-        File localFolder = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder));
+        String localFolderPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, folder);
+        File localFolder = new File(localFolderPath);
         if (localFolder.exists()) {
             // stage 1: remove the local files already registered in the files database
         if (localFolder.exists()) {
             // stage 1: remove the local files already registered in the files database
-            Vector<OCFile> files = getFolderContent(folder.getFileId());
+            // TODO Enable when "On Device" is recovered ?
+            Vector<OCFile> files = getFolderContent(folder.getFileId()/*, false*/);
             if (files != null) {
                 for (OCFile file : files) {
                     if (file.isFolder()) {
             if (files != null) {
                 for (OCFile file : files) {
                     if (file.isFolder()) {
@@ -512,6 +560,8 @@ public class FileDataStorageManager {
                             File localFile = new File(file.getStoragePath());
                             success &= localFile.delete();
                             if (success) {
                             File localFile = new File(file.getStoragePath());
                             success &= localFile.delete();
                             if (success) {
+                                // notify MediaScanner about removed file
+                                deleteFileInMediaScan(file.getStoragePath());
                                 file.setStoragePath(null);
                                 saveFile(file);
                             }
                                 file.setStoragePath(null);
                                 saveFile(file);
                             }
@@ -535,6 +585,7 @@ public class FileDataStorageManager {
                 if (localFile.isDirectory()) {
                     success &= removeLocalFolder(localFile);
                 } else {
                 if (localFile.isDirectory()) {
                     success &= removeLocalFolder(localFile);
                 } else {
+                    String path = localFile.getAbsolutePath();
                     success &= localFile.delete();
                 }
             }
                     success &= localFile.delete();
                 }
             }
@@ -543,83 +594,20 @@ public class FileDataStorageManager {
         return success;
     }
 
         return success;
     }
 
+    
     /**
     /**
-     * Updates database for a folder that was moved to a different location.
+     * Updates database and file system for a file or folder that was moved to a different location.
      * 
      * TODO explore better (faster) implementations
      * TODO throw exceptions up !
      */
      * 
      * TODO explore better (faster) implementations
      * TODO throw exceptions up !
      */
-    public void moveFolder(OCFile folder, String newPath) {
-        // TODO check newPath
-
-        if (folder != null && folder.isFolder() && folder.fileExists() && !OCFile.ROOT_PATH.equals(folder.getFileName())) {
-            /// 1. get all the descendants of 'dir' in a single QUERY (including 'dir')
-            Cursor c = null;
-            if (getContentProviderClient() != null) {
-                try {
-                    c = getContentProviderClient().query(ProviderTableMeta.CONTENT_URI, 
-                            null,
-                            ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
-                            new String[] { mAccount.name, folder.getRemotePath() + "%"  }, ProviderTableMeta.FILE_PATH + " ASC ");
-                } catch (RemoteException e) {
-                    Log_OC.e(TAG, e.getMessage());
-                }
-            } else {
-                c = getContentResolver().query(ProviderTableMeta.CONTENT_URI, 
-                        null,
-                        ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PATH + " LIKE ? ",
-                        new String[] { mAccount.name, folder.getRemotePath() + "%"  }, ProviderTableMeta.FILE_PATH + " ASC ");
-            }
-
-            /// 2. prepare a batch of update operations to change all the descendants
-            ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(c.getCount());
-            int lengthOfOldPath = folder.getRemotePath().length();
-            String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
-            int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
-            if (c.moveToFirst()) {
-                do {
-                    ContentValues cv = new ContentValues(); // don't take the constructor out of the loop and clear the object
-                    OCFile child = createFileInstance(c);
-                    cv.put(ProviderTableMeta.FILE_PATH, newPath + child.getRemotePath().substring(lengthOfOldPath));
-                    if (child.getStoragePath() != null && child.getStoragePath().startsWith(defaultSavePath)) {
-                        cv.put(ProviderTableMeta.FILE_STORAGE_PATH, defaultSavePath + newPath + child.getStoragePath().substring(lengthOfOldStoragePath));
-                    }
-                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
-                            withValues(cv).
-                            withSelection(  ProviderTableMeta._ID + "=?", 
-                                    new String[] { String.valueOf(child.getFileId()) })
-                                    .build());
-                } while (c.moveToNext());
-            }
-            c.close();
-
-            /// 3. apply updates in batch
-            try {
-                if (getContentResolver() != null) {
-                    getContentResolver().applyBatch(MainApp.getAuthority(), operations);
-
-                } else {
-                    getContentProviderClient().applyBatch(operations);
-                }
-
-            } catch (OperationApplicationException e) {
-                Log_OC.e(TAG, "Fail to update descendants of " + folder.getFileId() + " in database", e);
-
-            } catch (RemoteException e) {
-                Log_OC.e(TAG, "Fail to update desendants of " + folder.getFileId() + " in database", e);
-            }
-
-        }
-    }
-
-    
     public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) {
 
         if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) {
             
             OCFile targetParent = getFileByPath(targetParentPath);
             if (targetParent == null) {
     public void moveLocalFile(OCFile file, String targetPath, String targetParentPath) {
 
         if (file != null && file.fileExists() && !OCFile.ROOT_PATH.equals(file.getFileName())) {
             
             OCFile targetParent = getFileByPath(targetParentPath);
             if (targetParent == null) {
-                // TODO panic
+                throw new IllegalStateException("Parent folder of the target path does not exist!!");
             }
             
             /// 1. get all the descendants of the moved element in a single QUERY
             }
             
             /// 1. get all the descendants of the moved element in a single QUERY
@@ -659,6 +647,8 @@ public class FileDataStorageManager {
             ArrayList<ContentProviderOperation> operations = 
                     new ArrayList<ContentProviderOperation>(c.getCount());
             String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
             ArrayList<ContentProviderOperation> operations = 
                     new ArrayList<ContentProviderOperation>(c.getCount());
             String defaultSavePath = FileStorageUtils.getSavePath(mAccount.name);
+            List<String> originalPathsToTriggerMediaScan = new ArrayList<String>();
+            List<String> newPathsToTriggerMediaScan = new ArrayList<String>();
             if (c.moveToFirst()) {
                 int lengthOfOldPath = file.getRemotePath().length();
                 int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
             if (c.moveToFirst()) {
                 int lengthOfOldPath = file.getRemotePath().length();
                 int lengthOfOldStoragePath = defaultSavePath.length() + lengthOfOldPath;
@@ -672,11 +662,14 @@ public class FileDataStorageManager {
                     if (child.getStoragePath() != null && 
                             child.getStoragePath().startsWith(defaultSavePath)) {
                         // update link to downloaded content - but local move is not done here!
                     if (child.getStoragePath() != null && 
                             child.getStoragePath().startsWith(defaultSavePath)) {
                         // update link to downloaded content - but local move is not done here!
-                        cv.put(
-                            ProviderTableMeta.FILE_STORAGE_PATH, 
-                            defaultSavePath + targetPath + 
-                                child.getStoragePath().substring(lengthOfOldStoragePath)
-                        );
+                        String targetLocalPath = defaultSavePath + targetPath + 
+                                child.getStoragePath().substring(lengthOfOldStoragePath);
+                        
+                        cv.put(ProviderTableMeta.FILE_STORAGE_PATH, targetLocalPath);
+                        
+                        originalPathsToTriggerMediaScan.add(child.getStoragePath());
+                        newPathsToTriggerMediaScan.add(targetLocalPath);
+                        
                     }
                     if (child.getRemotePath().equals(file.getRemotePath())) {
                         cv.put(
                     }
                     if (child.getRemotePath().equals(file.getRemotePath())) {
                         cv.put(
@@ -707,33 +700,41 @@ public class FileDataStorageManager {
                 }
 
             } catch (Exception e) {
                 }
 
             } catch (Exception e) {
-                Log_OC.e(
-                    TAG, 
-                    "Fail to update " + file.getFileId() + " and descendants in database", 
-                    e
-                );
+                Log_OC.e(TAG, "Fail to update " + file.getFileId() + " and descendants in database", e);
             }
 
             /// 4. move in local file system 
             }
 
             /// 4. move in local file system 
-            String localPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
-            File localFile = new File(localPath);
+            String originalLocalPath = FileStorageUtils.getDefaultSavePathFor(mAccount.name, file);
+            String targetLocalPath = defaultSavePath + targetPath;
+            File localFile = new File(originalLocalPath);
             boolean renamed = false;
             if (localFile.exists()) {
             boolean renamed = false;
             if (localFile.exists()) {
-                File targetFile = new File(defaultSavePath + targetPath);
+                File targetFile = new File(targetLocalPath);
                 File targetFolder = targetFile.getParentFile();
                 if (!targetFolder.exists()) {
                     targetFolder.mkdirs();
                 }
                 renamed = localFile.renameTo(targetFile);
             }
                 File targetFolder = targetFile.getParentFile();
                 if (!targetFolder.exists()) {
                     targetFolder.mkdirs();
                 }
                 renamed = localFile.renameTo(targetFile);
             }
-            Log_OC.d(TAG, "Local file RENAMED : " + renamed);
-            
+
+            if (renamed) {
+                Iterator<String> it = originalPathsToTriggerMediaScan.iterator();
+                while (it.hasNext()) {
+                    // Notify MediaScanner about removed file
+                    deleteFileInMediaScan(it.next());
+                }
+                it = newPathsToTriggerMediaScan.iterator();
+                while (it.hasNext()) {
+                    // Notify MediaScanner about new file/folder
+                    triggerMediaScan(it.next());
+                }
+            }
         }
         
     }
     
     
         }
         
     }
     
     
-    private Vector<OCFile> getFolderContent(long parentId) {
+    private Vector<OCFile> getFolderContent(long parentId/*, boolean onlyOnDevice*/) {
 
         Vector<OCFile> ret = new Vector<OCFile>();
 
 
         Vector<OCFile> ret = new Vector<OCFile>();
 
@@ -760,7 +761,10 @@ public class FileDataStorageManager {
         if (c.moveToFirst()) {
             do {
                 OCFile child = createFileInstance(c);
         if (c.moveToFirst()) {
             do {
                 OCFile child = createFileInstance(c);
-                ret.add(child);
+                // TODO Enable when "On Device" is recovered ?
+                // if (child.isFolder() || !onlyOnDevice || onlyOnDevice && child.isDown()){
+                    ret.add(child);
+                // }
             } while (c.moveToNext());
         }
 
             } while (c.moveToNext());
         }
 
@@ -851,7 +855,9 @@ public class FileDataStorageManager {
                 file.setStoragePath(c.getString(c
                         .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
                 if (file.getStoragePath() == null) {
                 file.setStoragePath(c.getString(c
                         .getColumnIndex(ProviderTableMeta.FILE_STORAGE_PATH)));
                 if (file.getStoragePath() == null) {
-                    // try to find existing file and bind it with current account; - with the current update of SynchronizeFolderOperation, this won't be necessary anymore after a full synchronization of the account
+                    // try to find existing file and bind it with current account; 
+                    // with the current update of SynchronizeFolderOperation, this won't be 
+                    // necessary anymore after a full synchronization of the account
                     File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
                     if (f.exists()) {
                         file.setStoragePath(f.getAbsolutePath());
                     File f = new File(FileStorageUtils.getDefaultSavePathFor(mAccount.name, file));
                     if (f.exists()) {
                         file.setStoragePath(f.getAbsolutePath());
@@ -881,6 +887,8 @@ public class FileDataStorageManager {
             file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID)));
             file.setNeedsUpdateThumbnail(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1 ? true : false);
             file.setRemoteId(c.getString(c.getColumnIndex(ProviderTableMeta.FILE_REMOTE_ID)));
             file.setNeedsUpdateThumbnail(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.FILE_UPDATE_THUMBNAIL)) == 1 ? true : false);
+            file.setDownloading(c.getInt(
+                    c.getColumnIndex(ProviderTableMeta.FILE_IS_DOWNLOADING)) == 1 ? true : false);
                     
         }
         return file;
                     
         }
         return file;
@@ -930,13 +938,16 @@ public class FileDataStorageManager {
         cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
         cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
         cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
         cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
         cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
         cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
-        cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
+        cv.put(
+            ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, 
+            share.getSharedWithDisplayName()
+        );
         cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
         cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
         cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
         cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
         
         cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
         cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
         cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
         cv.put(ProviderTableMeta.OCSHARES_ACCOUNT_OWNER, mAccount.name);
         
-        if (shareExists(share.getIdRemoteShared())) {           // for renamed files; no more delete and create
+        if (shareExists(share.getIdRemoteShared())) {   // for renamed files
 
             overriden = true;
             if (getContentResolver() != null) {
 
             overriden = true;
             if (getContentResolver() != null) {
@@ -1038,7 +1049,9 @@ public class FileDataStorageManager {
             share.setIsFolder(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1 ? true : false);
             share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID)));
             share.setIsFolder(c.getInt(
                     c.getColumnIndex(ProviderTableMeta.OCSHARES_IS_DIRECTORY)) == 1 ? true : false);
             share.setUserId(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_USER_ID)));
-            share.setIdRemoteShared(c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED)));
+            share.setIdRemoteShared(
+                c.getLong(c.getColumnIndex(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED))
+            );
                     
         }
         return share;
                     
         }
         return share;
@@ -1090,7 +1103,9 @@ public class FileDataStorageManager {
 
         } else {
             try {
 
         } else {
             try {
-                getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
+                getContentProviderClient().update(
+                        ProviderTableMeta.CONTENT_URI, cv, where, whereArgs
+                );
                 
             } catch (RemoteException e) {
                 Log_OC.e(TAG, "Exception in cleanSharedFiles" + e.getMessage());
                 
             } catch (RemoteException e) {
                 Log_OC.e(TAG, "Exception in cleanSharedFiles" + e.getMessage());
@@ -1102,7 +1117,8 @@ public class FileDataStorageManager {
         ContentValues cv = new ContentValues();
         cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
         ContentValues cv = new ContentValues();
         cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, false);
         cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, "");
-        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + ProviderTableMeta.FILE_PARENT + "=?";
+        String where = ProviderTableMeta.FILE_ACCOUNT_OWNER + "=? AND " + 
+                ProviderTableMeta.FILE_PARENT + "=?";
         String [] whereArgs = new String[] { mAccount.name , String.valueOf(folder.getFileId()) };
         
         if (getContentResolver() != null) {
         String [] whereArgs = new String[] { mAccount.name , String.valueOf(folder.getFileId()) };
         
         if (getContentResolver() != null) {
@@ -1110,7 +1126,9 @@ public class FileDataStorageManager {
 
         } else {
             try {
 
         } else {
             try {
-                getContentProviderClient().update(ProviderTableMeta.CONTENT_URI, cv, where, whereArgs);
+                getContentProviderClient().update(
+                        ProviderTableMeta.CONTENT_URI, cv, where, whereArgs
+                );
                 
             } catch (RemoteException e) {
                 Log_OC.e(TAG, "Exception in cleanSharedFilesInFolder " + e.getMessage());
                 
             } catch (RemoteException e) {
                 Log_OC.e(TAG, "Exception in cleanSharedFilesInFolder " + e.getMessage());
@@ -1127,7 +1145,9 @@ public class FileDataStorageManager {
 
         } else {
             try {
 
         } else {
             try {
-                getContentProviderClient().delete(ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs);
+                getContentProviderClient().delete(
+                        ProviderTableMeta.CONTENT_URI_SHARE, where, whereArgs
+                );
                 
             } catch (RemoteException e) {
                 Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage());
                 
             } catch (RemoteException e) {
                 Log_OC.e(TAG, "Exception in cleanShares" + e.getMessage());
@@ -1138,7 +1158,8 @@ public class FileDataStorageManager {
     public void saveShares(Collection<OCShare> shares) {
         cleanShares();
         if (shares != null) {
     public void saveShares(Collection<OCShare> shares) {
         cleanShares();
         if (shares != null) {
-            ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(shares.size());
+            ArrayList<ContentProviderOperation> operations = 
+                    new ArrayList<ContentProviderOperation>(shares.size());
 
             // prepare operations to insert or update files to save in the given folder
             for (OCShare share : shares) {
 
             // prepare operations to insert or update files to save in the given folder
             for (OCShare share : shares) {
@@ -1152,7 +1173,10 @@ public class FileDataStorageManager {
                 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
                 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
                 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
                 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
                 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
                 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
-                cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
+                cv.put(
+                    ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, 
+                    share.getSharedWithDisplayName()
+                );
                 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
                 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
                 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
                 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
                 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
                 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
@@ -1160,15 +1184,23 @@ public class FileDataStorageManager {
 
                 if (shareExists(share.getIdRemoteShared())) {
                     // updating an existing file
 
                 if (shareExists(share.getIdRemoteShared())) {
                     // updating an existing file
-                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
+                    operations.add(
+                            ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
                             withValues(cv).
                             withValues(cv).
-                            withSelection(  ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", 
-                                    new String[] { String.valueOf(share.getIdRemoteShared()) })
-                                    .build());
+                            withSelection(
+                                    ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", 
+                                    new String[] { String.valueOf(share.getIdRemoteShared()) }
+                            ).
+                            build()
+                    );
 
                 } else {
                     // adding a new file
 
                 } else {
                     // adding a new file
-                    operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build());
+                    operations.add(
+                            ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
+                            withValues(cv).
+                            build()
+                    );
                 }
             }
             
                 }
             }
             
@@ -1176,10 +1208,13 @@ public class FileDataStorageManager {
             if (operations.size() > 0) {
                 @SuppressWarnings("unused")
                 ContentProviderResult[] results = null;
             if (operations.size() > 0) {
                 @SuppressWarnings("unused")
                 ContentProviderResult[] results = null;
-                Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
+                Log_OC.d(TAG, "Sending " + operations.size() + 
+                        " operations to FileContentProvider");
                 try {
                     if (getContentResolver() != null) {
                 try {
                     if (getContentResolver() != null) {
-                        results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+                        results = getContentResolver().applyBatch(
+                                MainApp.getAuthority(), operations
+                        );
     
                     } else {
                         results = getContentProviderClient().applyBatch(operations);
     
                     } else {
                         results = getContentProviderClient().applyBatch(operations);
@@ -1200,13 +1235,17 @@ public class FileDataStorageManager {
         cleanSharedFiles();
         
         if (sharedFiles != null) {
         cleanSharedFiles();
         
         if (sharedFiles != null) {
-            ArrayList<ContentProviderOperation> operations = new ArrayList<ContentProviderOperation>(sharedFiles.size());
+            ArrayList<ContentProviderOperation> operations = 
+                    new ArrayList<ContentProviderOperation>(sharedFiles.size());
 
             // prepare operations to insert or update files to save in the given folder
             for (OCFile file : sharedFiles) {
                 ContentValues cv = new ContentValues();
                 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
 
             // prepare operations to insert or update files to save in the given folder
             for (OCFile file : sharedFiles) {
                 ContentValues cv = new ContentValues();
                 cv.put(ProviderTableMeta.FILE_MODIFIED, file.getModificationTimestamp());
-                cv.put(ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, file.getModificationTimestampAtLastSyncForData());
+                cv.put(
+                    ProviderTableMeta.FILE_MODIFIED_AT_LAST_SYNC_FOR_DATA, 
+                    file.getModificationTimestampAtLastSyncForData()
+                );
                 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
                 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
                 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
                 cv.put(ProviderTableMeta.FILE_CREATION, file.getCreationTimestamp());
                 cv.put(ProviderTableMeta.FILE_CONTENT_LENGTH, file.getFileLength());
                 cv.put(ProviderTableMeta.FILE_CONTENT_TYPE, file.getMimetype());
@@ -1218,27 +1257,44 @@ public class FileDataStorageManager {
                 }
                 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
                 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
                 }
                 cv.put(ProviderTableMeta.FILE_ACCOUNT_OWNER, mAccount.name);
                 cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE, file.getLastSyncDateForProperties());
-                cv.put(ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, file.getLastSyncDateForData());
+                cv.put(
+                    ProviderTableMeta.FILE_LAST_SYNC_DATE_FOR_DATA, 
+                    file.getLastSyncDateForData()
+                );
                 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
                 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
                 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
                 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
                 cv.put(ProviderTableMeta.FILE_KEEP_IN_SYNC, file.keepInSync() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_ETAG, file.getEtag());
                 cv.put(ProviderTableMeta.FILE_SHARE_BY_LINK, file.isShareByLink() ? 1 : 0);
                 cv.put(ProviderTableMeta.FILE_PUBLIC_LINK, file.getPublicLink());
                 cv.put(ProviderTableMeta.FILE_PERMISSIONS, file.getPermissions());
                 cv.put(ProviderTableMeta.FILE_REMOTE_ID, file.getRemoteId());
-                cv.put(ProviderTableMeta.FILE_UPDATE_THUMBNAIL, file.needsUpdateThumbnail() ? 1 : 0);
+                cv.put(
+                    ProviderTableMeta.FILE_UPDATE_THUMBNAIL, 
+                    file.needsUpdateThumbnail() ? 1 : 0
+                );
+                cv.put(
+                        ProviderTableMeta.FILE_IS_DOWNLOADING,
+                        file.isDownloading() ? 1 : 0
+                );
 
                 boolean existsByPath = fileExists(file.getRemotePath());
                 if (existsByPath || fileExists(file.getFileId())) {
                     // updating an existing file
 
                 boolean existsByPath = fileExists(file.getRemotePath());
                 if (existsByPath || fileExists(file.getFileId())) {
                     // updating an existing file
-                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
+                    operations.add(
+                            ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI).
                             withValues(cv).
                             withValues(cv).
-                            withSelection(  ProviderTableMeta._ID + "=?", 
-                                    new String[] { String.valueOf(file.getFileId()) })
-                                    .build());
+                            withSelection(
+                                    ProviderTableMeta._ID + "=?", 
+                                    new String[] { String.valueOf(file.getFileId()) }
+                            ).build()
+                    );
 
                 } else {
                     // adding a new file
 
                 } else {
                     // adding a new file
-                    operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).withValues(cv).build());
+                    operations.add(
+                            ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI).
+                            withValues(cv).
+                            build()
+                    );
                 }
             }
             
                 }
             }
             
@@ -1246,10 +1302,13 @@ public class FileDataStorageManager {
             if (operations.size() > 0) {
                 @SuppressWarnings("unused")
                 ContentProviderResult[] results = null;
             if (operations.size() > 0) {
                 @SuppressWarnings("unused")
                 ContentProviderResult[] results = null;
-                Log_OC.d(TAG, "Sending " + operations.size() + " operations to FileContentProvider");
+                Log_OC.d(TAG, "Sending " + operations.size() + 
+                        " operations to FileContentProvider");
                 try {
                     if (getContentResolver() != null) {
                 try {
                     if (getContentResolver() != null) {
-                        results = getContentResolver().applyBatch(MainApp.getAuthority(), operations);
+                        results = getContentResolver().applyBatch(
+                                MainApp.getAuthority(), operations
+                        );
     
                     } else {
                         results = getContentProviderClient().applyBatch(operations);
     
                     } else {
                         results = getContentProviderClient().applyBatch(operations);
@@ -1268,7 +1327,8 @@ public class FileDataStorageManager {
     
     public void removeShare(OCShare share){
         Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE;
     
     public void removeShare(OCShare share){
         Uri share_uri = ProviderTableMeta.CONTENT_URI_SHARE;
-        String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " + ProviderTableMeta.FILE_PATH + "=?";
+        String where = ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?" + " AND " + 
+                ProviderTableMeta.FILE_PATH + "=?";
         String [] whereArgs = new String[]{mAccount.name, share.getPath()};
         if (getContentProviderClient() != null) {
             try {
         String [] whereArgs = new String[]{mAccount.name, share.getPath()};
         if (getContentProviderClient() != null) {
             try {
@@ -1325,7 +1385,10 @@ public class FileDataStorageManager {
                 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
                 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
                 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
                 cv.put(ProviderTableMeta.OCSHARES_SHARED_DATE, share.getSharedDate());
                 cv.put(ProviderTableMeta.OCSHARES_EXPIRATION_DATE, share.getExpirationDate());
                 cv.put(ProviderTableMeta.OCSHARES_TOKEN, share.getToken());
-                cv.put(ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, share.getSharedWithDisplayName());
+                cv.put(
+                    ProviderTableMeta.OCSHARES_SHARE_WITH_DISPLAY_NAME, 
+                    share.getSharedWithDisplayName()
+                );
                 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
                 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
                 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
                 cv.put(ProviderTableMeta.OCSHARES_IS_DIRECTORY, share.isFolder() ? 1 : 0);
                 cv.put(ProviderTableMeta.OCSHARES_USER_ID, share.getUserId());
                 cv.put(ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED, share.getIdRemoteShared());
@@ -1334,7 +1397,8 @@ public class FileDataStorageManager {
                 /*
                 if (shareExists(share.getIdRemoteShared())) {
                     // updating an existing share resource
                 /*
                 if (shareExists(share.getIdRemoteShared())) {
                     // updating an existing share resource
-                    operations.add(ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
+                    operations.add(
+                            ContentProviderOperation.newUpdate(ProviderTableMeta.CONTENT_URI_SHARE).
                             withValues(cv).
                             withSelection(  ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", 
                                     new String[] { String.valueOf(share.getIdRemoteShared()) })
                             withValues(cv).
                             withSelection(  ProviderTableMeta.OCSHARES_ID_REMOTE_SHARED + "=?", 
                                     new String[] { String.valueOf(share.getIdRemoteShared()) })
@@ -1343,7 +1407,11 @@ public class FileDataStorageManager {
                 } else {
                 */
                 // adding a new share resource
                 } else {
                 */
                 // adding a new share resource
-                operations.add(ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).withValues(cv).build());
+                operations.add(
+                        ContentProviderOperation.newInsert(ProviderTableMeta.CONTENT_URI_SHARE).
+                        withValues(cv).
+                        build()
+                );
                 //}
             }
         }
                 //}
             }
         }
@@ -1372,18 +1440,23 @@ public class FileDataStorageManager {
         
     }
 
         
     }
 
-    private ArrayList<ContentProviderOperation> prepareRemoveSharesInFolder(OCFile folder, ArrayList<ContentProviderOperation> preparedOperations) {
+    private ArrayList<ContentProviderOperation> prepareRemoveSharesInFolder(
+            OCFile folder, ArrayList<ContentProviderOperation> preparedOperations) {
         if (folder != null) {
         if (folder != null) {
-            String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND " + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
+            String where = ProviderTableMeta.OCSHARES_PATH + "=?" + " AND " 
+                    + ProviderTableMeta.OCSHARES_ACCOUNT_OWNER + "=?";
             String [] whereArgs = new String[]{ "", mAccount.name };
             String [] whereArgs = new String[]{ "", mAccount.name };
-            
-            Vector<OCFile> files = getFolderContent(folder);
+
+            // TODO Enable when "On Device" is recovered ?
+            Vector<OCFile> files = getFolderContent(folder /*, false*/);
             
             for (OCFile file : files) {
                 whereArgs[0] = file.getRemotePath();
             
             for (OCFile file : files) {
                 whereArgs[0] = file.getRemotePath();
-                preparedOperations.add(ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE)
-                        .withSelection(where, whereArgs)
-                        .build());
+                preparedOperations.add(
+                        ContentProviderOperation.newDelete(ProviderTableMeta.CONTENT_URI_SHARE).
+                        withSelection(where, whereArgs).
+                        build()
+                );
             }
         }
         return preparedOperations;
             }
         }
         return preparedOperations;
@@ -1427,4 +1500,52 @@ public class FileDataStorageManager {
         //}
     }
 
         //}
     }
 
+    public void triggerMediaScan(String path) {
+        Intent intent = new Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE);
+        intent.setData(Uri.fromFile(new File(path)));
+        MainApp.getAppContext().sendBroadcast(intent);
+    }
+
+    public void deleteFileInMediaScan(String path) {
+
+        String mimetypeString = FileStorageUtils.getMimeTypeFromName(path);
+        ContentResolver contentResolver = getContentResolver();
+
+        if (contentResolver != null) {
+            if (mimetypeString.startsWith("image/")) {
+                // Images
+                contentResolver.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+                        MediaStore.Images.Media.DATA + "=?", new String[]{path});
+            } else if (mimetypeString.startsWith("audio/")) {
+                // Audio
+                contentResolver.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
+                        MediaStore.Audio.Media.DATA + "=?", new String[]{path});
+            } else if (mimetypeString.startsWith("video/")) {
+                // Video
+                contentResolver.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+                        MediaStore.Video.Media.DATA + "=?", new String[]{path});
+            }
+        } else {
+            ContentProviderClient contentProviderClient = getContentProviderClient();
+            try {
+                if (mimetypeString.startsWith("image/")) {
+                    // Images
+                    contentProviderClient.delete(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+                            MediaStore.Images.Media.DATA + "=?", new String[]{path});
+                } else if (mimetypeString.startsWith("audio/")) {
+                    // Audio
+                    contentProviderClient.delete(MediaStore.Audio.Media.EXTERNAL_CONTENT_URI,
+                            MediaStore.Audio.Media.DATA + "=?", new String[]{path});
+                } else if (mimetypeString.startsWith("video/")) {
+                    // Video
+                    contentProviderClient.delete(MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
+                            MediaStore.Video.Media.DATA + "=?", new String[]{path});
+                }
+            } catch (RemoteException e) {
+                Log_OC.e(TAG, "Exception deleting media file in MediaStore " + e.getMessage());
+            }
+        }
+
+    }
+
 }
 }