-1

I am trying to delete file from my External/Removable SD Card. But I got following error:

remove failed: EACCES (Permission denied) : /storage/987F-099F/SDNumber/Voc_112_1.png

I basically need to move file from my removable SD card to my device storage. But I am not able to do that also.

I can fetch all the files from my removable SD card. Here is code for how I am fetching files from removable SD card:

final String[] columns = {MediaStore.Images.Media.DATA, MediaStore.Images.Media._ID, MediaStore.Images.Media.DISPLAY_NAME};
        final String orderBy = MediaStore.Images.Media.DISPLAY_NAME;

        Cursor cursor = context.getContentResolver().query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, columns, null,
                null, orderBy);

From this when I try to move file from SD card to device external storage it gives me error like this:

rename failed: EXDEV (Cross-device link) : /storage/987F-099F/SDNumber/Voc_112_1.png

Then, I move ahead and trying to copy that file. Copy file works great. But, then after I need to delete that file but it also doesn't work and gives error like this:

remove failed: EACCES (Permission denied) : /storage/987F-099F/SDNumber/Voc_112_1.png

Basically my whole code is like this:

public static void moveFile(Context context, File srcFile, File destFile) {
        boolean rename = srcFile.renameTo(destFile);
        if (!rename) {
            copyFile(srcFile.getAbsolutePath(), destFile.getAbsolutePath());
            boolean deleted = deleteFile(srcFile.getAbsolutePath());
            if (!deleted) {
                deleted = delete(context, srcFile);
                Log.e("moveFile", "deleted : " + deleted);
            }
        }
    }


public static boolean copyFile(String sourceFilePath, String destFilePath) {
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(sourceFilePath);
        } catch (FileNotFoundException e) {
            throw new RuntimeException("FileNotFoundException occurred. ", e);
        }
        return writeFile(destFilePath, inputStream);
    }


public static boolean deleteFile(String path) {
        if (path == null || path.trim().length() == 0) {
            return true;
        }

        File file = new File(path);
        if (!file.exists()) {
            return true;
        }
        if (file.isFile()) {
            return file.delete();
        }
        if (!file.isDirectory()) {
            return false;
        }
        for (File f : file.listFiles()) {
            if (f.isFile()) {
                f.delete();
            } else if (f.isDirectory()) {
                deleteFile(f.getAbsolutePath());
            }
        }
        return file.delete();
    }

I am also trying to delete using content resolver:

public static boolean delete(final Context context, final File file) {
        final String where = MediaStore.MediaColumns.DATA + "=?";
        final String[] selectionArgs = new String[] {
                file.getAbsolutePath()
        };
        final ContentResolver contentResolver = context.getContentResolver();
        final Uri filesUri = MediaStore.Files.getContentUri("external");

        contentResolver.delete(filesUri, where, selectionArgs);

        if (file.exists()) {

            contentResolver.delete(filesUri, where, selectionArgs);
        }
        return !file.exists();
    }

But none of this function works. That file still appear in my gallery.

Please let me know where I am going wrong and what is missing here. I am also checking runtime permission for Read and Write external storage.

Here is my Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="pix.tours.pixtours">

    <uses-permission android:name="android.permission.CALL_PHONE" />
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="com.android.vending.BILLING" />

    <application
        android:name=".GlobalApplication"
        android:allowBackup="true"
        android:hardwareAccelerated="false"
        android:icon="@drawable/logo"
        android:label="@string/app_name"
        android:largeHeap="true"
        android:roundIcon="@drawable/logo"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">


        <activity
            android:name=".activities.MainActivity"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme.NoActionBar" />

        <activity
            android:name=".activities.SplashActivity"
            android:screenOrientation="portrait"
            android:theme="@style/AppTheme.NoActionBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
 </application>

</manifest>

Thanks!

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
MKP
  • 141
  • 1
  • 11
  • show your manifest file – krishank Tripathi Mar 20 '18 at 06:49
  • @krishank Tripathi Please check updated question. – MKP Mar 20 '18 at 07:23
  • Android is Linux. Which, in turn, is Unix. Make sure you (your app) have the write (**w**) permission on that specific file. – Phantômaxx Mar 20 '18 at 08:23
  • How can I add write permission to my Removable SD Card? – MKP Mar 20 '18 at 08:42
  • `Here is code for how I am fetching files from removable SD card:` That code will never give you that path you mentioned. – greenapps Mar 20 '18 at 09:15
  • I am fetching all the images from device through cursor. And if there is external SD card available in device then it will also get images from sd card. So in the end, it is giving me all images in device storage and also from the external SD card. – MKP Mar 20 '18 at 09:30

2 Answers2

0

rename failed: EXDEV (Cross-device link) : /storage/987F-099F/SDNumber/Voc_112_1.png

Removable SD cards are read only (using file scheme) since Android 4.4+.

To be able to write use the storage access framework.

greenapps
  • 11,154
  • 2
  • 16
  • 19
  • Hi, Thank you for the answer. Can you please tell me more about "storage access framework" ? I am not aware about it's use. – MKP Mar 20 '18 at 09:32
-1

Are you requesting storage permission at runtime? Even if you add uses-permission in manifest, still you need to ask user to grant permissions at runtime. Here is code:

/ Storage Permissions
private static final int REQUEST_EXTERNAL_STORAGE = 1;
private static String[] PERMISSIONS_STORAGE = {
        Manifest.permission.READ_EXTERNAL_STORAGE,
        Manifest.permission.WRITE_EXTERNAL_STORAGE
};

/**
 * Checks if the app has permission to write to device storage
 *
 * If the app does not has permission then the user will be prompted to grant permissions
 *
 * @param activity
 */
public static void verifyStoragePermissions(Activity activity) {
    // Check if we have write permission
    int permission = ActivityCompat.checkSelfPermission(activity, Manifest.permission.WRITE_EXTERNAL_STORAGE);

    if (permission != PackageManager.PERMISSION_GRANTED) {
        // We don't have permission so prompt the user
        ActivityCompat.requestPermissions(
                activity,
                PERMISSIONS_STORAGE,
                REQUEST_EXTERNAL_STORAGE
        );
    }
}

Read more about the runtime permission request here: https://developer.android.com/training/permissions/requesting.html

Vikasdeep Singh
  • 20,983
  • 15
  • 78
  • 104