Android 10中应用程序创建的Mediastore文件如何重命名?在Android API 30上工作,但在API 29上会显示错误。

6

这里,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.FileColumns 更新为 MediaStore.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;
}

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

同时,您可以阅读以下内容:https://dev59.com/tFMI5IYBdhLWcg3wy-te - blackapps
3个回答

6

java.lang.IllegalArgumentException: 对于不属于明确定义集合的内容://media/external/file/116 的移动是不被允许的。

因此,如果您使用该集合,则 Android Q 不允许这样做。

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

但对于“明确定义的集合”,例如:

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

我相信您可以寻找其他明确定义的集合。

为什么这只适用于Android Q我不知道。

您可以在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的情况下重命名文件


1

我认为这是Android 10媒体提供程序中的系统错误。在Android 10中,它是这样的。

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

在Android 11中,它是这样的

        final boolean allowMovement = extras.getBoolean(MediaStore.QUERY_ARG_ALLOW_MOVEMENT,
            !isCallingPackageSelf());
    if (containsAny(initialValues.keySet(), sPlacementColumns)
            && !initialValues.containsKey(MediaColumns.DATA)
            && !isThumbnail
            && allowMovement) {
        Trace.beginSection("movement");
        // We only support movement under well-defined collections
        switch (match) {
            case AUDIO_MEDIA_ID:
            case AUDIO_PLAYLISTS_ID:
            case VIDEO_MEDIA_ID:
            case IMAGES_MEDIA_ID:
            case DOWNLOADS_ID:
            case FILES_ID:
                break;
            default:
                throw new IllegalArgumentException("Movement of " + uri
                        + " which isn't part of well-defined collection not allowed");
        }

0

我自己也遇到了重命名问题(Android 29),上面的解决方案并不足够。

这是因为我有一个物理SD卡,其中存放着我想要重命名的文件。

然后,按照以下指示进行操作:

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

没有起作用,相反,我不得不:

  1. 列出“外部卷”(根据Android术语)

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

    ..这给了我2个卷:

    "external_primary"    (内置外部存储)
    "bc21-eafa"           (SD卡外部存储)
    
  2. 用第二个值初始化'extUri',如下所示:

    extUri = MediaStore.Audio.Media.getContentUri("bc21-eafa");
    
  3. 按照本文所述的其余步骤进行操作。感谢大家!


1
目前您的回答不够清晰明了。请编辑并添加更多细节,以帮助其他人理解这如何回答所提出的问题。您可以在帮助中心中找到有关编写良好答案的更多信息。 - Community

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接