125

I want to make a file uploader. And I hence I need a file chooser but I don't want to write this by myself. I find OI file manager and I think it suits me. But how can I force user to install OI file manager? If I cannot , is there a better way to include a file manager in my app? Thx

Pratik Butani
  • 60,504
  • 58
  • 273
  • 437
Bear
  • 5,138
  • 5
  • 50
  • 80

2 Answers2

273

EDIT (02 Jan 2012):

I created a small open source Android Library Project that streamlines this process, while also providing a built-in file explorer (in case the user does not have one present). It's extremely simple to use, requiring only a few lines of code.

You can find it at GitHub: aFileChooser.


ORIGINAL

If you want the user to be able to choose any file in the system, you will need to include your own file manager, or advise the user to download one. I believe the best you can do is look for "openable" content in an Intent.createChooser() like this:

private static final int FILE_SELECT_CODE = 0;

private void showFileChooser() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT); 
    intent.setType("*/*"); 
    intent.addCategory(Intent.CATEGORY_OPENABLE);

    try {
        startActivityForResult(
                Intent.createChooser(intent, "Select a File to Upload"),
                FILE_SELECT_CODE);
    } catch (android.content.ActivityNotFoundException ex) {
        // Potentially direct the user to the Market with a Dialog
        Toast.makeText(this, "Please install a File Manager.", 
                Toast.LENGTH_SHORT).show();
    }
}

You would then listen for the selected file's Uri in onActivityResult() like so:

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    switch (requestCode) {
        case FILE_SELECT_CODE:
        if (resultCode == RESULT_OK) {
            // Get the Uri of the selected file 
            Uri uri = data.getData();
            Log.d(TAG, "File Uri: " + uri.toString());
            // Get the path
            String path = FileUtils.getPath(this, uri);
            Log.d(TAG, "File Path: " + path);
            // Get the file instance
            // File file = new File(path);
            // Initiate the upload
        }
        break;
    }
    super.onActivityResult(requestCode, resultCode, data);
}

The getPath() method in my FileUtils.java is:

public static String getPath(Context context, Uri uri) throws URISyntaxException {
    if ("content".equalsIgnoreCase(uri.getScheme())) {
        String[] projection = { "_data" };
        Cursor cursor = null;

        try {
            cursor = context.getContentResolver().query(uri, projection, null, null, null);
            int column_index = cursor.getColumnIndexOrThrow("_data");
            if (cursor.moveToFirst()) {
                return cursor.getString(column_index);
            }
        } catch (Exception e) {
            // Eat it
        }
    }
    else if ("file".equalsIgnoreCase(uri.getScheme())) {
        return uri.getPath();
    }

    return null;
} 
Xavi
  • 20,111
  • 14
  • 72
  • 63
Paul Burke
  • 25,496
  • 9
  • 66
  • 62
  • 1
    I'd even go so far as to also direct them to app on the market. – Kurtis Nusbaum Oct 22 '11 at 02:50
  • 1
    Thx, but I get the content uri ---content://org.openintents.cmfilemanager/mimetype//mnt/sdcard/1318638826728.jpg instead of file path. Could I convert it into file path? – Bear Oct 22 '11 at 05:14
  • Updated answer to show how to get the file path, as well as creating a File instance that gives you convenience callbacks like file.getName() and file.getAbsolutePath(). – Paul Burke Oct 22 '11 at 05:34
  • 2
    But I can't find FileUtils.... – Bear Oct 22 '11 at 05:42
  • Sorry, I forgot to include my FileUtils.getPath() at first. – Paul Burke Oct 22 '11 at 05:43
  • without use file explorer it`s possible?can we make to display file structure in android? – Zala Janaksinh Jul 24 '12 at 09:56
  • On Google Code the license was explicitly Apache 2.0, is it still the case on GitHub? Thanks. – Benoit Duffez Sep 03 '12 at 21:44
  • 2
    @Bicou Thanks for the note. Your nudge helped me to stop being lazy and make some minor changes. :-) I just pushed an update to the library that includes the license. – Paul Burke Sep 04 '12 at 06:15
  • java.lang.NoClassDefFoundError com.ipaulpro.afilechooser.utils.FileUtils . What might I be doing wrong? – Dheeraj Bhaskar Feb 02 '13 at 22:13
  • Thanks for this, especially the `getPath()` code! I found on one device for me `cursor.getString(column_index)` returns a `file:///` URL, and I had to run it through a second pass to extract the actual path name. – Richard Walters May 23 '13 at 00:42
  • 1
    @Bear You just need to copy that getPath method to your own class and that's it! – vilpe89 Jun 03 '13 at 10:36
  • Do I have to use intents even if I don't need 3rd party components? Can this be used like a DialogFragment? – David Doria Sep 05 '13 at 15:30
  • @DavidDoria Sure, you can also simply call `startActivity(Context, FileChooserActivity.class)` and set the theme you want in the Manifest. Listen for the `Uri` in `onActivityResult` just as you would normally. – Paul Burke Sep 05 '13 at 18:39
  • @PaulBurke Sorry, I'm very new to this. I don't see a startActivity function here http://developer.android.com/reference/android/app/Activity.html#startActivity%28android.content.Intent%29 that takes anything but an intent? The closest I found online was startActivity(new Intent(MainActivity.this, FileChooserActivity.class)); - is that the best way? – David Doria Sep 06 '13 at 11:58
  • @DavidDoria My apologies! I did mean `startActivity(Intent)`. – Paul Burke Sep 12 '13 at 20:46
  • how can I enable multi select ..? – Chandan Reddy Mar 19 '15 at 14:14
  • @PaulBurke: I am using your method to attach a file and upload it to server. But I am facing an error, can you please help me. Please see this question: http://stackoverflow.com/questions/30882833/file-not-found-exception-when-trying-to-upload-file-to-xampp-server-from-android/30883016?noredirect=1#comment49807367_30883016. Thanks in advance. – keshav kowshik Jun 17 '15 at 09:42
  • 26
    This answer does not consider the uri like this:"content://com.android.providers.media.documents/document/image:62". – wangqi060934 Jul 31 '15 at 07:38
  • 2
    @wangqi060934: how did you manage to work with such uri? please share your experience to achieve the functionality – Mehul Joisar May 22 '16 at 06:48
  • @MehulJoisar,the library " aFileChooser" is perfect now. – wangqi060934 May 25 '16 at 14:23
  • 1
    Or you can use this one: https://www.github.com/Angads25/android-filepicker – Angad Singh Sep 12 '16 at 17:44
  • Sir, how to filter a specific file type like pdf, doc ect... – salih kallai Dec 17 '17 at 18:58
  • 1
    Here you can find all cases to select file from document and all types of mobiles https://github.com/memo1231014/MUT-master/blob/master/MUT/src/com/example/androidprogramminghelper/FileOperations.java – Mohamed Atef Dec 22 '17 at 08:11
  • @PaulBurke - Thank you very much i used you android studio project and it worked great. The only problem i had is that when the `onActivityResult` function was called the `REQUEST_CHOOSER` did not trigger the correct action - found in your git-hub project, in your _README.markdown_ file under _usage_ in your `switch`. (i changed it to `REQUEST_CODE`) – JFreeman Jan 25 '18 at 08:28
  • is this lib provide multiple file selection ? – Mr. Sajid Shaikh Jul 11 '18 at 12:37
  • Here path getiing null some time,i can see in log "coloumn name _data not able to find" message. – learner Jul 19 '19 at 11:59
  • Today, there are a lot of deprecated classes/methods in the module like 'AsyncTaskLoader'. Needs some updates. – Jomme Feb 27 '20 at 16:33
  • Hi i have an issue in onActivityResult when i didn't select any file and press back it doesn't open again can any one help ? – Ahmad Mar 20 '20 at 07:12
-2

I used AndExplorer for this purpose and my solution is popup a dialog and then redirect on the market to install the misssing application:

My startCreation is trying to call external file/directory picker. If it is missing call show installResultMessage function.

private void startCreation(){
    Intent intent = new Intent();
    intent.setAction(Intent.ACTION_PICK);
    Uri startDir = Uri.fromFile(new File("/sdcard"));

    intent.setDataAndType(startDir,
            "vnd.android.cursor.dir/lysesoft.andexplorer.file");
    intent.putExtra("browser_filter_extension_whitelist", "*.csv");
    intent.putExtra("explorer_title", getText(R.string.andex_file_selection_title));
    intent.putExtra("browser_title_background_color",
            getText(R.string.browser_title_background_color));
    intent.putExtra("browser_title_foreground_color",
            getText(R.string.browser_title_foreground_color));
    intent.putExtra("browser_list_background_color",
            getText(R.string.browser_list_background_color));
    intent.putExtra("browser_list_fontscale", "120%");
    intent.putExtra("browser_list_layout", "2");

    try{
         ApplicationInfo info = getPackageManager()
                                 .getApplicationInfo("lysesoft.andexplorer", 0 );

            startActivityForResult(intent, PICK_REQUEST_CODE);
    } catch( PackageManager.NameNotFoundException e ){
        showInstallResultMessage(R.string.error_install_andexplorer);
    } catch (Exception e) {
        Log.w(TAG, e.getMessage());
    }
}

This methos is just pick up a dialog and if user wants install the external application from market

private void showInstallResultMessage(int msg_id) {
    AlertDialog dialog = new AlertDialog.Builder(this).create();
    dialog.setMessage(getText(msg_id));
    dialog.setButton(getText(R.string.button_ok),
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    finish();
                }
            });
    dialog.setButton2(getText(R.string.button_install),
            new DialogInterface.OnClickListener() {

                @Override
                public void onClick(DialogInterface dialog, int which) {
                    Intent intent = new Intent(Intent.ACTION_VIEW);
                    intent.setData(Uri.parse("market://details?id=lysesoft.andexplorer"));
                    startActivity(intent);
                    finish();
                }
            });
    dialog.show();
}
andep
  • 8,033
  • 1
  • 13
  • 5