为什么File.listFiles在目录上调用时可以返回null?

时间:2015-01-10 09:27:44

标签: java android nullpointerexception file-listing

我正在创建一个Android应用,我想列出目录中的文件。我通过调用

来做到这一点
File[] files = path.listFiles(new CustomFileFilter());

pathFile对象,通过调用

创建
File path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS);

当我尝试通过调用

获取files数组的长度时
int length = files.length;

此行为我提供NullPointerException,因为files为空。

我已经通过调用

检查了我尝试列出文件的path是否存在
System.out.println("Path exists: " + path.exists());

当我运行应用程序时,会打印

Path exists: true

在Android Studio控制台中,因此目录存在。

我还打印了路径名,即

/storage/emulated/0/Download

所以path是一个目录,而不是一个文件。

我不知道为什么我会收到NullPointerException,因为path是一个目录。

编辑CustomFileFilter类看起来像这样:

public class CustomFileFilter implements FileFilter {

    // Determine if the file should be accepted
    @Override
    public boolean accept(File file) {
        // If the file isn't a directory
        if(file.isDirectory()) {
            // Accept it
            return true;
        } else if(file.getName().endsWith("txt")) {
            // Accept it
            return true;
        }
        // Don't accept it
        return false;
    }
}

3 个答案:

答案 0 :(得分:6)

将此添加到AndroidManifest.xml:

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

此权限允许您读取文件;如果您不使用此权限,则listFiles()list()都会抛出NullPointerException

以下是显示/storage/emulated/0/Download中所有文件的示例:

   String dir = "/storage/emulated/0/Download/";
        File f = new File(dir);
        String[] files = f.list();
        for(int i=0; i<files.length; i++){
            Log.d("tag", files[i]);
        }

答案 1 :(得分:2)

对于那些正在使用Android SDK&gt; 23的人,您需要通过代码授予权限: 使用类似的东西:

 boolean grantedAll = ContextCompat.checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
if (!grantedAll)
   {
     ActivityCompat.requestPermissions(thisActivity,
            new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
            REQUEST_PERMISSIONS);
   }

答案 2 :(得分:2)

确保您遵循Saeed Masoumi的回答,如果仍然有问题,那是因为您已将Target API设置为29或更高。

将此属性添加到清单文件的应用程序标记中,它将起作用。

android:requestLegacyExternalStorage="true"

根据google’s App compatibility features for data storage

在您的应用与范围存储完全兼容之前,您可以使用以下方法之一暂时选择退出:

  • 定位到Android 9(API级别28)或更低版本。
  • 如果您定位到Android 10(API级别29)或更高版本,请在应用的清单文件中将requestLegacyExternalStorage的值设置为true:

    <manifest ... >
      <!-- This attribute is "false" by default on apps targeting
           Android 10 or higher. -->
        <application android:requestLegacyExternalStorage="true" ... >
          ...
        </application>
    </manifest>

要测试使用范围存储的Android 9或更低版本的应用程序的行为,您可以通过将requestLegacyExternalStorage的值设置为false来选择行为。