简体   繁体   中英

Rename file of the Mediastore which is created by app in android 10. Working on Android API 30 but shows error in API 29

Here, this renameFile(..) func is working in Android API 30. But, it is not working in Android API 29 and shows the error like :

java.lang.IllegalArgumentException: Movement of content://media/external/file/116 which isn't part of well-defined collection not allowed

Update-Note:

---Begins---

In-order to work with sdk-29 we have to use Uri as extUri = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL) like:

private static Uri extUri = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL);

in place of below code. And also update MediaStore.Files.FileColumns to MediaStore.Downloads

---Ends---

Uri extUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);
String relativeLocation = Environment.DIRECTORY_DOWNLOADS + File.separator + "AppFolder";

function renameFile(...)

boolean renameFile(Context context, String newName, String displayName) {

    try {
        Long id = getIdFromDisplayName(displayName);
        ContentResolver contentResolver = context.getContentResolver();
        Uri mUri = ContentUris.withAppendedId(extUri, id);
        ContentValues contentValues = new ContentValues();

        contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 1);
        contentResolver.update(mUri, contentValues, null, null);

        contentValues.clear();
        contentValues.put(MediaStore.Files.FileColumns.DISPLAY_NAME, newName);
        // contentValues.put(MediaStore.Files.FileColumns.MIME_TYPE, "files/pdf");
        // contentValues.put(MediaStore.Files.FileColumns.RELATIVE_PATH, relativeLocation);
        // contentValues.put(MediaStore.Files.FileColumns.TITLE, "SomeName");
        // contentValues.put(MediaStore.Files.FileColumns.DATE_ADDED, System.currentTimeMillis() / 1000);
        // contentValues.put(MediaStore.Files.FileColumns.DATE_TAKEN, System.currentTimeMillis());
        contentValues.put(MediaStore.Files.FileColumns.IS_PENDING, 0);
        contentResolver.update(mUri, contentValues, null, null);
        return true;
    } catch (Exception ex) {
        ex.printStackTrace();
    }
    return false;
}

function getIdFromDisplayName(...)

@RequiresApi(api = Build.VERSION_CODES.Q)
Long getIdFromDisplayName(String displayName) {
    String[] projection;
    projection = new String[]{MediaStore.Files.FileColumns._ID};

    // TODO This will break if we have no matching item in the MediaStore.
    Cursor cursor = getContentResolver().query(extUri, projection,
            MediaStore.Files.FileColumns.DISPLAY_NAME + " LIKE ?", new String[]{displayName}, null);
    assert cursor != null;
    cursor.moveToFirst();

    if (cursor.getCount() > 0) {
        int columnIndex = cursor.getColumnIndex(projection[0]);
        long fileId = cursor.getLong(columnIndex);

        cursor.close();
        return fileId;
    }
    return null;
}

java.lang.IllegalArgumentException: Movement of content://media/external/file/116 which isn't part of well-defined collection not allowed

So it is for Android Q not allowed if you use the collection;

Uri extUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);

But is is allowed for a 'well-defined collection' like:

Uri extUri = MediaStore.Images.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);
// Use  "Pictures/MyFolder" for RELATIVE_PATH

I leave it to you to find other well-defined collections.

Why this is only for Android Q i dont know.

You can see the message in the java file: https://android.googlesource.com/platform/packages/providers/MediaProvider/+/refs/heads/master/src/com/android/providers/media/MediaProvider.java

Quote:

     // We only support movement under well-defined collections
        switch (match) {
            case AUDIO_MEDIA_ID:
            case VIDEO_MEDIA_ID:
            case IMAGES_MEDIA_ID:
            case DOWNLOADS_ID:
                break;
            default:
                throw new IllegalArgumentException("Movement of " + uri
                        + " which isn't part of well-defined collection not allowed");
        }

If the rename fails use SAF (as mentioned before). How to rename a file in Android knowing only its media content Uri

I had to face the rename problem myself (Android 29) and the solution above did not suffice.

This was because I had a physical SD card on which were located the files I wanted to rename.

Then, instruction:

extUri = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL);

did not work; instead,I had to:

  1. list the "external volumes"(according to Android terms)

     Set<String> lVls = MediaStore.getExternalVolumeNames(this);

    ..which gave me 2 volumes:

     "external_primary" (the built-in external storage) "bc21-eafa" (the SD card external storage)
  2. Initialize 'extUri' with that second value, like that:

     extUri = MediaStore.Audio.Media.getContentUri("bc21-eafa");
  3. Apply the rest of the procedure as described in this article. Thanks to all !

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM