11package com .devpaul .filepickerlibrary ;
22
3+ import android .Manifest ;
34import android .app .ProgressDialog ;
45import android .content .Context ;
56import android .content .Intent ;
7+ import android .content .pm .PackageManager ;
68import android .net .Uri ;
79import android .os .AsyncTask ;
10+ import android .os .Build ;
811import android .os .Bundle ;
912import android .os .Environment ;
13+ import android .support .v4 .app .ActivityCompat ;
14+ import android .support .v4 .content .ContextCompat ;
1015import android .support .v7 .app .AppCompatActivity ;
1116import android .support .v7 .widget .DefaultItemAnimator ;
1217import android .support .v7 .widget .LinearLayoutManager ;
1318import android .support .v7 .widget .RecyclerView ;
1419import android .support .v7 .widget .Toolbar ;
15- import android .util .Log ;
1620import android .view .MenuItem ;
1721import android .view .View ;
1822import android .view .ViewTreeObserver ;
2428import android .widget .LinearLayout ;
2529import android .widget .RelativeLayout ;
2630
31+ import com .afollestad .materialdialogs .MaterialDialog ;
2732import com .devpaul .filepickerlibrary .adapter .FileRecyclerViewAdapter ;
2833import com .devpaul .filepickerlibrary .enums .FileScopeType ;
2934import com .devpaul .filepickerlibrary .enums .FileType ;
@@ -230,7 +235,14 @@ public class FilePicker extends AppCompatActivity implements NameFileDialogInter
230235 */
231236 private Context mContext ;
232237
238+ /**
239+ * Request code for app permissions.
240+ */
241+ private static final int REQUEST_FOR_READ_EXTERNAL_STORAGE = 101 ;
233242
243+ /**
244+ * Layout manager for the Recycler View.
245+ */
234246 private LinearLayoutManager mLinearLayoutManager ;
235247
236248 @ Override
@@ -306,8 +318,7 @@ public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
306318 if (Math .abs (dy ) >= 5 ) {
307319 if (dy > 0 ) {
308320 toggleButton (false );
309- }
310- else if (dy < 0 ) {
321+ } else if (dy < 0 ) {
311322 toggleButton (true );
312323 }
313324 if (areButtonsShowing ) {
@@ -318,8 +329,7 @@ else if(dy < 0) {
318329 hideButtons ();
319330 adapter .setSelectedPosition (-1 );
320331 }
321- }
322- else {
332+ } else {
323333 mLastFirstVisibleItem = firstVisibleItem ;
324334 }
325335 super .onScrolled (recyclerView , dx , dy );
@@ -332,23 +342,83 @@ else if(dy < 0) {
332342 //drawable has not been set so set the color.
333343 setHeaderBackground (colorId , drawableId );
334344
345+ //check for proper permissions.
346+ if (Build .VERSION .SDK_INT == Build .VERSION_CODES .M ) {
347+ int permissionCheck = ContextCompat .checkSelfPermission (this ,
348+ Manifest .permission .READ_EXTERNAL_STORAGE );
349+ if (permissionCheck != PackageManager .PERMISSION_GRANTED ) {
350+ if (ActivityCompat .shouldShowRequestPermissionRationale (this , Manifest .permission .READ_EXTERNAL_STORAGE )) {
351+ //Show permission rationale.
352+ new MaterialDialog .Builder (FilePicker .this )
353+ .title (R .string .file_picker_permission_rationale_dialog_title )
354+ .content (R .string .file_picker_permission_rationale_dialog_content )
355+ .positiveText (R .string .file_picker_ok )
356+ .negativeText (R .string .file_picker_cancel )
357+ .callback (new MaterialDialog .ButtonCallback () {
358+ @ Override
359+ public void onPositive (MaterialDialog dialog ) {
360+ ActivityCompat .requestPermissions (FilePicker .this ,
361+ new String []{Manifest .permission .READ_EXTERNAL_STORAGE ,
362+ Manifest .permission .WRITE_EXTERNAL_STORAGE },
363+ REQUEST_FOR_READ_EXTERNAL_STORAGE );
364+ }
365+
366+ @ Override
367+ public void onNegative (MaterialDialog dialog ) {
368+ setResult (RESULT_CANCELED );
369+ finish ();
370+ }
371+ })
372+ .show ();
373+ }
374+ else {
375+ ActivityCompat .requestPermissions (this ,
376+ new String []{Manifest .permission .READ_EXTERNAL_STORAGE ,
377+ Manifest .permission .WRITE_EXTERNAL_STORAGE },
378+ REQUEST_FOR_READ_EXTERNAL_STORAGE );
379+ }
380+ }
381+ } else {
382+ init ();
383+ }
384+ }
385+
386+ /**
387+ * Initialize the current directory.
388+ */
389+ private void init () {
335390 curDirectory = new File (Environment .getExternalStorageDirectory ().getPath ());
336391 currentFile = new File (curDirectory .getPath ());
337392 lastDirectory = curDirectory .getParentFile ();
338393
339394 if (curDirectory .isDirectory ()) {
340- Log .d ("FILEPICKER" , "Is directory" );
341395 new UpdateFilesTask (this ).execute (curDirectory );
342396 } else {
343- Log .d ("FILEPICKER" , "Is not directory" );
344397 try {
345- throw new Exception ("Initial file must be a directory." );
398+ throw new Exception (getString ( R . string . file_picker_directory_error ) );
346399 } catch (Exception e ) {
347400 e .printStackTrace ();
348401 }
349402 }
350403 }
351404
405+ @ Override
406+ public void onRequestPermissionsResult (int requestCode , String [] permissions , int [] grantResults ) {
407+ switch (requestCode ) {
408+ //see if we got the permission.
409+ case REQUEST_FOR_READ_EXTERNAL_STORAGE :
410+ if (grantResults .length > 0 && grantResults [0 ] == PackageManager .PERMISSION_GRANTED
411+ && grantResults [1 ] == PackageManager .PERMISSION_GRANTED ) {
412+ init ();
413+ }
414+ else {
415+ setResult (RESULT_CANCELED );
416+ finish ();
417+ }
418+ return ;
419+ }
420+ }
421+
352422 private static OvershootInterpolator interpolator = new OvershootInterpolator ();
353423 /**
354424 * Toggles the material floating action button.
@@ -415,7 +485,7 @@ public void onClick(View view) {
415485 finish ();
416486 } else {
417487 SnackbarManager .show (Snackbar .with (FilePicker .this )
418- .text ("Please select a directory." )
488+ .text (R . string . file_picker_snackbar_select_directory_message )
419489 .duration (1500 ));
420490 }
421491 } else { //request code is for a file
@@ -433,7 +503,8 @@ public void onClick(View view) {
433503 finish ();
434504 } else {
435505 SnackbarManager .show (Snackbar .with (FilePicker .this )
436- .text ("Please select a " + requiredExtension + " file." )
506+ .text (String .format (getString (R .string .file_picker_snackbar_select_file_ext_message ),
507+ requiredExtension ))
437508 .duration (1500 ));
438509 }
439510 } else {
@@ -465,11 +536,11 @@ public void onClick(View view) {
465536 startActivity (newIntent );
466537 } catch (android .content .ActivityNotFoundException e ) {
467538 SnackbarManager .show (Snackbar .with (FilePicker .this )
468- .text ("No handler for this type of file." ));
539+ .text (R . string . file_picker_snackbar_no_file_type_handler ));
469540 }
470541 } else {
471542 SnackbarManager .show (Snackbar .with (FilePicker .this )
472- .text ("Couldn't get file type." ));
543+ .text (R . string . file_picker_snackbar_no_read_type ));
473544 }
474545
475546 }
@@ -556,7 +627,7 @@ public void onReturnFileName(String fileName) {
556627 if (fileName .equalsIgnoreCase ("" ) || fileName .isEmpty ()) {
557628 fileName = null ;
558629 }
559- if (fileName != null ) {
630+ if (fileName != null && curDirectory != null ) {
560631 File file = new File (curDirectory .getPath () + "//" + fileName );
561632 boolean created = false ;
562633 if (!file .exists ()) {
@@ -613,9 +684,8 @@ private UpdateFilesTask(Context context) {
613684
614685 @ Override
615686 protected void onPreExecute () {
616- Log .i ("FilePicker" , "AsyncCalled" );
617687 dialog = new ProgressDialog (mContext );
618- dialog .setMessage ("Loading..." );
688+ dialog .setMessage (getString ( R . string . file_picker_progress_dialog_loading ) );
619689 dialog .setCancelable (false );
620690 dialog .show ();
621691 hideButtons ();
@@ -635,7 +705,7 @@ protected void onPostExecute(File[] localFiles) {
635705 files = localFiles ;
636706 if (directory .getPath ().equalsIgnoreCase (Environment
637707 .getExternalStorageDirectory ().getPath ())) {
638- toolbar .setTitle ("Parent Directory" );
708+ toolbar .setTitle (getString ( R . string . file_picker_default_directory_title ) );
639709
640710 } else {
641711 toolbar .setTitle (directory .getName ());
@@ -647,9 +717,15 @@ protected void onPostExecute(File[] localFiles) {
647717// for(int i = 0; i < files.length; i++) {
648718// adapter.addFile(files[i]);
649719// }
650- adapter = new FileRecyclerViewAdapter (FilePicker .this , files , scopeType , callback );
651- //TODO: Fix this, figure out how to add and remove the header.
652- recyclerView .setAdapter (adapter );
720+ if (files != null ) {
721+ adapter = new FileRecyclerViewAdapter (FilePicker .this , files , scopeType , callback );
722+ //TODO: Fix this, figure out how to add and remove the header.
723+ recyclerView .setAdapter (adapter );
724+ }
725+ //make sure the button is showing.
726+ if (!isFabShowing ) {
727+ toggleButton (true );
728+ }
653729 if (dialog .isShowing ()) {
654730 dialog .dismiss ();
655731 }
0 commit comments