Android10のアプリによって作成されたMediastoreのファイル名を変更します。AndroidAPI30で動作していますが、API29でエラーが表示されます。

Aug 23 2020

ここで、このrenameFile(..)関数はAndroid API 30で機能しています。ただし、Android API 29では機能せず、次のようなエラーが表示されます。

java.lang.IllegalArgumentException:明確に定義されたコレクションの一部ではないcontent:// media / external / file / 116の移動は許可されていません

更新-注:

---始まり---

sdk-29を使用するには、次のようにUriをextUri = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL)として使用する必要があります。

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

以下のコードの代わりに。また、MediaStore.Files.FileColumnsMediaStore.Downloadsに更新します

---終了---

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

関数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;
}

関数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;
}

回答

4 blackapps Aug 26 2020 at 21:18

java.lang.IllegalArgumentException:明確に定義されたコレクションの一部ではないcontent:// media / external / file / 116の移動は許可されていません

そのため、コレクションを使用する場合はAndroidQでは許可されません。

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

ただし、次のような「明確に定義されたコレクション」では許可されます。

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

他の明確に定義されたコレクションを見つけるのはあなたに任せます。

なぜこれがAndroidQ専用なのかわかりません。

あなたはjavaファイルでメッセージを見ることができます: https://android.googlesource.com/platform/packages/providers/MediaProvider/+/refs/heads/master/src/com/android/providers/media/MediaProvider.java

見積もり:

     // 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");
        }

名前の変更に失敗した場合は、SAFを使用してください(前述のとおり)。メディアコンテンツだけを知っているAndroidでファイルの名前を変更する方法Uri