Android文件权限问题:已声明读写权限但File.length()返回0
解决File.length()返回0的问题
可能的原因及解决方案:
动态权限未申请
Android 6.0(API 23)及以上版本中,READ_EXTERNAL_STORAGE和WRITE_EXTERNAL_STORAGE属于危险权限,仅在清单文件声明不足以获得访问权限,必须在代码中主动申请并获取用户授权。示例代码:// 检查权限状态 if (ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { // 发起权限请求 ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.READ_EXTERNAL_STORAGE}, REQUEST_CODE_READ_STORAGE); }注意:必须在
onRequestPermissionsResult回调中确认用户授权成功后,再执行文件读取操作。分区存储限制(Android 10+)
Android 10(API 29)引入分区存储机制,默认禁止直接通过File对象访问外部存储的文件路径。可通过两种方式处理:- 临时兼容旧模式(API29-30):在
AndroidManifest.xml的<application>标签下添加android:requestLegacyExternalStorage="true",暂时关闭分区存储限制。 - 适配分区存储规范:使用
MediaStore查询Download目录下的文件来获取大小,而非直接操作File对象。示例代码:
针对Android 11(API31)及以上版本,若需访问非媒体类文件,可申请String targetPath = "/storage/emulated/0/Download/Record_test.mp4"; Uri contentUri = MediaStore.Files.getContentUri("external"); String[] projection = {MediaStore.Files.FileColumns.SIZE}; String selection = MediaStore.Files.FileColumns.DATA + "=?"; String[] selectionArgs = {targetPath}; Cursor cursor = getContentResolver().query(contentUri, projection, selection, selectionArgs, null); if (cursor != null && cursor.moveToFirst()) { long fileSize = cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.Files.FileColumns.SIZE)); cursor.close(); }MANAGE_EXTERNAL_STORAGE权限,但更推荐使用存储访问框架(SAF)让用户主动选择文件。
- 临时兼容旧模式(API29-30):在
文件不存在或路径错误
先通过File.exists()和File.isFile()确认目标文件真实存在且为普通文件,避免因路径拼写错误、文件被删除等导致的异常:File targetFile = new File("/storage/emulated/0/Download/Record_test.mp4"); if (targetFile.exists() && targetFile.isFile()) { long fileSize = targetFile.length(); } else { // 文件不存在或不是有效文件 }文件被其他进程占用
如果文件刚完成下载或写入操作,可能仍被其他进程占用,导致无法正确读取文件大小。可尝试延迟一段时间后再读取,或确保写入操作已完全结束。
内容的提问来源于stack exchange,提问作者ErrorCodes
相关产品推荐
相关产品推荐

