Android 无法在Oreo上拾取文件

Android 无法在Oreo上拾取文件,android,file-permissions,android-8.0-oreo,filepicker,Android,File Permissions,Android 8.0 Oreo,Filepicker,在Android Nougat及以下版本上,我可以使用以下代码在我的存储中获取一些文件: Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT); chooseFile.setType("*/*.jpg"); chooseFile = Intent.createChooser(chooseFile, "Choose a file"); startActivityForResult(chooseFile, 111); 并使用以下命令获取

在Android Nougat及以下版本上,我可以使用以下代码在我的存储中获取一些文件:

Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*.jpg");
chooseFile = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(chooseFile, 111);
并使用以下命令获取文件路径:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == 111 && resultCode == RESULT_OK && data.getData() != null)
       String path = data.getData().getPath();

}

但在Android Oreo上,这是行不通的。文件选择器出现了,但我甚至无法使用默认的文件选择器拾取文件。一开始,我以为这是和。但是在我添加了在运行时读写外部存储的权限并被授予之后,这个问题仍然发生。

因为OREO上的默认文件选择器很麻烦,所以目前我正在使用自定义类来选择文件或目录。另一个解决方案是您可以使用ES文件资源管理器等,但并非所有用户都有,主要问题仍然存在

public class FileChooser {

    private Activity activity;
    private Item[] fileList;
    private File path;

    private boolean rootDir  = true; //check if the current directory is rootDir
    private boolean pickFile = true; //flag to get directory or file

    private String title = "";
    private String upTitle = "Up";
    private String positiveTitle = "Choose Path";
    private String negativeTitle = "Cancel";

    private ListAdapter adapter;
    private ArrayList<String> str = new ArrayList<>(); //Stores names of traversed directories, to detect rootDir
    private Listener listener;

    /**
     * @param pickFile true for file picker and false for directory picker
     * */
    public FileChooser(Activity activity, boolean pickFile, Listener fileChooserListener) {
        this.activity = activity;
        this.pickFile = pickFile;
        this.listener = fileChooserListener;
        title = pickFile ? "Choose File" : "Choose Directory";
        path = new File(String.valueOf(Environment.getExternalStorageDirectory()));
    }


    /**
     * The view of your file picker
     * */
    public void openDirectory() {
        loadFileList();
        AlertDialog.Builder builder = new AlertDialog.Builder(activity, AlertDialog.THEME_DEVICE_DEFAULT_DARK);
        if (fileList == null)
            builder.create();

        builder.setTitle(title + "\n" + path.toString());
        builder.setAdapter(adapter, new DialogInterface.OnClickListener() {
            @Override
            public void onClick(DialogInterface dialog, int position) {
                String chosenFile = fileList[position].file;
                File selectedFile = new File(path + File.separator + chosenFile);

                if (selectedFile.isDirectory()) { // user click on folder
                    rootDir = false;
                    str.add(chosenFile); // Adds chosen directory to list
                    path = selectedFile;
                    openDirectory();
                }
                else if (chosenFile.equalsIgnoreCase(upTitle) && !selectedFile.exists()) { // 'up' was clicked
                    String s = str.remove(str.size() - 1); // present directory
                    path = new File(
                            path.toString().substring(0, path.toString().lastIndexOf(s))); // exclude present directory
                    if (str.isEmpty()) // no more directories in the list, rootDir
                        rootDir = true;
                    openDirectory();

                }
                else if (listener != null && pickFile)
                    listener.onSelectedPath(selectedFile.getAbsolutePath());

            }
        });

        if (!pickFile) {
            builder.setPositiveButton(positiveTitle, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialogInterface, int i) {
                    if (listener != null)
                        listener.onSelectedPath(path.getPath());
                }
            });
        }
        builder.setNegativeButton(negativeTitle, null);
        builder.show();
    }

    /**
     * Setup your file picker data
     * */
    private void loadFileList() {
        fileList = null;
        if (path.exists()) {
            FilenameFilter filter = new FilenameFilter() {
                @Override
                public boolean accept(File dir, String filename) {
                    File file = new File(dir, filename);
                    // Filters based on whether the file is hidden or not
                    return ((pickFile && file.isFile()) || file.isDirectory()) && !file.isHidden();
                }
            };

            String[] fList = path.list(filter); //set filter
            if (fList != null) {
                fileList = new Item[fList.length];
                for (int i = 0; i < fList.length; i++)
                    fileList[i] = new Item(fList[i], new File(path, fList[i]).isDirectory() ?
                            R.drawable.ic_folder : R.drawable.ic_file); //set icon, directory or file

                if (!rootDir) {
                    Item temp[] = new Item[fileList.length + 1];
                    System.arraycopy(fileList, 0, temp, 1, fileList.length);
                    temp[0] = new Item(upTitle, R.drawable.ic_undo);
                    fileList = temp;
                }
            }

        } else
            path = new File(String.valueOf(Environment.getExternalStorageDirectory()));

        try {
            adapter = new ArrayAdapter<Item>(activity,
                    android.R.layout.select_dialog_item, android.R.id.text1,
                    fileList) {
                @NonNull
                @Override
                public View getView(int position, View convertView, @NonNull ViewGroup parent) {
                    // creates view
                    View view = super.getView(position, convertView, parent);
                    TextView textView = view.findViewById(android.R.id.text1);
                    textView.setTextColor(Color.WHITE);

                    // put the image on the text view
                    textView.setCompoundDrawablesWithIntrinsicBounds(fileList[position].icon, 0, 0, 0);

                    // add margin between image and text (support various screen densities)
                    int dp5 = (int) (5 * activity.getResources().getDisplayMetrics().density + 0.5f);
                    textView.setCompoundDrawablePadding(dp5);

                    return view;
                }
            };
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    private class Item {
        public String file;
        public int icon;

        private Item(String file, Integer icon) {
            this.file = file;
            this.icon = icon;
        }

        @Override
        public String toString() {
            return file;
        }
    }

    public interface Listener {
        void onSelectedPath(String path);
    }

}
公共类文件选择器{
私人活动;
私有项[]文件列表;
私有文件路径;
private boolean rootDir=true;//检查当前目录是否为rootDir
private boolean pickFile=true;//获取目录或文件的标志
私有字符串title=“”;
私有字符串upTitle=“Up”;
私有字符串positiveTitle=“选择路径”;
私有字符串negativeTitle=“取消”;
专用列表适配器;
private ArrayList str=new ArrayList();//存储已遍历目录的名称,以检测rootDir
私人倾听者;
/**
*@param pickFile true表示文件选择器,false表示目录选择器
* */
公共文件选择器(活动、布尔选取文件、侦听器文件选择器侦听器){
这个。活动=活动;
this.pickFile=pickFile;
this.listener=fileChooserListener;
title=pickFile?“选择文件”:“选择目录”;
path=新文件(String.valueOf(Environment.getExternalStorageDirectory());
}
/**
*文件选择器的视图
* */
public void openDirectory(){
loadFileList();
AlertDialog.Builder=新建AlertDialog.Builder(活动,AlertDialog.THEME\u设备\u默认值\u暗);
if(fileList==null)
builder.create();
builder.setTitle(title+“\n”+path.toString());
setAdapter(适配器,新的DialogInterface.OnClickListener(){
@凌驾
公共void onClick(对话框接口对话框,int位置){
字符串chosenFile=fileList[position].file;
File selectedFile=新文件(path+File.separator+chosenFile);
如果(selectedFile.isDirectory()){//用户单击文件夹
rootDir=false;
str.add(chosenFile);//将所选目录添加到列表中
路径=所选文件;
openDirectory();
}
如果单击了(chosenFile.equalsIgnoreCase(upTitle)&&!selectedFile.exists()){/'up'
字符串s=str.remove(str.size()-1);//当前目录
路径=新文件(
path.toString().substring(0,path.toString().lastIndexOf(s));//排除当前目录
if(str.isEmpty())//列表中没有更多目录,则为rootDir
rootDir=true;
openDirectory();
}
else if(侦听器!=null&&pickFile)
onSelectedPath(selectedFile.getAbsolutePath());
}
});
如果(!pickFile){
setPositiveButton(positiveTitle,新的DialogInterface.OnClickListener()对话框){
@凌驾
公共void onClick(DialogInterface,inti){
if(侦听器!=null)
onSelectedPath(path.getPath());
}
});
}
builder.setNegativeButton(negativeTitle,null);
builder.show();
}
/**
*设置文件选择器数据
* */
私有void loadFileList(){
fileList=null;
if(path.exists()){
FilenameFilter筛选器=新建FilenameFilter(){
@凌驾
公共布尔接受(文件目录,字符串文件名){
文件=新文件(目录,文件名);
//根据文件是否隐藏进行筛选
return((pickFile&&file.isFile())| | file.isDirectory())&&!file.ishiden();
}
};
字符串[]fList=path.list(过滤器);//设置过滤器
如果(fList!=null){
fileList=新项[fList.length];
for(int i=0;i