4141public class DocumentPickerModule extends ReactContextBaseJavaModule {
4242 private static final String NAME = "RNDocumentPicker" ;
4343 private static final int READ_REQUEST_CODE = 41 ;
44+ private static final int PICK_DIR_REQUEST_CODE = 42 ;
4445
4546 private static final String E_ACTIVITY_DOES_NOT_EXIST = "ACTIVITY_DOES_NOT_EXIST" ;
4647 private static final String E_FAILED_TO_SHOW_PICKER = "FAILED_TO_SHOW_PICKER" ;
@@ -51,7 +52,7 @@ public class DocumentPickerModule extends ReactContextBaseJavaModule {
5152 private static final String E_UNEXPECTED_EXCEPTION = "UNEXPECTED_EXCEPTION" ;
5253
5354 private static final String OPTION_TYPE = "type" ;
54- private static final String OPTION_MULIPLE = "multiple" ;
55+ private static final String OPTION_MULTIPLE = "multiple" ;
5556 private static final String OPTION_COPYTO = "copyTo" ;
5657
5758 private static final String FIELD_URI = "uri" ;
@@ -61,13 +62,17 @@ public class DocumentPickerModule extends ReactContextBaseJavaModule {
6162 private static final String FIELD_TYPE = "type" ;
6263 private static final String FIELD_SIZE = "size" ;
6364
65+
6466 private final ActivityEventListener activityEventListener = new BaseActivityEventListener () {
6567 @ Override
6668 public void onActivityResult (Activity activity , int requestCode , int resultCode , Intent data ) {
69+ if (promise == null ) {
70+ return ;
71+ }
6772 if (requestCode == READ_REQUEST_CODE ) {
68- if ( promise != null ) {
69- onShowActivityResult ( resultCode , data , promise );
70- }
73+ onShowActivityResult ( resultCode , data , promise );
74+ } else if ( requestCode == PICK_DIR_REQUEST_CODE ) {
75+ onPickDirectoryResult ( resultCode , data , promise );
7176 }
7277 }
7378 };
@@ -126,7 +131,7 @@ public void pick(ReadableMap args, Promise promise) {
126131 }
127132 }
128133
129- boolean multiple = !args .isNull (OPTION_MULIPLE ) && args .getBoolean (OPTION_MULIPLE );
134+ boolean multiple = !args .isNull (OPTION_MULTIPLE ) && args .getBoolean (OPTION_MULTIPLE );
130135 intent .putExtra (Intent .EXTRA_ALLOW_MULTIPLE , multiple );
131136
132137 currentActivity .startActivityForResult (Intent .createChooser (intent , null ), READ_REQUEST_CODE , Bundle .EMPTY );
@@ -175,6 +180,43 @@ public void onShowActivityResult(int resultCode, Intent data, Promise promise) {
175180 }
176181 }
177182
183+ @ ReactMethod
184+ public void pickDirectory (Promise promise ) {
185+ Activity currentActivity = getCurrentActivity ();
186+
187+ if (currentActivity == null ) {
188+ promise .reject (E_ACTIVITY_DOES_NOT_EXIST , "Current activity does not exist" );
189+ return ;
190+ }
191+ this .promise = promise ;
192+ try {
193+ Intent intent = new Intent (Intent .ACTION_OPEN_DOCUMENT_TREE );
194+ currentActivity .startActivityForResult (intent , PICK_DIR_REQUEST_CODE , null );
195+ } catch (Exception e ) {
196+ sendError (E_FAILED_TO_SHOW_PICKER , "Failed to create directory picker" , e );
197+ }
198+ }
199+
200+ private void onPickDirectoryResult (int resultCode , Intent data , Promise promise ) {
201+ if (resultCode == Activity .RESULT_CANCELED ) {
202+ sendError (E_DOCUMENT_PICKER_CANCELED , "User canceled directory picker" );
203+ return ;
204+ } else if (resultCode != Activity .RESULT_OK ) {
205+ sendError (E_UNKNOWN_ACTIVITY_RESULT , "Unknown activity result: " + resultCode );
206+ return ;
207+ }
208+
209+ if (data == null || data .getData () == null ) {
210+ sendError (E_INVALID_DATA_RETURNED , "Invalid data returned by intent" );
211+ return ;
212+ }
213+ Uri uri = data .getData ();
214+
215+ WritableMap map = Arguments .createMap ();
216+ map .putString (FIELD_URI , uri .toString ());
217+ promise .resolve (map );
218+ }
219+
178220 private static class ProcessDataTask extends GuardedResultAsyncTask <ReadableArray > {
179221 private final WeakReference <Context > weakContext ;
180222 private final List <Uri > uris ;
0 commit comments