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

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

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

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.