Code Monkey home page Code Monkey logo

android-file-chooser's Introduction

android-file-chooser

Financial Contributors on Open Collective Android Arsenal Download Release Build Status

IMPORTANT:

THIS REPO HAS BEEN STOPPED TO UPDATE TO COMPLY WITH THE NEWER ANDROID LIKE 'Q' AND ABOVE.


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

The usages at HERE, and Acknowledges.

Legacy

1. with AndroidX

dependencies {
	// implementation 'com.github.hedzr:android-file-chooser:1.2.0-SNAPSHOT'
	implementation 'com.github.hedzr:android-file-chooser:v1.2.0-final'
}

MediaStore for Android Q (still in beta)

dependencies {
	implementation 'com.github.hedzr:android-file-chooser:devel-SNAPSHOT'
}

Overview

banner

Demo Application

A demo-app can be installed from Play Store.

Get it on Google Play

Xamarin Binding

A Xamarin nuget package by @Guiorgy can be found at NuGet

Changes

v1.1.19

  • bugs fixed
  • minor fixes for themes
  • #60, #61, #62 fixed
  • revamped Dpad controls
  • added cancelOnTouchOutside and enableDpad (true by default)
  • mainly by Guiorgy.

Archived History:

  • rewrite demo app

  • #48: add displayPath(boolean), thank you @Guiorgy, and your android-smbfile-chooser.

  • new style demo app by @Guiorgy.

  • NOTE: displayPath is true by default now.

  • since v1.1.16, bumped targer sdk to 1.8 (please include the following into your build.gradle)

    android {
        compileOptions {
            sourceCompatibility JavaVersion.VERSION_1_8
            targetCompatibility JavaVersion.VERSION_1_8
        }
    }
  • no WRITE_EXTERNAL_STORAGE requests if not enableOptions(true);

  • after requested permissions, try showing dialog again instead of return directly;

  • #42: onBackPressedListener not fired. Now, use withCancelListener to handle back key. see also below

  • #45: add titleFollowsDir(boolean) to allow title following the change of current directory.

  • create new folder on the fly, and the optional multiple select mode for developer, thx @Guiorgy.

  • 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)

Snapshots

More images (beyond v1.1.16) have been found at Gallery

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.14'

Tips for using JitPack.io

To disable gradle local cache in your project, add stretegy into your top build.grable:

configurations.all {
    resolutionStrategy.cacheChangingModulesFor 0, 'seconds'
    resolutionStrategy.cacheDynamicVersionsFor 0, 'seconds'
}

ref: spring-gradle-plugins/dependency-management-plugin#74 (comment)

Sometimes it's right, sometimes ... no more warrants.

Codes

Tips

  1. I am hands down AlertDialog.
  2. Any codes about ChooserDialog, such as the following demo codes, should be only put into UI thread.

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

Choose a Folder

    new ChooserDialog(MainActivity.this)
            .withFilter(true, false)
        	.withStartFile(startingDir)
        	// to handle the result(s)
            .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(MainActivity.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();
                }
            })
        	// to handle the back key pressed or clicked outside the dialog:
        	.withOnCancelListener(new DialogInterface.OnCancelListener() {
    			public void onCancel(DialogInterface dialog) {
			        Log.d("CANCEL", "CANCEL");
			        dialog.cancel(); // MUST have
    			}
			})
            .build()
            .show();

Wild-match

    new ChooserDialog(MainActivity.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(MainActivity.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(MainActivity.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(MainActivity.this)
            .withFilter(true, false)
            .withStartFile(startingDir)
            .withIcon(R.drawable.ic_file_chooser)
            .withLayoutView(R.layout.alert_file_chooser) // (API > 20)
            .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/or withNegativeButtonListener()


withOnBackPressedListener

BackPressedListener will be called every time back key is pressed, and current directory is not the root of Primary/SdCard storage. LastBackPressedListener will be called if back key is pressed, and current directory is the root of Primary/SdCard storage.

.withOnBackPressedListener(dialog -> chooserDialog.goBack())
.withOnLastBackPressedListener(dialog -> dialog.cancel())

onCancelListener

OnCancelListener will be called when touching outside the dialog (cancelOnTouchOutside must be set true), and when pressing back key. If BackPressedListener is overridden, it wont be called if dialog.dismiss is used instead of dialog.cancel. OnCancelListener will NOT be called when pressing the negative button. use withNegativeButtonListener for that.

.withOnCancelListener(new DialogInterface.OnCancelListener() {
    public void onCancel(DialogInterface dialog) {
        Log.d("CANCEL", "CANCEL");
    }
})

---

#### New calling chain

1.1.7+, new constructor `ChooserDialog(context)` can simplify the chain invoking. Also `build()` is no longer obligatory to be called:

​```java
    new ChooserDialog(MainActivity.this)
            .withFilter(true, false)
            .withStartFile(startingDir)
            ...
			.show();

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

withRowLayoutView(resId)

1.1.8+. Now you can customize each row.

since 1.1.17, DirAdatper.GetViewListener#getView allows you do the same thing and more, and withRowLayoutView will be deprecated. See also: withAdapterSetter(setter)

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.

    final Context ctx = MainActivity.this;
    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);
		// since 1.1.17
		adapter.overrideGetView((file, isSelected, isFocused, convertView, parent, inflater) -> {
			ViewGroup view = (ViewGroup) inflater.inflate(R.layout.li_row, parent, false);
			...
			return view;
		}
    }
})

More information in source code of DirAdapter.

since 1.1.17, DirAdapter.overrideGetView() supports GetViewListener interface.

    public interface GetView {
        /**
         * @param file        file that should me displayed
         * @param isSelected  whether file is selected when _enableMultiple is set to true
         * @param isFocused   whether this file is focused when using dpad controls
		 					  deprecated since 1.1.18! use fileListItemFocusedDrawable attribute instead
         * @param convertView see ArrayAdapter#getView(int, View, ViewGroup)
         * @param parent      see ArrayAdapter#getView(int, View, ViewGroup)
         * @param inflater    a layout inflater with the FileChooser theme wrapped context
         * @return your custom row item view
         */
        @NonNull
        View getView(@NonNull File file, boolean isSelected, boolean isFocused, View convertView,
            @NonNull ViewGroup parent, @NonNull LayoutInflater inflater);
    }

withNavigateUpTo(CanNavigateUp)

1.1.10+. withNavigateUpTo

You can disallow someone enter some special directories.

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

withNavigateTo(CanNavigateTo)

1.1.10+. withNavigateTo

With withStartFile(), you can limit the root folder.

.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)

  • withOptionStringResources(@Nullable String createDir, @Nullable String delete, @Nullable String newFolderCancel, @Nullable String newFolderOk)

    since v1.1.17

  • 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

since v1.11, external storage will be detected automatically. That means user can switch between internal and external storage by clicking on psuedo folder names.

titleFollowsDir(true)

since the latest patch of v1.14, it allows the chooser dialog title updated by changing directory.

displayPath(true), customizePathView(callback)

since the latest patch of v1.15, it allows a path string displayed below the title area.

since v1.16, its default value is true.

Screen Snapshot

As a useful complement, customizePathView(callback) allows tuning the path TextView. For example:

.customizePathView((pathView) -> {
    pathView.setGravity(Gravity.RIGHT);
})

since 1.1.17, this can also be done through a custom theme:

<style name="FileChooserStyle">
	...
	<item name="fileChooserPathViewStyle">@style/FileChooserPathViewStyle</item>
</style>

<style name="FileChooserPathViewStyle">
	<item name="android:background">#ffffffff</item>
	<item name="android:textColor">#40000000</item>
	<item name="android:textSize">12sp</item>
	<item name="fileChooserPathViewElevation">2</item>
	<item name="fileChooserPathViewDisplayRoot">true</item>
</style>

withResources, withStringResources

you can customize the text of buttons:

            .withResources(R.string.title_choose_any_file, R.string.title_choose, R.string.dialog_cancel)
            .withStringResources("Title", "OK", "Cancel")

Under Kotlin

class MyFragment : Fragment() {

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
                              savedInstanceState: Bundle?): View? {
        val root = inflater.inflate(R.layout.fragment_book, container, false)
        root.upload_button.setOnClickListener { _: View ->
            ChooserDialog().with(activity)
                    .withStartFile(Environment.getExternalStorageDirectory().absolutePath)
                    // .withStartFile(Environment.getExternalStorageState()+"/")
                    .withFilterRegex(false, false, ".*\\.(jpe?g|png)")
                    .titleFollowsDir(true)
                    .displayPath(true)
                    .customizePathView{ pathView -> pathView.setGravity(Gravity.RIGHT) }
                    .withChosenListener { path, pathFile -> activity!!.toast("FILE: $path / $pathFile") }
                    .build()
                    .show()
        }

        return root
    }
}

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

For Library Developers

Just fork and build me currently.

Contrib

Contributions and translations are welcome.

Feedback

feel free to make a 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.

Contributors

Code Contributors

This project exists thanks to all the people who contribute. [Contribute].

Financial Contributors

Become a financial contributor and help us sustain our community. [Contribute]

Individuals

Organizations

Support this project with your organization. Your logo will show up here with a link to your website. [Contribute]

License

Standard Apache 2.0

Copyright 2015-2019 Hedzr Yeh.

android-file-chooser's People

Contributors

banlyst avatar bostrot avatar guiorgy avatar hedzr avatar joielechong avatar monkeywithacupcake avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

android-file-chooser's Issues

Crash on runtime (Android 4.2)

This runtime exception append on monkey test of my app that implements the file chooser

The specs

Build Label: Android/NX8/NX8:4.2.2/JDQ39/88.07.20170207:user/release-keys

The events
:Switch: #Intent;action=android.intent.action.MAIN;category=android.intent.category.LAUNCHER;launchFlags=0x10200000;component=com.sdmo_quiniou/.MainActivity;end
// Allowing start of Intent { act=android.intent.action.MAIN cat=[android.intent.category.LAUNCHER] cmp=com.sdmo_quiniou/.MainActivity } in package com.sdmo_quiniou

:Sending Touch (ACTION_DOWN): 0:(283.0,477.0)
:Sending Touch (ACTION_UP): 0:(284.1647,469.472)
:Sending Trackball (ACTION_MOVE): 0:(3.0,2.0)

// CRASH: com.sdmo_quiniou (pid 2034)
// Short Msg: java.lang.NullPointerException
// Long Msg: java.lang.NullPointerException

//      at com.obsez.android.lib.filechooser.keyListener.onKey(keyListener.java:48)
//      at android.app.Dialog.dispatchKeyEvent(Dialog.java:703)
//      at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchKeyEvent(PhoneWindow.java:1847)
//      at android.view.ViewRootImpl.deliverKeyEventPostIme(ViewRootImpl.java:3716)
//      at android.view.ViewRootImpl.deliverKeyEvent(ViewRootImpl.java:3641)
//      at android.view.ViewRootImpl.deliverInputEvent(ViewRootImpl.java:3163)
//      at android.view.ViewRootImpl.doProcessInputEvents(ViewRootImpl.java:4345)
//      at android.view.ViewRootImpl.enqueueInputEvent(ViewRootImpl.java:4324)
//      at android.view.ViewRootImpl$WindowInputEventReceiver.onInputEvent(ViewRootImpl.java:4416)
//      at android.view.InputEventReceiver.dispatchInputEvent(InputEventReceiver.java:179)
//      at android.os.MessageQueue.nativePollOnce(Native Method)
//      at android.os.MessageQueue.next(MessageQueue.java:125)
//      at android.os.Looper.loop(Looper.java:124)
//      at android.app.ActivityThread.main(ActivityThread.java:5041)
//      at java.lang.reflect.Method.invokeNative(Native Method)
//      at java.lang.reflect.Method.invoke(Method.java:511)
//      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:793)
//      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:560)
//      at dalvik.system.NativeStart.main(Native Method)

Does not display the name of a selected folder

Suppose the following is the start screen:
image
If one taps folder "Download", the following is shown with the folder name "Download" nowhere to be found:
image
It actually shows the contents of folder "Download".
I am wondering if I am missing a parameter to enable the display of the selected folder name.
At this point time, this is the only missing part that I have found to prevent it from being as good as a file choose can be for my use.

Runtime Exception on Android 6 devices

Got a runtime exception only on Android 6 devices after 1.1.17 update

Fatal Exception: java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=347, result=-1, data=Intent { act=android.content.pm.action.REQUEST_PERMISSIONS (has extras) }} to activity {com.ytheekshana.deviceinfo/com.obsez.android.lib.filechooser.permissions.PermissionActivity}: android.util.AndroidRuntimeException: requestFeature() must be called before adding content
at android.app.ActivityThread.deliverResults(ActivityThread.java:5004)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5047)
at android.app.ActivityThread.access$1600(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1875)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7406)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

Caused by android.util.AndroidRuntimeException: requestFeature() must be called before adding content
at com.android.internal.policy.PhoneWindow.requestFeature(PhoneWindow.java:411)
at com.android.internal.app.AlertController.installContent(AlertController.java:250)
at android.app.AlertDialog.onCreate(AlertDialog.java:437)
at android.app.Dialog.dispatchOnCreate(Dialog.java:733)
at android.app.Dialog.show(Dialog.java:469)
at com.obsez.android.lib.filechooser.ChooserDialog.showDialog(ChooserDialog.java:568)
at com.obsez.android.lib.filechooser.ChooserDialog.access$000(ChooserDialog.java:65)
at com.obsez.android.lib.filechooser.ChooserDialog$1.onPermissionGranted(ChooserDialog.java:604)
at com.obsez.android.lib.filechooser.permissions.PermissionActivity.onRequestPermissionsResult(PermissionActivity.java:81)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:7291)
at android.app.Activity.dispatchActivityResult(Activity.java:7169)
at android.app.ActivityThread.deliverResults(ActivityThread.java:5000)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5047)
at android.app.ActivityThread.access$1600(ActivityThread.java:229)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1875)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:7406)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1230)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1120)

Unable to resolve dependency

`Unable to resolve dependency for ':app@debug/compileClasspath': Could not resolve com.obsez.android.lib.filechooser:filechooser:1.1.6.
Open File
Show Details

Unable to resolve dependency for ':app@debugAndroidTest/compileClasspath': Could not resolve com.obsez.android.lib.filechooser:filechooser:1.1.6.
Open File
Show Details

Unable to resolve dependency for ':app@debugUnitTest/compileClasspath': Could not resolve com.obsez.android.lib.filechooser:filechooser:1.1.6.
Open File
Show Details

Unable to resolve dependency for ':app@release/compileClasspath': Could not resolve com.obsez.android.lib.filechooser:filechooser:1.1.6.
Open File
Show Details

Unable to resolve dependency for ':app@releaseUnitTest/compileClasspath': Could not resolve com.obsez.android.lib.filechooser:filechooser:1.1.6.
Open File
Show Details
`

Remove kotlin plugin from library

For the library module, I think you can safely remove the apply plugin: 'kotlin-android' and implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" from dependencies. I try running the sample app with the two above removed and the app is running smoothly.

I can send you a PR to let me remove them.

Navigating up in browser

I used the template in your README.md to create a basic chooser for selecting a file, setting the path to the devices public Downloads folder. This works, and looks great. The only problem I'm running into is that the user can't navigate up past the root of internal storage. If I tell it to set the path as ROOT (Environment.getRootDirectory().toString()) than they can navigate everywhere, but the average user may be confused by the file path they are looking at. Can you suggest a way of allowing them to navigate to a file that may be on local OR external storage? I have already implemented the appropriate read permissions.

withOnBackPressedListener not fired

Hi,
I define the withOnBackPressedListener option :

.withOnBackPressedListener(new ChooserDialog.OnBackPressedListener() {
                            @Override
                            public void onBackPressed(AlertDialog dialog) {
                                Log.i("Qt", "onBackPressed");
                            }
                        })

It is never fired.
I have this warning in the log

W InputEventReceiver: Attempted to finish an input event but the input event receiver has already been disposed.

Runtime Exception

Got this today.
image

Fatal Exception: java.lang.RuntimeException: Failure delivering result ResultInfo{who=@android:requestPermissions:, request=782, result=0, data=null} to activity {com.ytheekshana.deviceinfo/com.obsez.android.lib.filechooser.permissions.PermissionActivity}: java.lang.RuntimeException: there are no permissions
at android.app.ActivityThread.deliverResults(ActivityThread.java:5002)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5044)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2155)
at android.os.Handler.dispatchMessage(Handler.java:109)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:7539)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)

Caused by java.lang.RuntimeException: there are no permissions
at com.obsez.android.lib.filechooser.permissions.PermissionActivity.onRequestPermissionsResult(PermissionActivity.java:73)
at android.app.Activity.dispatchRequestPermissionsResult(Activity.java:7934)
at android.app.Activity.dispatchActivityResult(Activity.java:7784)
at android.app.ActivityThread.deliverResults(ActivityThread.java:4995)
at android.app.ActivityThread.handleSendResult(ActivityThread.java:5044)
at android.app.servertransaction.ActivityResultItem.execute(ActivityResultItem.java:49)
at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:108)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:68)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2155)
at android.os.Handler.dispatchMessage(Handler.java:109)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:7539)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:524)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:958)

German translation for storage removed is wrong

Can you please adjust the german translation for the storage remove

<string name="storage_removed">Speicher wurde entferntet.</string>

to

<string name="storage_removed">Speicher wurde entfernt.</string>

Otherwise, the word is not correct ;)

Error:(16, 0) path may not be null or empty string. path='null' <a href="openFile:H:\Project\studio2.3_workspace\android-file-chooser-master\app\build.gradle">

signingConfigs {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())
def sdkDir = properties.getProperty('sdk.dir')
def ndkDir = properties.getProperty('ndk.dir')
def ksPath = properties.getProperty('KS_PATH')
def keystorePropertiesFile = rootProject.file(ksPath) //"../keystore.properties") //something here
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
config {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile file(keystoreProperties['storeFile'])
storePassword keystoreProperties['storePassword']
}
}

Writing to external storage

For some reason in the last version 1.1.11 you have added a request to write to external storage, giving no option for app owner to disable this. Since some apps definitely do not plan writing there, it is excess permission to request.
Probably the best way would be to configure whatever the processing mode should be with write or not.

Null pointer exception

I am getting this issue when I use it

E/MessageQueue-JNI: java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File[] java.io.File.listFiles(java.io.FileFilter)' on a null object reference

Changing design

Is there anyway to override resources and styles to change text colors/paddings/background color etc?

Cannot navigate up on 1.1.11

Just started looking into this library and if I am not mistaken there is some regression on 1.1.11 and it is impossible to navigate up.
Using this simple snippet.
Pixel 3, 9.0

ChooserDialog(context)
    .withStartFile(Environment.getExternalStorageDirectory().absolutePath)
    .withNavigateTo { true }
    .withNavigateUpTo { true }
    .build()
    .show()

cant move image file from app package folder to another folder of sd card.

cant move file from package folder,

  Bitmap bitmap = camera.getCameraBitmap();
 String path=camera.getCameraBitmapPath();
 if(bitmap != null) {
           
                File from=new File(path);
                File dest=new File(FOLDER_PATH+"/"+pic_count+"_"+from.getName());
               boolean movefile= from.renameTo(dest);
        
                if(movefile){
                     Log,d(TAG,"file moved");
                }else 
                   Log,d(TAG,"file not moved");
  }

FOLDER_PATH is sd card path.
is it possible to custom folder location for pic ??

Flies on all versions of android up to version LOLLIPOP_MR1.

If you enable .enableOptions (true) and and click on the open menu in the dialog with the addition and deletion of the folder crashes. Thanks for helping me solve the problem.
Fatal Exception: java.lang.ClassCastException: android.widget.LinearLayout cannot be cast to android.widget.FrameLayout
at com.obsez.android.lib.filechooser.ChooserDialog$9$6.onClick(ChooserDialog.java:599)
at android.view.View.performClick(View.java:4756)
at android.view.View$PerformClick.run(View.java:19749)
at android.os.Handler.handleCallback(Handler.java:739)
at android.os.Handler.dispatchMessage(Handler.java:95)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5221)
at java.lang.reflect.Method.invoke(Method.java)
at java.lang.reflect.Method.invoke(Method.java:372)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

Thumbnail of images

Is it possible to implement thumbnails for images?
On left side, there can be a thumbnail instead of small file icon.

v1.1.16: java.lang.BootstrapMethodError: Exception from call site #10 bootstrap method

java.lang.BootstrapMethodError: Exception from call site #10 bootstrap method
        at com.obsez.android.lib.filechooser.ChooserDialog.<clinit>(ChooserDialog.java:1529)
        at com.teamb.chzonk.ui.settings.SettingsFragment$PrefsFragment.onPreferenceTreeClick(SettingsFragment.kt:73)
        at androidx.preference.Preference.performClick(Preference.java:1173)
        at androidx.preference.Preference.performClick(Preference.java:1148)
        at androidx.preference.Preference$1.onClick(Preference.java:172)
        at android.view.View.performClick(View.java:6597)
        at android.view.View.performClickInternal(View.java:6574)
        at android.view.View.access$3100(View.java:778)
        at android.view.View$PerformClick.run(View.java:25885)
        at android.os.Handler.handleCallback(Handler.java:873)
        at android.os.Handler.dispatchMessage(Handler.java:99)
        at android.os.Looper.loop(Looper.java:193)
        at android.app.ActivityThread.main(ActivityThread.java:6669)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
     Caused by: java.lang.ClassCastException: Bootstrap method returned null
        at com.obsez.android.lib.filechooser.ChooserDialog.<clinit>(ChooserDialog.java:1529) 
        at com.teamb.chzonk.ui.settings.SettingsFragment$PrefsFragment.onPreferenceTreeClick(SettingsFragment.kt:73) 
        at androidx.preference.Preference.performClick(Preference.java:1173) 
        at androidx.preference.Preference.performClick(Preference.java:1148) 
        at androidx.preference.Preference$1.onClick(Preference.java:172) 
        at android.view.View.performClick(View.java:6597) 
        at android.view.View.performClickInternal(View.java:6574) 
        at android.view.View.access$3100(View.java:778) 
        at android.view.View$PerformClick.run(View.java:25885) 
        at android.os.Handler.handleCallback(Handler.java:873) 
        at android.os.Handler.dispatchMessage(Handler.java:99) 
        at android.os.Looper.loop(Looper.java:193) 
        at android.app.ActivityThread.main(ActivityThread.java:6669) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858) 

This is only present on 1.1.16. Tested: Android TV API 28, code for the dialog is

ChooserDialog(activity)
                    .withFilter(true, false)
                    .withStartFile(Environment.getExternalStorageDirectory().absolutePath)
                    .withResources(R.string.title_choose_folder, R.string.title_choose, R.string.dialog_cancel)
                    .withChosenListener { path, pathFile ->
                        Toast.makeText(activity, "FILE: $path / $pathFile", Toast.LENGTH_SHORT).show()
                    }
                    .build()
                    .show()

ExtFileFilter crashes if a folder contain a file without extension

Hi,

I launch the file chooser using your sample code:
new ChooserDialog().with(getActivity()) .withFilter(false, false, "db", "zip", "zi_") .withStartFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getAbsolutePath()) .withChosenListener( new ChooserDialog.Result() { @Override public void onChoosePath(String path, File pathFile) { Toast.makeText(getActivity(), "FILE: " + path, Toast.LENGTH_SHORT).show(); } }) .build() .show();

If I navigate to a folder that contains a file without an extension, the chooser crash. Please find the callstack attached.

Thank you

callStack.txt

Permission dialog have open every time.

Hello
Good Work..

I have one issues while show ChooserDialog, issues is permission dialog have open every time, if i have allow to access those permissions

I have fount where is wrong

You code
int PERMISSION_REQUEST_READ_EXTERNAL_STORAGE = false; ActivityCompat.requestPermissions((Activity)this._context, new String[]{"android.permission.READ_EXTERNAL_STORAGE"}, 0); int permissionCheck = ContextCompat.checkSelfPermission(this._context, "android.permission.READ_EXTERNAL_STORAGE"); if (permissionCheck == 0) { this._alertDialog.show(); }
why you are ask requestPermissions before permissionCheck
Please change you code aspa

val permissionCheck = ContextCompat.checkSelfPermission(this, "android.permission.READ_EXTERNAL_STORAGE") Log.e("TAG", " permissionCheck " + permissionCheck) if (permissionCheck == 0) { this._alertDialog.show() }else{ ActivityCompat.requestPermissions(this as Activity, arrayOf("android.permission.READ_EXTERNAL_STORAGE"), 0) }

Thanks..
device-2018-08-11-162815

Creating a new folder window color bug in dark theme

As you said here, I am using a custom row layout to give a dark mode. But how to change the alert textbox and its text color when creating a new folder. Check the screenshot to get an idea about what I am saying. I checked the demo app in the 1.2.X branch. The same thing happens in it too when in night mode.

see the image
file-chooser

DirAdapter.java line 50 Crash

I have a crash on many devices. Firebase Crashlytics show this.

Fatal Exception: android.content.res.Resources$NotFoundException: Resource ID #0x7f080121
at android.content.res.ResourcesImpl.getValueForDensity(ResourcesImpl.java:237)
at android.content.res.Resources.getDrawableForDensity(Resources.java:902)
at android.content.res.Resources.getDrawable(Resources.java:842)
at android.content.Context.getDrawable(Context.java:628)
at androidx.core.content.ContextCompat.getDrawable(ContextCompat.java:454)
at com.obsez.android.lib.filechooser.tool.DirAdapter.init(DirAdapter.java:50)
at com.obsez.android.lib.filechooser.tool.DirAdapter.(DirAdapter.java:38)
at com.obsez.android.lib.filechooser.ChooserDialog.build(ChooserDialog.java:473)
at com.ytheekshana.deviceinfo.SettingsActivity$SettingsFragment.lambda$onCreatePreferences$4(SettingsActivity.java:155)
at com.ytheekshana.deviceinfo.-$$Lambda$SettingsActivity$SettingsFragment$Y7f1g7hc3TMWquV4ySFCNsnDHKw.onPreferenceClick(Unknown Source:2)
at androidx.preference.Preference.performClick(Preference.java:1169)
at androidx.preference.Preference.performClick(Preference.java:1152)
at androidx.preference.Preference$1.onClick(Preference.java:182)
at android.view.View.performClick(View.java:7333)
at android.view.View.performClickInternal(View.java:7299)
at android.view.View.access$3200(View.java:846)
at android.view.View$PerformClick.run(View.java:27774)
at android.os.Handler.handleCallback(Handler.java:873)
at android.os.Handler.dispatchMessage(Handler.java:99)
at android.os.Looper.loop(Looper.java:214)
at android.app.ActivityThread.main(ActivityThread.java:6981)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1445)

I am Building the FileChooser like this.

ChooserDialog chooseLocation;
if (dark_theme_Pref.isChecked()) {
chooseLocation = new ChooserDialog(getActivity(), R.style.FileChooserStyle_Dark);
} else {
chooseLocation = new ChooserDialog(getActivity());
}
chooseLocation.withDateFormat("dd MMMM yyyy");
chooseLocation.displayPath(false);
chooseLocation.enableOptions(true);
chooseLocation.withResources(R.string.file_chooser_title, R.string.file_chooser_choose, R.string.cancel);
chooseLocation.withFilter(true, false);
chooseLocation.withStartFile(Environment.getExternalStorageDirectory().getAbsolutePath());
chooseLocation.withChosenListener((path, pathFile) -> {
shareEdit.putString("extract_location", path);
shareEdit.apply();
shareEdit.commit();
pref_extract_location.setSummary(path);
});
chooseLocation.build();
chooseLocation.show();

Broken on Android Q (API 29)

Hi, i migrated my app from a different library to yours yesterday, and i love how easy to use it is!
Now i also wanted to prepare my app for Android Q (API 29), but already stumbled when trying to use getExternalStorageDirectory() to get the initial path for your dialog.

According to the docs, getExternalStorageDirectory() is deprecated in Q and apps don't have access to the path anymore. The recommended solution to use Context.getExternalFilesDir(String) is kinda pointless, as it only allows you to access files under Android/data/data/your.package.name, not /storage/emulated.

It looks like the best way forward is using MediaStore with a Files collection, but right now that would require a refactoring of your library.

What are your thoughts?

Crash on Fragment

Crash Error : -

 java.lang.NullPointerException: Attempt to invoke virtual method 'java.io.File[] java.io.File.listFiles(java.io.FileFilter)' on a null object reference
                                                                        at com.obsez.android.lib.filechooser.ChooserDialog.listDirs(ChooserDialog.java:288)
                                                                        at com.obsez.android.lib.filechooser.ChooserDialog.refreshDirs(ChooserDialog.java:371)
                                                                        at com.obsez.android.lib.filechooser.ChooserDialog.build(ChooserDialog.java:204)
                                                                        at com.verveba.pimapp.view.frgmnts.LocTestingWorstPortFragment.chooseDTPFile(LocTestingWorstPortFragment.java:304)

Following code used in fragment : -

new ChooserDialog().with(getActivity())
                .withFilter(false, false, "jpg", "jpeg", "png")
                .withResources(R.string.dtp_file, R.string.title_choose, R.string.dialog_cancel)
                .withChosenListener(new ChooserDialog.Result() {
                    @Override
                    public void onChoosePath(String path, File pathFile) {
                      
                        }
                    }
                })
                .build()
                .show();

Cannot create directory on external SDCard

When the dialog opens, I go the actual external SDCard and try to create a new directory but it fails with this error:

"Couldn't create folder " + newDir.getName() + " at " + newDir.getAbsolutePath(),

If I go the external card provided by Environment.getExternalStorageDirectory(), I can create a new folder. This happens on Android 8.0 (targetSdkVersion 28).
From what I read on some forums, Android 5.0+ must use a new API (https://developer.android.com/guide/topics/providers/document-provider#client) in order to access external cards. Is this implemented in this library?

Project won't build.

Not sure what's going on, but my project won't build anymore, because it says it resolve:

import com.obsez.android.lib.filechooser.ChooserDialog;

My project was working great two days ago. I currently have your build specified as:
implementation 'com.github.hedzr:android-file-chooser:master-SNAPSHOT'

...so, I am subject to unexpected issues on each push, which is my fault. But, I also reverted to
implementation 'com.obsez.android.lib.filechooser:filechooser:1.1.0'

and I still get build errors. I'm not sure what I did wrong, or if something got goofed?

failed linking file resources

Hi,
I try to use this library in my Qt Apps.
i have a compilation error :
filechooser-1.1.14.aar\7d59b420dfe3de1865f00e24f95a41ff\res\layout\li_row_textview.xml:51: error: attribute srcCompat (aka org.qtproject.myProject:srcCompat) not found. error: failed linking file resources.

What am i doing wrong ?

regards

Not compatible with D-pad

Unable to use D-pad to click the OK or Cancel button. The focus will not stay on them. Very strange.
This has been confirmed on both physical devices and emulators.

Cannot go up to /emulated/0

I've noticed that going up function has changed when the following code was added in ChooserDialog.java. This causes the side effect that you cannot navigate up from that point onwards. Maybe the test should be (_currentDir.getParentFile() != null) && f.canRead() && (f.listFiles().length == 0). This happens on Android 6.
I think the code should be to allow up navigation until it is possible irrespective if you can show the items in that folder.

if (f.canRead()) {
_currentDir = f;
 } else {
 Toast.makeText(this._context, "Couldn't go up level", Toast.LENGTH_SHORT).show();
}

onChoosePath(String path, File pathFile) cannot have anything blocking the UI

For example, if you cannot use AlertDialog. It would not show, and the app would hang.
This is not a big deal because one can always start a new thread, then grab the UI thread to remedy this.
I thought it would be nice to have the ChooserDialog closed upon entering onChoosePath(String path, File pathFile) because it is closed anyway after this void method ends.

Secure up navigation

It would be a nice thing to have an option to secure the up level navigation. For example, one can have the following use case: start in a certain path but don't want to allow navigation further than
getExternalStorageDirectory(), basically meaning that the user cannot change from primary storage to SD card for a certain file/folder picker task. Or for example an application that allows to save resources only in an app specific folder structure, so navigating outside that app root folder is not allowed and other such scenarios.
Also it would be nice to have a callback for when the up navigation is disabled because you reached the set folder e.g. withNavigateUpTo(folder, callback).

Customize colors

The library is great. Do you plan to add item color and date color to allow customization or add theme support?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.