You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android 10文件重命名无反应问题排查(Android 11+正常)

问题:Android 10下文件重命名无反应,Android 11+正常

我编写了一套文件重命名代码,在Android 11及以上版本可正常完成文件重命名操作,但在Android 10中执行后无任何反应。相关代码实现、参数示例及调用方式如下:

原代码实现

public class PathDiv {
public static String dev(String path){
    return path.replaceAll("^(.*)/.*?$","$1");
}

public static void renameFilesInDir(String path, String dirIn, String ext) {

    File checkFile = new File(path);
        if (checkFile.isFile()) {
            try {
                checkFile.renameTo(new File(dirIn, ext));

            } catch (Exception e) {
                e.printStackTrace();
            }
    }
}

参数示例

  • path: /storage/emulated/0/Music/04. Kasger - Highland.mp3
  • dirIn: /storage/emulated/0/Music
  • ext: Highland.mp3

调用代码

PathDiv.renameFilesInDir(songItem.realUri,PathDiv.dev(songItem.realUri),newName.toString())

问题根源

  1. Android 10 Scoped Storage限制:Android 10(API 29)引入了Scoped Storage机制,此时直接通过File.renameTo()操作外部存储的媒体文件,会因为权限限制静默失败——方法返回false但不会抛出异常,而你的代码没有检查这个返回值,所以看不到操作失败的迹象。
  2. renameTo()方法的局限性:该方法本身依赖底层文件系统支持,在不同Android版本的存储权限模型下行为不一致,且没有可靠的失败反馈机制。

修复方案

针对Android 10及以上版本,必须适配Scoped Storage,使用MediaStore API来修改媒体文件名;同时增加返回值检查,明确操作结果。

兼容版重命名代码

import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.net.Uri;
import android.os.Build;
import android.provider.MediaStore;
import android.util.Log;
import java.io.File;

public class PathDiv {
    public static String dev(String path) {
        return path.replaceAll("^(.*)/.*?$", "$1");
    }

    public static boolean renameFilesInDir(Context context, String path, String dirIn, String ext) {
        File checkFile = new File(path);
        if (!checkFile.isFile()) {
            return false;
        }

        // Android 10及以上,使用MediaStore修改文件名
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            Uri contentUri = MediaStore.Audio.Media.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY);
            String selection = MediaStore.Audio.Media.DATA + "=?";
            String[] selectionArgs = new String[]{path};

            ContentResolver resolver = context.getContentResolver();
            try (Cursor cursor = resolver.query(contentUri, new String[]{MediaStore.Audio.Media._ID}, selection, selectionArgs, null)) {
                if (cursor != null && cursor.moveToFirst()) {
                    long mediaId = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Audio.Media._ID));
                    Uri itemUri = ContentUris.withAppendedId(contentUri, mediaId);

                    ContentValues values = new ContentValues();
                    values.put(MediaStore.Audio.Media.DISPLAY_NAME, ext);
                    // 执行更新
                    int rowsUpdated = resolver.update(itemUri, values, null, null);
                    return rowsUpdated > 0;
                }
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
            return false;
        } else {
            // Android 9及以下,沿用File操作,但检查返回值
            try {
                File targetFile = new File(dirIn, ext);
                boolean success = checkFile.renameTo(targetFile);
                if (!success) {
                    Log.e("PathDiv", "重命名失败:原路径" + path + ",目标路径" + targetFile.getAbsolutePath());
                }
                return success;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        }
    }
}

修改后的调用方式

// 传入Context对象,接收重命名结果
boolean isSuccess = PathDiv.renameFilesInDir(getApplicationContext(), songItem.realUri, PathDiv.dev(songItem.realUri), newName.toString());
if (!isSuccess) {
    // 这里处理重命名失败的逻辑,比如提示用户
}

注意事项

  • 权限配置:在AndroidManifest.xml中添加权限声明,并在运行时动态申请:
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
    
  • Android 11及以上版本,Scoped Storage进一步收紧,但MediaStore API是官方推荐的合规操作方式,能正常工作。

内容的提问来源于stack exchange,提问作者UserAndroidDeveloper

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 05:25:26