2

On Android Nougat and below, I can simply get some file on my storage using this code :

Intent chooseFile = new Intent(Intent.ACTION_GET_CONTENT);
chooseFile.setType("*/*.jpg");
chooseFile = Intent.createChooser(chooseFile, "Choose a file");
startActivityForResult(chooseFile, 111);

And get the file path using :

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

}

But on Android Oreo, this is not working. The file picker is showing up, but I cannot even pick the file using the default file picker. At first, I thought that this is related to permission. But after I add the permission to READ and WRITE external storage on runtime, and granted, this problem still occurred.

Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
  • `"The file picker is showing up, but I cannot even pick the file using the default file picker."` why you cannot? `onActivityResult()` is not called or what? or `resultCode != RESULT_OK` ? – pskink Jun 21 '18 at 06:05
  • It's like listview or button, but without onClick method. I simply cannot click it, and onActivityResult will never get called. – Wahyu Anggara Raya Jun 21 '18 at 06:08
  • i have no idea what you are talking about... what button? what onClick? – pskink Jun 21 '18 at 06:09
  • The button and listview are the metaphors. I just cannot click the file on my device(default) file picker – Wahyu Anggara Raya Jun 21 '18 at 06:10
  • Is the issue raised because of Recent dialog ? – Shree Krishna Jun 21 '18 at 06:33
  • tried `ACTION_PICK` or `ACTION_OPEN_DOCUMENT` ? – pskink Jun 21 '18 at 06:39
  • The same result when using ACTION_OPEN_DOCUMENT. And with ACTION_PICK, I've got toast 'No apps can perform this action' and RESULT_CANCELED onActivityResult(). My device is Huawei MHA-L29 and using 'Internal Storage'. – Wahyu Anggara Raya Jun 21 '18 at 06:56
  • use `chooseFile.setType("image/jpg");` – pskink Jun 21 '18 at 06:58
  • I think the main problem comes from my default file manager. Since using the ES File browser and the Gallery are working fine. But what if my user also uses their default file manager and not working, that's my only concern. Thanks all, currently I'm using third party library from GitHub to fix this problem. – Wahyu Anggara Raya Jun 22 '18 at 07:44
  • did you found any solution ..we are also facing same issue.. can you help us –  Jul 24 '18 at 06:38
  • Please see my answer below. Since I cannot post the source code in the comment section. Hope it can help you. hehe – Wahyu Anggara Raya Jul 24 '18 at 10:41

1 Answers1

1

Since the default file picker on OREO is troublesome, currently I'm using a custom class to pick file or directory. Another solution is you can use ES File Explorer, etc, but not all of your user has it and the main problem still occurred.

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

}