Simple Android File Chooser

By , 3 June 2015

Simple Android File Chooser
Simple Android File Chooser

Surprisingly, the Android API doesn't include a file chooser. I'm not sure why that is, I guess the developers don't want to make the assumption that the device has a user filesystem available. Anyway, it's not my job to speculate on what the Android developers talk about over lunch. I just need a file chooser.

It seems like there are a few options out there but I wanted something uber simple and ultra light. It's just for users to select an import file.

My solution is a single Java class utilising regular android Dialog and ListViews. It just wires up the event handlers to read from the disk and refresh the list. You provide a FileSelectedListener implementation to handle the file selection event. Menial stuff that you don't want to bother implementing yourself. It can be used like this:

new FileChooser(activity).setFileListener(new FileSelectedListener() {
    @Override public void fileSelected(final File file) {
        // do something with the file
    }).showDialog();

Here is the FileChooser class which you can cut and paste into your project. Public domain code so do what you want with it.

Peace.

Simple Android File Chooser
package au.com.ninthavenue.patterns.android.dialogs;

import android.app.Activity;
import android.app.Dialog;
import android.os.Environment;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import android.widget.TextView;
import java.io.File;
import java.io.FileFilter;
import java.util.Arrays;

public class FileChooser {
    private static final String PARENT_DIR = "..";

    private final Activity activity;
    private ListView list;
    private Dialog dialog;
    private File currentPath;

    // filter on file extension
    private String extension = null;
    public void setExtension(String extension) {
        this.extension = (extension == null) ? null :
                extension.toLowerCase();
    }

    // file selection event handling
    public interface FileSelectedListener {
        void fileSelected(File file);
    }
    public FileChooser setFileListener(FileSelectedListener fileListener) {
        this.fileListener = fileListener;
        return this;
    }
    private FileSelectedListener fileListener;

    public FileChooser(Activity activity) {
        this.activity = activity;
        dialog = new Dialog(activity);
        list = new ListView(activity);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override public void onItemClick(AdapterView<?> parent, View view, int which, long id) {
                String fileChosen = (String) list.getItemAtPosition(which);
                File chosenFile = getChosenFile(fileChosen);
                if (chosenFile.isDirectory()) {
                    refresh(chosenFile);
                } else {
                    if (fileListener != null) {
                        fileListener.fileSelected(chosenFile);
                    }
                    dialog.dismiss();
                }
            }
        });
        dialog.setContentView(list);
        dialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        refresh(Environment.getExternalStorageDirectory());
    }

    public void showDialog() {
        dialog.show();
    }


    /**
     * Sort, filter and display the files for the given path.
     */
    private void refresh(File path) {
        this.currentPath = path;
        if (path.exists()) {
            File[] dirs = path.listFiles(new FileFilter() {
                @Override public boolean accept(File file) {
                    return (file.isDirectory() && file.canRead());
                }
            });
            File[] files = path.listFiles(new FileFilter() {
                @Override public boolean accept(File file) {
                    if (!file.isDirectory()) {
                        if (!file.canRead()) {
                            return false;
                        } else if (extension == null) {
                            return true;
                        } else {
                            return file.getName().toLowerCase().endsWith(extension);
                        }
                    } else {
                        return false;
                    }
                }
            });

            // convert to an array
            int i = 0;
            String[] fileList;
            if (path.getParentFile() == null) {
                fileList = new String[dirs.length + files.length];
            } else {
                fileList = new String[dirs.length + files.length + 1];
                fileList[i++] = PARENT_DIR;
            }
            Arrays.sort(dirs);
            Arrays.sort(files);
            for (File dir : dirs) { fileList[i++] = dir.getName(); }
            for (File file : files ) { fileList[i++] = file.getName(); }

            // refresh the user interface
            dialog.setTitle(currentPath.getPath());
            list.setAdapter(new ArrayAdapter(activity, 
                   android.R.layout.simple_list_item_1, fileList) {
                       @Override public View getView(int pos, View view, ViewGroup parent) {
                           view = super.getView(pos, view, parent);
                           ((TextView) view).setSingleLine(true);
                           return view;
                       }
                   });
        }
    }


    /**
     * Convert a relative filename into an actual File object.
     */
    private File getChosenFile(String fileChosen) {
        if (fileChosen.equals(PARENT_DIR)) {
            return currentPath.getParentFile();
        } else {
            return new File(currentPath, fileChosen);
        }
    }
}

About Roger Keays

Simple Android File Chooser

Roger Keays is an artist, an engineer, and a student of life. He has no fixed address and has left footprints on 40-something different countries around the world. Roger is addicted to surfing. His other interests are music, psychology, languages, the proper use of semicolons, and finding good food.

Leave a Comment

Please visit https://rogerkeays.com/simple-android-file-chooser to add your comments.

Comment posted by: Jay Dove, yesterday

Hey Man.  I would really love if I could implement this into my project.  I'm a complete noob and could use some extra help.  Does the entire script go into mainactivity.java?..  and where exactly?

Comment posted by: Awali Muistwa (Atramega Dynamics), 5 years ago

When you understand the following trick, you may ignore everything else:

Like my page http://www.facebook.com/atramegadynamics/

public int REQCODE_SAVEFILE_ = 0; //make this special
public void openFile_(){
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("*/*");
    //intent.putExtra(Intent.EXTRA_MIME_TYPES, "*/*");
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    intent.putExtra(Intent.EXTRA_LOCAL_ONLY, true);
    startActivityForResult(intent, REQCODE_OPENFILE);

}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == REQCODE_SAVEFILE_) {
        if (resultCode == Activity.RESULT_OK && data != null) {
            Uri file_uri = data.getData();
            //Globals.saveFile(file_uri, getAll_ringItems(), the_context);//this.getApplicationContext());
        }
    }
}
public static boolean saveFile(Uri file_uri, String data, Context context){
    try {
        android.os.ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(file_uri, "w");
        java.io.FileOutputStream fos = new java.io.FileOutputStream( pfd.getFileDescriptor() );
        fos.write(data.getBytes());
        fos.close();
        fos.flush();
        pfd.close();
        return true;
    } catch (Exception e) {
        //Toast.makeText(context.getApplicationContext(), e.getMessage(),Toast.LENGTH_SHORT);
    }
    return false;
}
Comment posted by: Awali Muistwa (Atramega Dynamics), 5 years ago

Hello friends. I updated the file to cater for more feature. \

[code]
package com.atramega.schbell;
import android.Manifest;
import android.app.Dialog;
import android.content.Context;
import android.content.pm.PackageManager;
import android.graphics.drawable.Drawable;
import android.os.Environment;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;

import java.io.File;
import java.io.FileFilter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class FileChooser {
    private static final String PARENT_DIR = "..";

    private Context the_context;
    private ListView listView;
    private Dialog dialog;
    private File currentPath;
    private String title = "Choose File";
    private boolean dirsOnly = false;
    private boolean canShow = true;
    private boolean excludeDotPrefixDirs = false;
    private boolean excludeDotPrefixFiles = false;

    private String extension = null;
    private FileChosenListener fileChosenListener;
    public interface FileChosenListener {
        void onFileChosen(File file);
    }

    public FileChooser setFileChosenListener(FileChosenListener fileChosenListener) {
        this.fileChosenListener = fileChosenListener;
        return this;
    }

    public  FileChooser(final Context context){
        this.the_context = context;
        dialog = new Dialog( context );
        listView = new ListView(context);
        dialog.setContentView(listView );
        dialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        if(  (ContextCompat.checkSelfPermission(the_context, Manifest.permission.READ_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED)
            || (ContextCompat.checkSelfPermission(the_context, Manifest.permission.WRITE_EXTERNAL_STORAGE)!= PackageManager.PERMISSION_GRANTED) ){
            String msg = "First setup Storage permissions in Settings - Apps - "+the_context.getString(R.string.app_name)+" - permissions";
            Toast.makeText(the_context, msg, Toast.LENGTH_LONG);
            Toast.makeText(the_context, msg, Toast.LENGTH_LONG);
            Toast.makeText(the_context, msg, Toast.LENGTH_LONG);
            canShow = false;
        }
    }

    public void setExtension(String extension) {
        this.extension = (extension == null) ? null :
                extension.toLowerCase();
    }
    public void setDirsOnly(boolean val){
        this.dirsOnly = val;
    }
    public void excludeDotPrefixDirs(boolean val){
        this.excludeDotPrefixDirs = val;
    }

    public void excludeDotPrefixFiles(boolean val){
        this.excludeDotPrefixFiles = val;
    }

    public void setTitle(String title){
        this.title = title;
    }
    public void showDialog() {
        if(canShow){
            refresh(Environment.getExternalStoragePublicDirectory(""));
            dialog.show();
        }
    }


    private File[] getDirsUnder(File path){
        File[] dirs = path.listFiles(new FileFilter() {
            @Override public boolean accept(File file) {
                return (file.isDirectory() );//&& file.canRead());
            }
        });
        return dirs;
    }
    private File[] getFilesUnder(File path){
        File[] files = path.listFiles(new FileFilter() {
            @Override public boolean accept(File file) {
                if (!file.isDirectory()) {
                    //if (!file.canRead()) {return false;} else
                    if (extension == null) {
                        return true;
                    } else {
                        return file.getName().toLowerCase().endsWith(extension);
                    }
                } else {
                    return false;
                }
            }
        });
        return files;
    }

    /**
     * Sort, filter and display the files for the given path.
     */
    private void refresh(File path) {
        this.currentPath = path;
        if (path.exists()) {
            File[] dirs = getDirsUnder(path);
            File[] files = getFilesUnder(path);
            Arrays.sort(dirs);
            Arrays.sort(files);
            ArrayList<File> fileList = new ArrayList<>();
            fileList.add(null); //item 0 for the heading
            if(path.getParentFile() != null && path.getParentFile().canRead()) { //this parrent be used used as item 1
                fileList.add( path.getParentFile() );
            } else {
                fileList.add(null); //item 1 does no
            }
            for (File dir : dirs) {
                if( !(excludeDotPrefixDirs && dir.getName().startsWith(".")) ){ fileList.add(dir); }
            }
            if(!dirsOnly){
                for (File file : files ) {
                    if( !(excludeDotPrefixFiles && file.getName().startsWith(".")) ){ fileList.add(file); }
                }
            }
            listView.setBackgroundColor(the_context.getColor(R.color.atramegaLightGray));
            listView.setAdapter(new FileArrayAdapter(the_context, 0, fileList));
        }
    }
    /**
     * Convert a relative filename into an actual File object.
     */
    private File getChosenFile(String fileChosen) {
        if (fileChosen.equals(PARENT_DIR)) {
            return currentPath.getParentFile();
        } else {
            return new File(currentPath, fileChosen);
        }
    }
    //custom ArrayAdapter
    public class FileArrayAdapter extends ArrayAdapter<File> {
        public Context context;
        public List<File> myFileList;
        public FileArrayAdapter(Context contex, int resourc, ArrayList<File> myFileLis) {
            super(contex, resourc, myFileLis);
            this.context = contex;
            this.myFileList = myFileLis;
        }

        //called when rendering the list
        public View getView(final int position, final View convertView, ViewGroup parent) {
            LinearLayout linearLayout = new LinearLayout(the_context);
            linearLayout.setOrientation( LinearLayout.HORIZONTAL );
            linearLayout.setPadding(10, 10, 5, 5);
            linearLayout.setDividerPadding(5);
            ////////////////////////
            TextView name_textView = new TextView(the_context);
            name_textView.setTextColor( the_context.getColor(R.color.atramegaBlack) );
            name_textView.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);
            name_textView.setHeight(40);
            name_textView.setTextSize(18);
            ///////////////////////////
            ImageView dir_imageButton = new ImageView(the_context);
            dir_imageButton.setImageDrawable( the_context.getDrawable(android.R.drawable.sym_contact_card) );
            dir_imageButton.setVisibility( View.INVISIBLE );
            ////////////////////////////////
            ImageView file_imageButton = new ImageView(the_context);
            file_imageButton.setImageDrawable( the_context.getDrawable(android.R.drawable.stat_notify_chat) );
            file_imageButton.setPadding(10, 0, 0, 0);
            file_imageButton.setVisibility( View.GONE );
            ////////////////////////////////
            linearLayout.addView(dir_imageButton);
            linearLayout.addView(file_imageButton);
            linearLayout.addView(name_textView);
            //////////////////////////////
            if(position==0) { //heading
                name_textView.setText(title);
                name_textView.setTextAlignment( View.TEXT_ALIGNMENT_CENTER );
                name_textView.setTextColor(the_context.getColor(R.color.atramegaWhite));
                linearLayout.setBackgroundColor(the_context.getColor(R.color.atramegaBlue));
                return linearLayout;
            } else { //directories and files
                if( null != myFileList.get(position)) {
                    final File fileItem = myFileList.get(position);
                    name_textView.setText( "   "+fileItem.getName() );
                    if (fileItem.isDirectory()) {
                        if (position == 1) { //parent directory
                            name_textView.setTextColor(the_context.getColor(R.color.atramegaBlue) );
                            linearLayout.setBackgroundColor(the_context.getColor(R.color.atramegaLightBlue));
                        } else { //other directories
                            dir_imageButton.setVisibility( View.VISIBLE );
                            file_imageButton.setVisibility( View.GONE );
                        }
                    } else { //files
                        dir_imageButton.setVisibility( View.GONE );
                        file_imageButton.setVisibility( View.VISIBLE );
                    }

                    if(!fileItem.canRead()) {
                        name_textView.setTextColor( the_context.getColor(R.color.atramegaGray));
                        linearLayout.setEnabled(false);
                    }
                    linearLayout.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                                if (fileItem.isDirectory()) {
                                    refresh(fileItem);
                                } else {
                                    if (fileChosenListener != null) {
                                        fileChosenListener.onFileChosen(fileItem);
                                    }
                                    dialog.dismiss();
                                }
                        }
                    });
                    if (dirsOnly && fileItem.isDirectory()) {
                        linearLayout.setOnLongClickListener(new View.OnLongClickListener() {
                            @Override
                            public boolean onLongClick(View view) {
                                    if (fileChosenListener != null) {
                                        fileChosenListener.onFileChosen(fileItem);
                                    }
                                    dialog.dismiss();
                                return false;
                            }
                        });
                    }
                } else {
                    linearLayout.removeAllViews();
                    File[] dirs = context.getExternalFilesDirs(null);
                    String[] names = {"Internal Storage", "SD Card", "External Storage 2"}; int i = 0;
                    for( File dir: dirs) {
                        while(null != dir.getParentFile()  && dir.getParentFile().canRead()) {
                                dir = dir.getParentFile();
                        }
                        final File the_dir = dir;
                        Button button = new Button(the_context);
                        try {
                            button.setText( names[i++] );
                        }catch (IndexOutOfBoundsException iobe){}finally {}
                        button.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View view) {
                                refresh(the_dir);
                            }
                        });
                        linearLayout.addView(button);
                    }
                    return linearLayout;
                }
                return linearLayout;
            }
        }

    }

}

/*

        FileChooser fc = new FileChooser( the_context );
        fc.setTitle("Choose a File");
        fc.excludeDotPrefixDirs(true);
        fc.excludeDotPrefixFiles(true);
        fc.setFileChosenListener(new FileChooser.FileChosenListener() {
            @Override
            public void onFileChosen(final File chosenFile) {
                fillFromString( Globals.readFile(chosenFile) );
            }
        });
        fc.showDialog();

*/
[/code]

Comment posted by: Awali Muistwa (Atramega Dynamics), 5 years ago

Hello. Thanks a lot to every one. After going through the main post and one advice, i have come up with the following for those who want to pass context instead of activity. I found this important since I was using a fragment

package _YOUR PACKAGE_;
import android.app.Activity;
import android.app.Dialog;
import android.app.TimePickerDialog;
import android.content.Context;
import android.graphics.Color;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager.LayoutParams;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.TimePicker;

import java.io.File;
import java.io.FileFilter;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.Locale;
import java.util.TimeZone;

public class FileChooser {
    private static final String PARENT_DIR = "..";

    private Context the_context;
    private ListView list;
    private Dialog dialog;
    private File currentPath;

    // filter on file extension
    private String extension = null;
    public void setExtension(String extension) {
        this.extension = (extension == null) ? null :
                extension.toLowerCase();
    }

    // file selection event handling
    public interface FileSelectedListener {
        void fileSelected(File file);
    }
    public FileChooser setFileListener(FileSelectedListener fileListener) {
        this.fileListener = fileListener;
        return this;
    }
    private FileSelectedListener fileListener;
    public  FileChooser(Context context){
        this.the_context = context;
        dialog = new Dialog( context );
        list = new ListView(context);
        list.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
                String fileChosen = (String) list.getItemAtPosition(position);
                File chosenFile = getChosenFile(fileChosen);

                if (chosenFile.isDirectory()) {
                    refresh(chosenFile);
                } else {
                    if (fileListener != null) {
                        fileListener.fileSelected(chosenFile);
                    }
                    dialog.dismiss();
                }
            }
        });
        dialog.setContentView(list);
        dialog.getWindow().setLayout(LayoutParams.FILL_PARENT, LayoutParams.FILL_PARENT);
        refresh( Environment.getRootDirectory() );//getExternalStorageDirectory( ) );
    }

    public void showDialog() {
        dialog.show();
    }


    private File[] getDirsUnder(File path){
        File[] dirs = path.listFiles(new FileFilter() {
            @Override public boolean accept(File file) {
                return (file.isDirectory() && file.canRead());
            }
        });
        return dirs;
    }
    private File[] getFilesUnder(File path){
        File[] files = path.listFiles(new FileFilter() {
            @Override public boolean accept(File file) {
                if (!file.isDirectory()) {
                    if (!file.canRead()) {
                        return false;
                    } else if (extension == null) {
                        return true;
                    } else {
                        return file.getName().toLowerCase().endsWith(extension);
                    }
                } else {
                    return false;
                }
            }
        });
        return files;
    }
    /**
     * Sort, filter and display the files for the given path.
     */
    private void refresh(File path) {
        this.currentPath = path;
        if (path.exists()) {
            File[] dirs = getDirsUnder(path);
            File[] files = getFilesUnder(path);
            Arrays.sort(dirs);
            Arrays.sort(files);

            // convert to an array
            int i = 0;
            String[] fileList;
            if (path.getParentFile() == null || !path.getParentFile().canRead()) {
                fileList = new String[dirs.length + files.length];
            } else {
                fileList = new String[dirs.length + files.length + 1];
                fileList[i++] = PARENT_DIR;
            }

            for (File dir : dirs) { fileList[i++] = dir.getName(); }
            for (File file : files ) { fileList[i++] = file.getName(); }

            // refresh the user interface
            dialog.setTitle(currentPath.getPath());
            list.setAdapter( new ArrayAdapter(the_context,
                    android.R.layout.simple_list_item_1, fileList) {
                @Override public View getView(int pos, View view, ViewGroup parent) {
                    view = super.getView(pos, view, parent);
                    ((TextView) view).setSingleLine(true);
                    return view;
                }
            });
        }
    }
    /**
     * Convert a relative filename into an actual File object.
     */
    private File getChosenFile(String fileChosen) {
        if (fileChosen.equals(PARENT_DIR)) {
            return currentPath.getParentFile();
        } else {
            return new File(currentPath, fileChosen);
        }
    }
    
}

You can contact me on Facebook www.facebook.com/atramegadynamics/

Comment posted by: Harley Atwell, 5 years ago
aa首席阿里巴巴zzzzzzzzzzz
Comment posted by: HonJang Yang, 6 years ago

First of all, thans very much for your sharing, it is very helpful.

But, in the very first dialog display, first list item with ".." should not appear, because we can not ask parent of root to list files. 

If one tap on this ".." item, device will crash.

 

So I suggest make following fix in refresh():

replace


if (path.getParentFile() == null) {
    fileList = new String[dirs.length + files.length];
} else {
    fileList = new String[dirs.length + files.length + 1];
    fileList[i++] = PARENT_DIR;
}

with

if (path.getParentFile() == null || !path.getParentFile().canRead()) {
    fileList = new String[dirs.length + files.length];
} else {
    fileList = new String[dirs.length + files.length + 1];
    fileList[i++] = PARENT_DIR;
}
 

Comment posted by: Jeff Jennings, 6 years ago
Hi, My name is Jeff, I work as a Internet Marketing Consultant, and was doing research for another client when I came across your site rogerkeays.com. and thought I would message you on your contact form. After doing a quick analysis of your website, I noticed a couple of issues that are most likely causing people to leave without making contact. I really liked your website but noticed you weren't getting a lot of traffic to your site and your Alexa ranking wasn't as strong as it could be. http://OnTargetSEO.us I can get 1,000’s of visitors looking at rogerkeays.com, ready to buy your product, service or signup for your offer. Our advertising network of over 9000 websites provides a low cost and effective online marketing solution that actually works. We can help your business get more online quality traffic by advertising your business on websites that are targeted to your market. The internet is a vast entity and kick starting your online business doesn’t have to take a ridiculous amount of cash. We’ll send real people to see your web site starting almost immediately! In fact, I can get 10,000 highly targeted visitors to your website for as little as $29 just so you can test out our service. Right now to make things really exciting you can get 200,000 Targeted visitors to you site in 30 days for only $199. If you'd like to talk personally please give me a call at 480-457-0165 9 to 5 MST USA. I have a short video here that explains how everything works http://OnTargetSEO.us Best Regards, Jeff http://OnTargetSEO.us
Comment posted by: Rasta, 6 years ago

1st time that i just copy/paste sth and its work ! thanks a lot

Comment posted by: Xerus, 7 years ago

I made a few tweaks, because the original method was a bit unreadable and called path.listFiles() twice for no apparent reason:

if (path.exists() && path.canRead()) {
    // find em all
    TreeSet<String> dirs = new TreeSet<>();
    TreeSet<String> files = new TreeSet<>();
    for(File file : path.listFiles()) {
        if(!file.canRead())
            continue;
        if(file.isDirectory()) {
            dirs.add(file.getName());
        } else {
            if(extension == null || file.getName().toLowerCase().endsWith(extension))
                files.add(file.getName());
        }
    }

    // convert to an array
    ArrayList<String> fileList = new ArrayList<>(dirs.size() + files.size());
    if (path.getParentFile() != null)
        fileList.add(PARENT_DIR);
    fileList.addAll(dirs);
    fileList.addAll(files);

    // refresh the user interface
    dialog.setTitle(currentPath.getPath());
    list.setAdapter(new ArrayAdapter<String>(activity, android.R.layout.simple_list_item_1, fileList) {
        @Override public View getView(int pos, View view, ViewGroup parent) {
            view = super.getView(pos, view, parent);
            ((TextView) view).setSingleLine(true);
            return view;
        }
    });
} else {
    list.setAdapter(new ArrayAdapter<>(activity, android.R.layout.simple_list_item_1, new String[]{"Can't access "+path}));
}

Oh and by the way, you should address the new permission issues with Android 6.0

Comment posted by: iliyan s, 7 years ago

Brian Young,

have you got this in manifest?

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Comment posted by: Godwin, 7 years ago
Nice! Really help me.
Comment posted by: Marcin Szydłowski, 7 years ago

Many thanks for this topic!

Comment posted by: }}}}}}}}}}}}}}}}}}}}, 7 years ago

Ai uitat o acolada pisa-m-as pe mortii matii

Comment posted by: Giancarlo, 7 years ago

Just had to say:

Thank you for sharing, helped me a lot.

Comment posted by: fredchamp, 7 years ago

Well, just to say thanks.

Simple and efficient

 

Comment posted by: , 8 years ago

Hey @Robot Maxwell. Thanks for the patch. It looks like path.listFiles() is returning null in your case. The javadoc says "The array will be empty if the directory is empty. Returns null if this abstract pathname does not denote a directory, or if an I/O error occurs."

So I think this code should work if the directory is empty, but will probably crash if Environment.getExternalStorageDirectory() does not return a valid directory. What happens if you change:

        if (path.exists()) {

to

        if (path.exists() && path.isDirectory()) {

?

 

Comment posted by: Robot Maxwell, 8 years ago

Roger you have a nasty error in your code, when the sdcard is "empty" it will crash. I had to bolster it up with a bit of checking thus:

 

~            // convert to an array
            int i = 0;
            int j = 0;
            int k = 0;
         if(dirs!=null && dirs.length>0)
             j = dirs.length;
         if(files!=null && files.length>0)
             k = files.length;
            String[] fileList;
            if (path.getParentFile() == null) {
                fileList = new String[j + k];
            } else {
                //fileList = new String[dirs.length + files.length + 1];
                fileList = new String[j + k + 1];
                fileList[i++] = PARENT_DIR;
            }
            if(dirs!=null && dirs.length>0) {
                Arrays.sort(dirs);
             for (File dir : dirs) { fileList[i++] = dir.getName(); }}
         if(files!=null && files.length>0){
                Arrays.sort(files);
              for (File file : files ) { fileList[i++] = file.getName(); }}
 

 

Comment posted by: Prathap, 8 years ago

Really Useful code for many Android Developers.

Great step by step solution, thanks for the help!

Comment posted by: Shadilan, 8 years ago

Great! Thanks alot you save my time!

Comment posted by: alessandro, 8 years ago

Marthono, it gave the same error to me. Just substitute this line:

FileChooser(this.getParent())

with this:

FileChooser(this)

and it worked for me.

Comment posted by: Martono, 8 years ago

it gives error :

06-15 03:43:31.038 24606-24606/on4shop.androidapp E/AndroidRuntime: FATAL EXCEPTION: main
                                                                    Process: on4shop.androidapp, PID: 24606
                                                                    java.lang.IllegalStateException: Could not execute method for android:onClick
                                                                        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:293)
                                                                        at android.view.View.performClick(View.java:4438)
                                                                        at android.view.View$PerformClick.run(View.java:18422)
                                                                        at android.os.Handler.handleCallback(Handler.java:733)
                                                                        at android.os.Handler.dispatchMessage(Handler.java:95)
                                                                        at android.os.Looper.loop(Looper.java:136)
                                                                        at android.app.ActivityThread.main(ActivityThread.java:5001)
                                                                        at java.lang.reflect.Method.invokeNative(Native Method)
                                                                        at java.lang.reflect.Method.invoke(Method.java:515)
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785)
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601)
                                                                        at dalvik.system.NativeStart.main(Native Method)
                                                                     Caused by: java.lang.reflect.InvocationTargetException
                                                                        at java.lang.reflect.Method.invokeNative(Native Method)
                                                                        at java.lang.reflect.Method.invoke(Method.java:515)
                                                                        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288)
                                                                        at android.view.View.performClick(View.java:4438) 
                                                                        at android.view.View$PerformClick.run(View.java:18422) 
                                                                        at android.os.Handler.handleCallback(Handler.java:733) 
                                                                        at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                        at android.os.Looper.loop(Looper.java:136) 
                                                                        at android.app.ActivityThread.main(ActivityThread.java:5001) 
                                                                        at java.lang.reflect.Method.invokeNative(Native Method) 
                                                                        at java.lang.reflect.Method.invoke(Method.java:515) 
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 
                                                                        at dalvik.system.NativeStart.main(Native Method) 
                                                                     Caused by: java.lang.NullPointerException
                                                                        at on4shop.androidapp.DialogClassCollection.clsSaveFileDialog.refresh(clsSaveFileDialog.java:99)
                                                                        at on4shop.androidapp.DialogClassCollection.clsSaveFileDialog.<init>(clsSaveFileDialog.java:62)
                                                                        at on4shop.androidapp.frm_file_act.WriteExternalFile(frm_file_act.java:67)
                                                                        at java.lang.reflect.Method.invokeNative(Native Method) 
                                                                        at java.lang.reflect.Method.invoke(Method.java:515) 
                                                                        at android.support.v7.app.AppCompatViewInflater$DeclaredOnClickListener.onClick(AppCompatViewInflater.java:288) 
                                                                        at android.view.View.performClick(View.java:4438) 
                                                                        at android.view.View$PerformClick.run(View.java:18422) 
                                                                        at android.os.Handler.handleCallback(Handler.java:733) 
                                                                        at android.os.Handler.dispatchMessage(Handler.java:95) 
                                                                        at android.os.Looper.loop(Looper.java:136) 
                                                                        at android.app.ActivityThread.main(ActivityThread.java:5001) 
                                                                        at java.lang.reflect.Method.invokeNative(Native Method) 
                                                                        at java.lang.reflect.Method.invoke(Method.java:515) 
                                                                        at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:785) 
                                                                        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:601) 
                                                                        at dalvik.system.NativeStart.main(Native Method) 

Comment posted by: , 8 years ago

Hey Brian, the stack trace might tell you if this.getParent() is the cause of the problem. Couldn't you just use 'this'?

Comment posted by: Brian Young, 8 years ago

I'm trying to use your file picker to pick a file for the XML parser to parse... I have the FileChooser Class and everything compiling, but my APP blows up when I include this code to present the file chooser.  I only pick an XML file to parse on the initial startup of the app.  It's likely the "this.getParent()" to get the activity, but I cannot be sure.

 

public class XMLPullParserActivity extends Activity {
...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

...
        if (savedInstanceState != null) {
...
 } else {

            new FileChooser(this.getParent()).setFileListener(new FileChooser.FileSelectedListener() {
                @Override public void fileSelected(final File file) {
                    // do something with the file
                    Application application=(Application)CBA_Application.getContext();
                    CBA_Application app = (CBA_Application)application;
                    Context context=getApplicationContext();
                    CharSequence mytext;
                    Integer myduration;
                    Toast mytoast;
                    mytext = "Root Directory for selected File " + file.getAbsolutePath();
                    myduration = Toast.LENGTH_LONG;
                    mytoast = Toast.makeText(context,mytext,myduration);
                    mytoast.show();
                }}).showDialog();
...

Comment posted by: Shipmodeller, 8 years ago

Thanks .. that made my life easy ..  Made a few minor tweaks.. but I had some issues with the extensions.  So, since I know what the extension is ahead of time, I  just added it to the construction methods.  I could add multiple extension filters on... your skeleton was what I really needed.. So, I use it like 

private void processFile(){
    filechooser = new FileChooser(ImportActivity.this);
    filechooser.setFileListener(new FileChooser.FileSelectedListener() {
        @Override
        public void fileSelected(final File file) {
            // ....do something with the file
            String filename = file.getAbsolutePath();
            Log.d("File", filename);
            // then actually do something in another module

        }
    });
// Set up and filter my extension I am looking for
    filechooser.setExtension("pdf");
    filechooser.showDialog();
}
Comment posted by: Choudry, 8 years ago

Hello, i already have a button in main activity to access this class, how i implement my button actionListener with this class?

Comment posted by: Kirintal, 9 years ago

Hi,

Thank you. This is absolutely brilliant and saved me a lot of time.

I noticed one issue with the processing order. When using "setExtension", the "refresh" method is not called. This results in the first screen displaying all file formats not just directories and the designated extension.

Thank you once again

Comment posted by: haruto, 9 years ago

I don't understand with this part:

// do something with the file

can you give me an example what i can do with that line?

Comment posted by: Tonny, 9 years ago

How do i implement the class within a button click of another class

Comment posted by: Felix Zaulda Jr, 9 years ago

Hi Roger,

Thank you so much for this code... I am so thankful that you allow this code to be used on our projects.