6

I was creating an application to test whether File.listFiles() method is working or not. To check this I made an application and I used it there but this returning null in place of an array. This is my full code please help and I have granted all permissions for android 11

MainActivity.java

package com.rajkumarcreations.file;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.widget.TextView;
import android.widget.Toast;

import org.w3c.dom.Text;

import java.io.File;

import static android.Manifest.permission.READ_EXTERNAL_STORAGE;
import static android.Manifest.permission.WRITE_EXTERNAL_STORAGE;
import static android.os.Build.VERSION.SDK_INT;

public class MainActivity extends AppCompatActivity {
TextView tv;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv = (TextView) findViewById(R.id.btn);
        if(!checkPermission()){
            requestPermission();
        }else{
            File file = new File(Environment.getExternalStorageDirectory()+"/Download/");
            File[] allfiles = null;
            allfiles = file.listFiles();
            if(file.exists()){
                tv.setText("Exist");
            }
            if(allfiles!=null){
                Toast.makeText(this, "length is "+allfiles.length, Toast.LENGTH_SHORT).show();
            }else{
                Toast.makeText(this, "Array is null", Toast.LENGTH_SHORT).show();
            }
        }
    }

    private boolean checkPermission() {
        if (SDK_INT >= Build.VERSION_CODES.R) {
            return Environment.isExternalStorageManager();
        } else {
            int write = ContextCompat.checkSelfPermission(MainActivity.this, WRITE_EXTERNAL_STORAGE);
            int read = ContextCompat.checkSelfPermission(MainActivity.this, READ_EXTERNAL_STORAGE);
            return write == PackageManager.PERMISSION_GRANTED && read == PackageManager.PERMISSION_GRANTED;
        }
    }

    private void requestPermission() {
        if (SDK_INT >= Build.VERSION_CODES.R) {
            try {
                Intent intent = new Intent(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
                intent.addCategory("android.intent.category.DEFAULT");
                intent.setData(Uri.parse(String.format("package:%s",new Object[]{getApplicationContext().getPackageName()})));
                startActivityForResult(intent, 2000);
            } catch (Exception e) {
                Intent intent = new Intent();
                intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
                startActivityForResult(intent, 2000);
            }
        } else {
            ActivityCompat.requestPermissions(MainActivity.this, new String[]{WRITE_EXTERNAL_STORAGE,READ_EXTERNAL_STORAGE}, 333);
        }
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == 2000) {
            if (SDK_INT >= Build.VERSION_CODES.R) {
                if (Environment.isExternalStorageManager()) {

                    Toast.makeText(this, "Allow permissions granted", Toast.LENGTH_SHORT).show();

                } else {
                    Toast.makeText(this, "Allow permission for storage access!", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode,permissions,grantResults);
        if (requestCode==333){
            if (grantResults.length > 0) {
                boolean WRITE_EXTERNAL_STORAGE = grantResults[0] == PackageManager.PERMISSION_GRANTED;
                boolean READ_EXTERNAL_STORAGE = grantResults[1] == PackageManager.PERMISSION_GRANTED;
                if (READ_EXTERNAL_STORAGE && WRITE_EXTERNAL_STORAGE) {

                    Toast.makeText(this, "All permissions granted", Toast.LENGTH_SHORT).show();

                } else {
                    Toast.makeText(this, "Allow permission for storage access!", Toast.LENGTH_SHORT).show();
                }
            }
        }
    }
}

Manifest File

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.rajkumarcreations.file">
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:requestLegacyExternalStorage="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

XML File

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"
        android:id="@+id/btn"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</androidx.constraintlayout.widget.ConstraintLayout>
user207421
  • 305,947
  • 44
  • 307
  • 483
Rajkumar
  • 79
  • 1
  • 5
  • `folder.listfiles() is returning null` For which directory? – blackapps Jun 18 '21 at 10:11
  • Try `File file = Environment.getExternalStorageDirectory();` As on an Android 11 device one can list root of external storage and you will obtain all public directories. (Also Download). ` And you do not need any permission doing so. – blackapps Jun 18 '21 at 10:19
  • You are sure null is returned and not an empty array? As i would rather expect an empty array. – blackapps Jun 18 '21 at 10:21
  • folder.listfiles() is returning for every directory – Rajkumar Jun 18 '21 at 17:04
  • ????????????????????? Is returning what? – blackapps Jun 18 '21 at 17:33
  • Listen when we call folder.listfiles() method so also it return an array of file objects okay but now folder.listfiles() method is returning null values in place of file object's array did you get? You can see in Mainactivity.java oncreate method's else block third line. – Rajkumar Jun 19 '21 at 01:55
  • You did not get me. And you did not answer my questions. And returning a null is something different as returning null values. The subject of your post still states that null is returned which i do not believe. And i did not hear you about empty array. – blackapps Jun 19 '21 at 06:32
  • So know the difference between allfiles==null and allfiles.length==0. The latter would be an empty array. – blackapps Jun 19 '21 at 06:35
  • Sir it is not executing the code folder.listFiles() so nothing is happening that was I mean ghat is not returning any pointer or array or list anything – Rajkumar Jun 21 '21 at 15:54
  • Do you mean that your app hangs on that statement? – blackapps Jun 21 '21 at 16:01
  • Yes my app terminate because of NullpointerExceprion on line MainActivity.java: on line this this this and did you get that – Rajkumar Jun 22 '21 at 06:10
  • actually I was creating an App which saves whatsapp status and I successfully created it but It was working till android 9 not on 10 and 11 so I got this error so that's why I was looking for – Rajkumar Jun 22 '21 at 06:16
  • I did not get it. How would that be possible?Please post the logcat. – blackapps Jun 22 '21 at 07:45
  • @blackapps returning null for every directory not returning empty array – Rajkumar Nov 23 '21 at 15:17
  • Before you do the listing add `if ( !file.exists()) return;` listFiles() returns null for non existing directories. – blackapps Nov 23 '21 at 16:07
  • And `if ( ! file.isDirectory()) return;`. Also please remove all import lines and all code concerning permissions. All obscures your problem. We do believe you have the permissions. – blackapps Nov 23 '21 at 16:08
  • `File.listFiles()` returns `null` under several documented circumstances, including doesn't exist, not a directory, and no read permissions. *Ergo* at least one of those conditions applies. – user207421 Mar 28 '22 at 06:01

2 Answers2

5

According to your requirement you were trying to access list of files under a directory by using listfiles() method. And want check it is working or not. But this returning null.

First, Declare the MANAGE_EXTERNAL_STORAGE permission in the manifest.

// For 30 and after
<uses-permission
    android:name="android.permission.MANAGE_EXTERNAL_STORAGE"
    tools:ignore="ScopedStorage" />

// For before 30
<uses-permission
    android:name="android.permission.READ_EXTERNAL_STORAGE"
    tools:node="merge" />
<uses-permission
    android:name="android.permission.STORAGE"
    tools:node="merge" />

// For 30 and after

Second, Use the ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION intent action to direct users to a system settings page where they can enable the following option for your app: Allow access to manage all files.

Write the code on your onCreate Method:

if (Build.VERSION.SDK_INT < 30) {
    if (!checkBefore30()) {
        requestBefore30();
    } else { 
      // User granted file permission, Access your file
      readFiles();
    }
  } else if (Build.VERSION.SDK_INT >= 30) {
    check30AndAfter();
  } else {
    // User already has file access permission
    readFiles();
}

Write those methods on your Activity:

private boolean checkBefore30() {
     return ContextCompat.checkSelfPermission(YourActivity.this,
         Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED;
}


private void requestBefore30() {
   if(ActivityCompat.shouldShowRequestPermissionRationale(YourActivity.this, Manifest.permission.READ_EXTERNAL_STORAGE)) {
                    Toast.makeText(LoginActivity.this, "Storage permission required. Please allow this permission", Toast.LENGTH_LONG).show();
                    ActivityCompat.requestPermissions(YourActivity.this, 
                            new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
                } else {
                    ActivityCompat.requestPermissions(YourActivity.this, 
                            new String[]{android.Manifest.permission.READ_EXTERNAL_STORAGE}, 100);
   }
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    switch (requestCode) {
        case 100:
            if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission for storage access successful!
                // Read your files now
            } else {
                // Allow permission for storage access!
            }
            break;
    }
}


@RequiresApi(api = Build.VERSION_CODES.R)
private void check30AndAfter() {
    if (!Environment.isExternalStorageManager()) {
        try {
            Intent intent = new Intent(Settings.ACTION_MANAGE_APP_ALL_FILES_ACCESS_PERMISSION);
            intent.addCategory("android.intent.category.DEFAULT");
            intent.setData(Uri.parse(String.format("package:%s", getApplicationContext().getPackageName())));
            startActivityForResult(intent, 200);
        } catch (Exception e) {
            Intent intent = new Intent();
            intent.setAction(Settings.ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION);
            startActivityForResult(intent, 200);
        }
    }
}

@RequiresApi(api = Build.VERSION_CODES.R)
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 200) {
        if (30 >= Build.VERSION_CODES.R) {
            if (Environment.isExternalStorageManager()) {
                // Permission for storage access successful!
                // Read your files now
            } else {
                // Allow permission for storage access!
            }
        }
    }
}


private void readFiles() {
        File file;
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString());
        } else {
            file = new File(Environment.getExternalStorageDirectory().toString() + "/Download/");
        }
        File[] files= null;
        files= file.listFiles();
        if (file.exists()) {
            //  files exist
        }
        if (allfiles != null) {
            Toast.makeText(this, " file length is" + files.length, Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "No files", Toast.LENGTH_SHORT).show();
        }
    }

Hopefully your problem will be solved.

Subarata Talukder
  • 5,407
  • 2
  • 34
  • 50
  • Thanks, you save my day. Your source code works but it remains validating use of MANAGE_EXTERNAL_STORAGE by Google Play Console :) – Djen Nik Jan 12 '23 at 14:38
1

Try with the following code it's working.

 //Add below permission in your manifest file
 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
 <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


//Add below attribute in manifest application tag
 android:requestLegacyExternalStorage="true"

//Activity code, ask file read/write runtime permission
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
    requestForPermission();
    getFile();
}

private void getFile() {
    File file;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
        file = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).toString());
    } else {
        file = new File(Environment.getExternalStorageDirectory().toString() + "/Download/");
    }
    File[] allfiles = null;
    allfiles = file.listFiles();
    if (file.exists()) {
        tv.setText("Exist");
    }
    if (allfiles != null) {
        Toast.makeText(this, "length is " + allfiles.length, Toast.LENGTH_SHORT).show();
    } else {
        Toast.makeText(this, "Array is null", Toast.LENGTH_SHORT).show();
    }
}

private void requestForPermission() {
    ActivityCompat.requestPermissions(
            this,
            new String[]{
                    android.Manifest.permission.READ_EXTERNAL_STORAGE,
                    android.Manifest.permission.WRITE_EXTERNAL_STORAGE
            },
            101
    );
}


@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case 101:
            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                getFile();
            } else {
                //not granted
            }
            break;
        default:
            break;
    }
}
}
matdev
  • 4,115
  • 6
  • 35
  • 56
Dharmender Manral
  • 1,504
  • 1
  • 6
  • 7
  • 1
    okay but if I give the path /storage/emulated/0/whatsapp/Media/.statuses then???? actually I was creating an App which saves whatsapp status and I successfully created it but It was working till android 9 not on 10 and 11 so I got this error so that's why I was looking for – Rajkumar Jun 22 '21 at 06:14
  • hi did you resolve it? – Vivek Oct 07 '21 at 08:47
  • No I did not resolve it till now – Rajkumar Nov 23 '21 at 15:19