文件存在且位于IS目录中,但listFiles()返回null


76

的文档File.listFiles()建议null仅在调用它的文件不是目录的情况下才返回。

我有以下内容:

String dir = "/storage/emulated/0";
File f = new File(dir);
Log.v("Files",f.exists()+"");
Log.v("Files",f.isDirectory()+"");
Log.v("Files",f.listFiles()+"");

日志显示为:

true
true
null

由于某种原因,即使将该识别为有效目录,listFiles(也仍会返回)。我对Android文件层次结构的行为不是很熟悉,所以我猜问题出在这里。nullFile

作为参考,我正在Moto X上进行调试,无论手机是否插入计算机,结果都是相同的-因此,我认为插入手机与安装无关。


4
这不是权限问题吗?普通用户可以访问该目录吗?
Peterdk

1
您是否尝试过将文件放在该目录中?在我看来,该文档的实际含义是,如果它不是目录,它将为null,但是如果目录中没有实际的文件,它将返回null
DigCamara 2013年

@DigCamara好吧,在Java中,文件包含目录-该文件夹中有目录。
威尔逊

@Peterdk我切换到/ sdcard,它指向相同的东西,并且我认为对用户开放。.?,并得到相同的结果。
威尔逊

1
是什么File#canRead()告诉你吗?(如果那是错误的,我很确定是这样,那么null当您尝试读取
Directoy

Answers:


94

对于那些有此问题的人,请将其添加到AndroidManifest.xml中:

<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

解决的问题:D

编辑:如果这不起作用,只是确保路径是否正确


3
这个答案+5!我想知道为什么没有错误说我在logcat中没有此权限?
Micer 2014年

21
在棉花糖+上,您还需要调用以下代码:ActivityCompat.requestPermissions(活动,新的String [] {Manifest.permission.WRITE_EXTERNAL_STORAGE},requestCode);
IHeartAndroid '16

1
IHeartAndroid:我正在尝试复制并粘贴此代码,直到我意识到您在请求WRITE_EXTERNAL_STORAGE而不是READ_EXTERNAL_STORAGE时,它才起作用。
马特·格里高利

38

除了其他答案和评论,我建议您检查是否需要

<application android:requestLegacyExternalStorage="true"

在你的清单上。似乎最近有一些api需要它。

无论如何,zapl的评论很短,但很有见地。您可以“ ls -ld”在设备上的目录(通过“ adb shell”或其他一些shell)。如果您对目录具有“ r”权限,则可以调用listFiles()。否则,它返回null。请注意,如果您知道文件名并且对该目录具有“ x”权限,则可以访问该目录下的文件。您可以通过“ whoami”和“ groups”命令知道自己是谁。


5
Android 10需要
linquize 19-10-13,13

25

对于android 23或更高版本,您需要以如下方式通过onresume方法以编程方式授予运行时权限

public final String[] EXTERNAL_PERMS = {Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE
};

public final int EXTERNAL_REQUEST = 138;

requestForPermission();

public boolean requestForPermission() {

    boolean isPermissionOn = true;
    final int version = Build.VERSION.SDK_INT;
    if (version >= 23) {
        if (!canAccessExternalSd()) {
            isPermissionOn = false;
            requestPermissions(EXTERNAL_PERMS, EXTERNAL_REQUEST);
        }
    }

    return isPermissionOn;
}

public boolean canAccessExternalSd() {
    return (hasPermission(android.Manifest.permission.WRITE_EXTERNAL_STORAGE));
}

private boolean hasPermission(String perm) {
    return (PackageManager.PERMISSION_GRANTED == ContextCompat.checkSelfPermission(this, perm));

}

我的内部存储出现此问题
IgorGanapolsky,

此解决方案是唯一对我有用的解决方案。在Nougat 7.0中测试
Billyjoker

13

对于那些有此问题的人,您要授予读取权限,请将其添加到AndroidManifest.xml中:

android:name="android.permission.READ_EXTERNAL_STORAGE" 

并且您还应该授予

设置>应用> “您的应用名称” >权限>存储


就我而言,这是正确的解决方案。它不需要更改代码,并且适用于在Lollipop上运行的所有应用程序,但不适用于棉花糖在运行时授予权限的新概念。
GoranM '16

内部存储呢?
IgorGanapolsky '18

8

从File'listFiles'方法文档中:如果此抽象路径名不表示目录,或者发生I / O错误,则返回null。

因此,可能发生了I / O错误。检查该目录上的权限,运行Java程序的用户是否具有读取该目录的权限?如果没有,那就是你的答案。如果是这样,则目录可能为空。

顺便说一句,您不应该使用+“”将某物转换为字符串,因为它比String.valueOf慢,所以这是一个不好的做法。我将使用apache的StringUtils将该数组连接到字符串中,但这需要将该jar添加到您的类路径中。


4

只要在清单中添加权限uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" ,您的问题就可以解决。


2

@tamo的答案解决了我的问题,我在ANQ上编译exoplayer并设置为:

build.gradle:

android {
compileSdkVersion 29
buildToolsVersion '29.0.0'

defaultConfig {
    minSdkVersion 16
    targetSdkVersion 29
}

manifest.xml:

  <application
  android:name="com.google.android.exoplayer.demo.ExoPlayerDemoApplication"
  android:label="@string/application_name"
  android:icon="@drawable/ic_launcher"
  android:largeHeap="true"
  android:allowBackup="false"
  android:requestLegacyExternalStorage="true">

我检查了android开发站点,已经对此进行了解释:https : //developer.android.com/training/data-storage/compatibility

如果您的目标是API 29或更高版本,请遵循Google的设置。


1

我的问题是,由于某种原因,android:sharedUserId =“ android.uid.system”属性不允许该应用读取特定设备上的/ sdcard /。

因为只需要进行快速测试,所以删除了sharedUserId属性,进行了测试并将其添加回去。


0

我在Java中遇到了相同的问题,但在Android中却没有,在我正在读取带引号路径的配置文件时。我只删除了引号就解决了我的问题

因此,您可以通过字符串替换功能来实现它,也可以不带引号

字符串someString =“” C:\ path“; someString = someString.replace(“ \”“,”“);


-1

在该<uses-permission .... >部分的清单文件中,添加以下行android:name="android.permission.READ_EXTERNAL_STORAGE"。我认为这可以解决您的问题。


3
这不只是现有答案的重复吗?
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.