Browse Source

Merge pull request #844 from owncloud/delete_local_files

Removal of media files is notified to MediaProvider directly - MediaScan API does not work properly in Android 4.x
David A. Velasco 10 years ago
parent
commit
7f23fa5a77

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

@@ -46,6 +46,7 @@ import android.content.OperationApplicationException;
 import android.database.Cursor;
 import android.database.Cursor;
 import android.net.Uri;
 import android.net.Uri;
 import android.os.RemoteException;
 import android.os.RemoteException;
+import android.provider.MediaStore;
 
 
 public class FileDataStorageManager {
 public class FileDataStorageManager {
 
 
@@ -262,8 +263,8 @@ public class FileDataStorageManager {
      * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
      * HERE ONLY DATA CONSISTENCY SHOULD BE GRANTED
      *  
      *  
      * @param folder
      * @param folder
-     * @param files
-     * @param removeNotUpdated
+     * @param updatedFiles
+     * @param filesToRemove
      */
      */
     public void saveFolder(
     public void saveFolder(
             OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
             OCFile folder, Collection<OCFile> updatedFiles, Collection<OCFile> filesToRemove
@@ -493,7 +494,7 @@ public class FileDataStorageManager {
                 if (removeLocalCopy && file.isDown() && localPath != null && success) {
                 if (removeLocalCopy && file.isDown() && localPath != null && success) {
                     success = new File(localPath).delete();
                     success = new File(localPath).delete();
                     if (success) {
                     if (success) {
-                        triggerMediaScan(localPath);
+                        deleteFileInMediaScan(localPath);
                     }
                     }
                     if (!removeDBData && success) {
                     if (!removeDBData && success) {
                         // maybe unnecessary, but should be checked TODO remove if unnecessary
                         // maybe unnecessary, but should be checked TODO remove if unnecessary
@@ -541,7 +542,8 @@ public class FileDataStorageManager {
 
 
     private boolean removeLocalFolder(OCFile folder) {
     private boolean removeLocalFolder(OCFile folder) {
         boolean success = true;
         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()) {
         if (localFolder.exists()) {
             // stage 1: remove the local files already registered in the files database
             // stage 1: remove the local files already registered in the files database
             Vector<OCFile> files = getFolderContent(folder.getFileId());
             Vector<OCFile> files = getFolderContent(folder.getFileId());
@@ -551,13 +553,13 @@ public class FileDataStorageManager {
                         success &= removeLocalFolder(file);
                         success &= removeLocalFolder(file);
                     } else {
                     } else {
                         if (file.isDown()) {
                         if (file.isDown()) {
-                            String path = file.getStoragePath();
                             File localFile = new File(file.getStoragePath());
                             File localFile = new File(file.getStoragePath());
                             success &= localFile.delete();
                             success &= localFile.delete();
                             if (success) {
                             if (success) {
+                                // notify MediaScanner about removed file
+                                deleteFileInMediaScan(file.getStoragePath());
                                 file.setStoragePath(null);
                                 file.setStoragePath(null);
                                 saveFile(file);
                                 saveFile(file);
-                                triggerMediaScan(path); // notify MediaScanner about removed file
                             }
                             }
                         }
                         }
                     }
                     }
@@ -581,7 +583,6 @@ public class FileDataStorageManager {
                 } else {
                 } else {
                     String path = localFile.getAbsolutePath();
                     String path = localFile.getAbsolutePath();
                     success &= localFile.delete();
                     success &= localFile.delete();
-                    triggerMediaScan(path); // notify MediaScanner about removed file
                 }
                 }
             }
             }
         }
         }
@@ -716,7 +717,7 @@ public class FileDataStorageManager {
                 Iterator<String> it = originalPathsToTriggerMediaScan.iterator();
                 Iterator<String> it = originalPathsToTriggerMediaScan.iterator();
                 while (it.hasNext()) {
                 while (it.hasNext()) {
                     // Notify MediaScanner about removed file
                     // Notify MediaScanner about removed file
-                    triggerMediaScan(it.next());
+                    deleteFileInMediaScan(it.next());
                 }
                 }
                 it = newPathsToTriggerMediaScan.iterator();
                 it = newPathsToTriggerMediaScan.iterator();
                 while (it.hasNext()) {
                 while (it.hasNext()) {
@@ -1498,4 +1499,46 @@ public class FileDataStorageManager {
         MainApp.getAppContext().sendBroadcast(intent);
         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());
+            }
+        }
+
+    }
+
 }
 }

+ 2 - 12
src/com/owncloud/android/datamodel/OCFile.java

@@ -20,9 +20,9 @@ package com.owncloud.android.datamodel;
 
 
 import android.os.Parcel;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.os.Parcelable;
-import android.webkit.MimeTypeMap;
 
 
 import com.owncloud.android.lib.common.utils.Log_OC;
 import com.owncloud.android.lib.common.utils.Log_OC;
+import com.owncloud.android.utils.FileStorageUtils;
 
 
 import java.io.File;
 import java.io.File;
 
 
@@ -538,17 +538,7 @@ public class OCFile implements Parcelable, Comparable<OCFile> {
      */
      */
     public boolean isImage() {
     public boolean isImage() {
         return ((mMimeType != null && mMimeType.startsWith("image/")) ||
         return ((mMimeType != null && mMimeType.startsWith("image/")) ||
-                getMimeTypeFromName().startsWith("image/"));
-    }
-
-    public String getMimeTypeFromName() {
-        String extension = "";
-        int pos = mRemotePath.lastIndexOf('.');
-        if (pos >= 0) {
-            extension = mRemotePath.substring(pos + 1);
-        }
-        String result = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
-        return (result != null) ? result : "";
+                FileStorageUtils.getMimeTypeFromName(mRemotePath).startsWith("image/"));
     }
     }
 
 
     public String getPermissions() {
     public String getPermissions() {

+ 3 - 4
src/com/owncloud/android/operations/RenameFileOperation.java

@@ -51,7 +51,6 @@ public class RenameFileOperation extends SyncOperation {
      * Constructor
      * Constructor
      * 
      * 
      * @param remotePath            RemotePath of the OCFile instance describing the remote file or folder to rename
      * @param remotePath            RemotePath of the OCFile instance describing the remote file or folder to rename
-     * @param account               OwnCloud account containing the remote file 
      * @param newName               New name to set as the name of file.
      * @param newName               New name to set as the name of file.
      */
      */
     public RenameFileOperation(String remotePath, String newName) {
     public RenameFileOperation(String remotePath, String newName) {
@@ -117,7 +116,7 @@ public class RenameFileOperation extends SyncOperation {
 
 
     private void saveLocalFile() {
     private void saveLocalFile() {
         mFile.setFileName(mNewName);
         mFile.setFileName(mNewName);
-        
+
         // try to rename the local copy of the file
         // try to rename the local copy of the file
         if (mFile.isDown()) {
         if (mFile.isDown()) {
             String oldPath = mFile.getStoragePath();
             String oldPath = mFile.getStoragePath();
@@ -129,8 +128,8 @@ public class RenameFileOperation extends SyncOperation {
                 String newPath = parentStoragePath + mNewName;
                 String newPath = parentStoragePath + mNewName;
                 mFile.setStoragePath(newPath);
                 mFile.setStoragePath(newPath);
 
 
-                // notify MediaScanner about removed file - TODO really works?
-                getStorageManager().triggerMediaScan(oldPath);
+                // notify MediaScanner about removed file
+                getStorageManager().deleteFileInMediaScan(oldPath);
                 // notify to scan about new file
                 // notify to scan about new file
                 getStorageManager().triggerMediaScan(newPath);
                 getStorageManager().triggerMediaScan(newPath);
             }
             }

+ 20 - 4
src/com/owncloud/android/utils/FileStorageUtils.java

@@ -36,6 +36,7 @@ import android.preference.PreferenceManager;
 import android.net.Uri;
 import android.net.Uri;
 import android.os.Environment;
 import android.os.Environment;
 import android.os.StatFs;
 import android.os.StatFs;
+import android.webkit.MimeTypeMap;
 
 
 
 
 /**
 /**
@@ -135,7 +136,7 @@ public class FileStorageUtils {
     /**
     /**
      * Creates and populates a new {@link RemoteFile} object with the data read from an {@link OCFile}.
      * Creates and populates a new {@link RemoteFile} object with the data read from an {@link OCFile}.
      * 
      * 
-     * @param oCFile    OCFile 
+     * @param ocFile    OCFile
      * @return          New RemoteFile instance representing the resource described by ocFile.
      * @return          New RemoteFile instance representing the resource described by ocFile.
      */
      */
     public static RemoteFile fillRemoteFile(OCFile ocFile){
     public static RemoteFile fillRemoteFile(OCFile ocFile){
@@ -171,7 +172,7 @@ public class FileStorageUtils {
     
     
     /**
     /**
      * Sorts list by Date
      * Sorts list by Date
-     * @param sortAscending true: ascending, false: descending
+     * @param files
      */
      */
     public static Vector<OCFile> sortByDate(Vector<OCFile> files){
     public static Vector<OCFile> sortByDate(Vector<OCFile> files){
         final Integer val;
         final Integer val;
@@ -239,7 +240,7 @@ public class FileStorageUtils {
 
 
     /**
     /**
      * Sorts list by Name
      * Sorts list by Name
-     * @param sortAscending true: ascending, false: descending
+     * @param files     files to sort
      */
      */
     public static Vector<OCFile> sortByName(Vector<OCFile> files){
     public static Vector<OCFile> sortByName(Vector<OCFile> files){
         final Integer val;
         final Integer val;
@@ -284,6 +285,21 @@ public class FileStorageUtils {
             return result;
             return result;
         }
         }
         return 0;
         return 0;
-    } 
+    }
+
+    /**
+     * Mimetype String of a file
+     * @param path
+     * @return
+     */
+    public static String getMimeTypeFromName(String path) {
+        String extension = "";
+        int pos = path.lastIndexOf('.');
+        if (pos >= 0) {
+            extension = path.substring(pos + 1);
+        }
+        String result = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension.toLowerCase());
+        return (result != null) ? result : "";
+    }
   
   
 }
 }