Daniel Kvist
Daniel Kvist

Reputation: 3042

Why can File.listFiles return null when called on a directory?

I'm creating an Android app, and I want to list the files in a directory. I do this by calling

File[] files = path.listFiles(new CustomFileFilter());

path is a File object, which is created by calling

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

When I then try to get the length of the files array by calling

int length = files.length;

This line gives me a NullPointerException, because files is null.

I have checked if the path which I try to list the files in exists by calling

System.out.println("Path exists: " + path.exists());

And when I run the app, it prints

Path exists: true

in the Android Studio console, so the directory exists.

I've also printed the path name, which is

/storage/emulated/0/Download

So the path is a directory, and not a file.

I have no idea about why I'm getting a NullPointerException, because the path is a directory.

EDIT: The CustomFileFilter class looks like this:

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

Upvotes: 8

Views: 13537

Answers (3)

sai Pavan Kumar
sai Pavan Kumar

Reputation: 1177

make sure you followed the Saeed Masoumi’s answer, and if you still have the problem it is because you have set Target API 29 or higher.

add this property in your application tag of Manifest file and it will work.

android:requestLegacyExternalStorage="true"

According to google’s App compatibility features for data storage :

Before your app is fully compatible with scoped storage, you can temporarily opt out by using one of the following methods:

  • Target Android 9 (API level 28) or lower.
  • If you target Android 10 (API level 29) or higher, set the value of requestLegacyExternalStorage to true in your app's manifest file:

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

To test how an app targeting Android 9 or lower behaves when using scoped storage, you can opt in to the behavior by setting the value of requestLegacyExternalStorage to false.

Upvotes: 5

Yahya Hussein
Yahya Hussein

Reputation: 9121

For those who are working on android SDK>23, you need to grant the permissions by code: use something like:

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

Upvotes: 3

Saeed Masoumi
Saeed Masoumi

Reputation: 8916

Add this to AndroidManifest.xml:

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

This permission allow you to read files; if you don't use this permission then listFiles() and list() will both throw NullPointerException.

And here is an example of showing all files in /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]);
        }

Upvotes: 9

Related Questions