【问题标题】:File.listFiles() is returning null in android 11folder.listfiles() 在 android 11 中返回 null
【发布时间】:2021-09-03 01:18:17
【问题描述】:

我正在创建一个应用程序来测试 listfiles() 方法是否正常工作以检查这个我创建了一个应用程序并在那里使用了 t 但这会返回 null 来代替数组。 这是我的完整代码,请帮忙,我已授予 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();
                }
            }
        }
    }
}

清单文件

<?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 文件

<?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>

【问题讨论】:

  • folder.listfiles() is returning null 为哪个目录?
  • 试试File file = Environment.getExternalStorageDirectory(); 在Android 11 设备上,您可以列出外部存储的根目录,您将获得所有公共目录。 (也下载)。 ` 这样做不需要任何许可。
  • 您确定返回的是 null 而不是空数组?因为我宁愿期待一个空数组。
  • folder.listfiles() 正在为每个目录返回
  • ?????????????????????退货是什么?

标签: java android android-11


【解决方案1】:

尝试使用以下代码,它正在工作。

 //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[]{
                    Manifest.permission.READ_EXTERNAL_STORAGE,
                    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;
    }
}
}

【讨论】:

  • 好的,但是如果我给出路径 /storage/emulated/0/whatsapp/Media/.statuses 那么????实际上我正在创建一个保存whatsapp状态的应用程序并且我成功创建了它但是它一直工作到android 9而不是10和11所以我收到了这个错误所以这就是我正在寻找的原因
  • 嗨,你解决了吗?
  • 不,我直到现在才解决它
【解决方案2】:

根据您的要求,您尝试使用 listfiles() 方法访问目录下的文件列表。并想检查 它是否工作。但是这会返回 null

首先,在清单中声明 MANAGE_EXTERNAL_STORAGE 权限。

// 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" />

// 30岁及以后

其次,使用 ACTION_MANAGE_ALL_FILES_ACCESS_PERMISSION 意图 将用户引导至可以启用的系统设置页面的操作 为您的应用选择以下选项:允许访问以管理所有文件。

在你的 onCreate 方法上写代码:

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

在你的 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();
        }
    }

希望您的问题能够得到解决。

【讨论】:

    【解决方案3】:

    将此添加到 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]);
    }
    

    使用androidSDK>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);
       }
    

    如果您仍然有问题,那是因为您设置了 Target API 29 或更高版本。然后将此属性添加到您的 AndroidManifest.xml 文件的应用程序标签中,它将起作用。

    android:requestLegacyExternalStorage="true"
    

    根据 Google 应用兼容性功能进行数据存储:

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

    • 面向 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 来选择该行为。

    【讨论】:

      猜你喜欢
      • 2022-06-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-25
      相关资源
      最近更新 更多