android-file-chooser

Additional

Language
Java
Version
N/A
Created
Jun 7, 2015
Updated
Dec 10, 2018
Owner
hedzr
Contributors
hedzr
bostrot
banlyst
Guiorgy
4
Activity
Badge
Generate
Download
Source code
APK file

Blurb

android-file-chooser

android-file-library is a lightweight file/folder chooser.

Overview

Snapshots

Demo Application

A demo-app can be installed from Play Store.

Changes

x1.2.0 branch

  • In progress
  • Done:
    • Keyboard supports: process SPACE and ENTER up event;
    • file list no focus when dailog first showing;
    • better storage media detect algorithm for Android M+;
    • no WRITE_EXTERNAL_STORAGE requests if not enableOptions(true);
    • after requested permissions, try showing dialog again instead of return directly;

v1.1.11 patches on master

  • no WRITE_EXTERNAL_STORAGE requests if not enableOptions(true);
  • after requested permissions, try showing dialog again instead of return directly;

v1.1.11

  • create new folder on the fly, and the optional multiple select mode for developer, thx Guiorgy and his android-smbfile-chooser
  • Up (..) on the primary storage root will be replaced with .. SDCard, it allows to jump to external storage such as a SDCard and going back available too.
  • DPad supports, arrow keys supports (#30)
  • ...

Usages

Configuration

build.gradle

android-file-chooser was released at jcenter, declare deps with:

implementation 'com.obsez.android.lib.filechooser:filechooser:$android_file_chooser_version'

for the newest version(s), looking up the badges above.

taste the fresh

there is a way to taste the master branch with jitpack.io:

  1. add the jitpack repository url to your root build.gradle:
allprojects {
    repositories {
        google()
        jcenter()
        maven { url "https://jitpack.io" }
    }
}
  1. import android-file-chooser
implementation 'com.github.hedzr:android-file-chooser:master-SNAPSHOT'
// implementation 'com.github.hedzr:android-file-chooser:v1.1.10'

Codes

FileChooser android library give a simple file/folder chooser in single call:

Choose a Folder

    new ChooserDialog().with(this)
            .withFilter(true, false)
            .withStartFile(startingDir)
            .withChosenListener(new ChooserDialog.Result() {
                @Override
                public void onChoosePath(String path, File pathFile) {
                    Toast.makeText(MainActivity.this, "FOLDER: " + path, Toast.LENGTH_SHORT).show();
                }
            })
            .build()
            .show();

Choose a File

    new ChooserDialog().with(this)
            .withStartFile(path)
            .withChosenListener(new ChooserDialog.Result() {
                @Override
                public void onChoosePath(String path, File pathFile) {
                    Toast.makeText(MainActivity.this, "FILE: " + path, Toast.LENGTH_SHORT).show();
                }
            })
            .build()
            .show();

Wild-match

    new ChooserDialog().with(this)
            .withFilter(false, false, "jpg", "jpeg", "png")
            .withStartFile(path)
            .withResources(R.string.title_choose_file, R.string.title_choose, R.string.dialog_cancel)
            .withChosenListener(new ChooserDialog.Result() {
                @Override
                public void onChoosePath(String path, File pathFile) {
                    Toast.makeText(MainActivity.this, "FILE: " + path, Toast.LENGTH_SHORT).show();
                }
            })
            .build()
            .show();

Regex filter

    new ChooserDialog().with(this)
            .withFilterRegex(false, false, ".*\\.(jpe?g|png)")
            .withStartFile(path)
            .withResources(R.string.title_choose_file, R.string.title_choose, R.string.dialog_cancel)
            .withChosenListener(new ChooserDialog.Result() {
                @Override
                public void onChoosePath(String path, File pathFile) {
                    Toast.makeText(NewMainActivity.this, "FILE: " + path, Toast.LENGTH_SHORT).show();
                }
            })
            .build()
            .show();

Date Format String

Since 1.1.3, new builder options withDateFormat(String) added.

    new ChooserDialog().with(this)
            .withFilter(true, false)
            .withStartFile(startingDir)
            .withDateFormat("HH:mm")    // see also SimpleDateFormat format specifiers
            .withChosenListener(new ChooserDialog.Result() {
                @Override
                public void onChoosePath(String path, File pathFile) {
                    Toast.makeText(MainActivity.this, "FOLDER: " + path, Toast.LENGTH_SHORT).show();
                }
            })
            .build()
            .show();

Modify Icon or View Layout of AlertDialog:

Since 1.1.6, 2 new options are available:

    new ChooserDialog().with(this)
            .withFilter(true, false)
            .withStartFile(startingDir)
            .withIcon(R.drawable.ic_file_chooser)
            .withLayoutView(R.layout.alert_file_chooser)
            .withChosenListener(new ChooserDialog.Result() {
                @Override
                public void onChoosePath(String path, File pathFile) {
                    Toast.makeText(MainActivity.this, "FOLDER: " + path, Toast.LENGTH_SHORT).show();
                }
            })
            .build()
            .show();

Customizable NegativeButton

1.1.7 or Higher, try withNegativeButton() and withNegativeButtonListener().

New calling chain

1.1.7+, new constructor ChooserDialog(context) can simplify the chain invoking, such as:

    new ChooserDialog(this)
            .withFilter(true, false)
            .withStartFile(startingDir)
            ...

And, old style is still available. No need to modify your existing codes.

withRowLayoutView(resId)

1.1.8+. Now you can customize each row.

withFileIcons

1.1.9+. withFileIcons(resolveMime, fileIcon, folderIcon) and withFileIconsRes(resolveMime, fileIconResId, folderIconResId) allow user-defined file/folder icon.

resolveMime: true means that DirAdapter will try get icon from the associated app with the file's mime type.

    new ChooserDialog(ctx)
            .withStartFile(_path)
            .withResources(R.string.title_choose_any_file, R.string.title_choose, R.string.dialog_cancel)
            .withFileIconsRes(false, R.mipmap.ic_my_file, R.mipmap.ic_my_folder)
            .withChosenListener(new ChooserDialog.Result() {
                @Override
                public void onChoosePath(String path, File pathFile) {
                    Toast.makeText(ctx, "FILE: " + path, Toast.LENGTH_SHORT).show();
                }
            })
            .build()
            .show();

withAdapterSetter(setter)

1.1.9+. a AdapterSetter can be use to customize the DirAdapter.

            .withAdapterSetter(new ChooserDialog.AdapterSetter() {
                @Override
                public void apply(DirAdapter adapter) {
                    adapter.setDefaultFileIcon(fileIcon);
                    adapter.setDefaultFolderIcon(folderIcon);
                    adapter.setResolveFileType(tryResolveFileTypeAndIcon);
                }
            })

withNavigateUpTo(CanNavigateUp)

1.1.10+. withNavigateUpTo

                .withNavigateUpTo(new ChooserDialog.CanNavigateUp() {
                    @Override
                    public boolean canUpTo(File dir) {
                        return true;
                    }
                })

withNavigateTo(CanNavigateTo)

1.1.10+. withNavigateTo

                .withNavigateTo(new ChooserDialog.CanNavigateTo() {
                    @Override
                    public boolean canNavigate(File dir) {
                        return true;
                    }
                })

enableOptions(true)

a tri-dot menu icon will be shown at bottom left corner. this icon button allows end user to create new folder on the fly or delete one.

further tunes:

  • withOptionResources(@StringRes int createDirRes, @StringRes int deleteRes, @StringRes int newFolderCancelRes, @StringRes int newFolderOkRes)
  • withOptionIcons(@DrawableRes int optionsIconRes, @DrawableRes int createDirIconRes, @DrawableRes int deleteRes)
  • withNewFolderFilter(NewFolderFilter filter)
  • withOnBackPressedListener(OnBackPressedListener listener)
  • withOnLastBackPressedListener(OnBackPressedListener listener)

see the sample codes in demo app.

NOTE:

  1. extra WRITE_EXTERNAL_STORAGE permission should be declared in your AndroidManifest.xml.
  2. we'll ask the extra runtime permission to WRITE_EXTERNAL_STORAGE on Android M and higher too.

disableTitle(true)

as named as working.

psuedo .. SDCard Storage and .. Primary Storage


And:

        ChooserDialog(context)
                .withFilterRegex(false, true, ".*\\.(jpe?g|png)")
                .withStartFile(startPath)
                .withResources(R.string.title_choose_file, R.string.title_choose, R.string.dialog_cancel)
                .withChosenListener { path, pathFile ->
                    Toast.makeText(context, "FILE: $path; PATHFILE: $pathFile", Toast.LENGTH_SHORT).show()

                    //_path = path
                    //_tv.setText(_path)
                    ////_iv.setImageURI(Uri.fromFile(pathFile));
                    //_iv.setImageBitmap(ImageUtil.decodeFile(pathFile))
                }
                .withNavigateUpTo { true }
                .withNavigateTo { true }
                .build()
                .show()

Build me

1. legacy

cat >keystore.properties<<EOF
keyAlias=youKeyAlias
keyPassword=password
storeFile=/Users/me/android-file-chooser.keystore
storePassword=password
EOF
git clone git@github.com:hedzr/android-file-chooser.git somewhere
cd somewhere
./gradlew assembleDebug

you'd better generate a new file android-file-chooser.keystore at homedir or else. such as: keytool -genkey -alias android.keystore -keyalg RSA -validity 20000 -keystore android.keystore, see also Sign an app. Or, erase the KS_PATH lines and signature section in app/build.gradle.

2. current

just fork and build me currently.

Contrib

Contributions and translations are welcome.

Feedback

feel free to make an new issue.

Acknowledges

many peoples report or contribute to improve me, but only a few of them be put here — it's hard to list all.

License

Copyright 2015-2018 Hedzr Yeh.

Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.