BoardiesITSolutions / FileDirectoryPicker

Simple directory/file picker for Android
MIT License
8 stars 2 forks source link

Crash when opening DirectoryPicker #3

Closed apacha closed 5 years ago

apacha commented 5 years ago

Describe the bug Upon starting the activity, the application crashes because of an unhandled NullPointerException by FileDirectoryPicker.

StackTrace

2019-09-02 14:03:04.470 19237-19237/at.mycompany.app.gk D/PermissionManager: Got permission request: 1
2019-09-02 14:03:04.470 19237-19237/at.mycompany.app.gk D/PermissionManager: Requesting permission 'android.permission.READ_EXTERNAL_STORAGE'
2019-09-02 14:03:04.475 19237-19237/at.mycompany.app.gk V/FileManager: Root Path: /storage/emulated/0
2019-09-02 14:03:04.476 19237-19237/at.mycompany.app.gk D/AndroidRuntime: Shutting down VM
2019-09-02 14:03:04.477 19237-19237/at.mycompany.app.gk E/AndroidRuntime: FATAL EXCEPTION: main
    Process: at.mycompany.app.gk, PID: 19237
    java.lang.RuntimeException: Unable to start activity ComponentInfo{at.mycompany.app.gk/com.BoardiesITSolutions.FileDirectoryPicker.DirectoryPicker}: java.lang.NullPointerException: Attempt to get length of null array
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3270)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409)
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83)
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135)
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95)
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016)
        at android.os.Handler.dispatchMessage(Handler.java:107)
        at android.os.Looper.loop(Looper.java:214)
        at android.app.ActivityThread.main(ActivityThread.java:7356)
        at java.lang.reflect.Method.invoke(Native Method)
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930)
     Caused by: java.lang.NullPointerException: Attempt to get length of null array
        at com.BoardiesITSolutions.FileExplorer.Logic.FileManager.getFilesAndDirectoryStructure(FileManager.java:54)
        at com.BoardiesITSolutions.FileExplorer.Logic.FileManager.getFilesAndDirectoryStructure(FileManager.java:32)
        at com.BoardiesITSolutions.FileDirectoryPicker.BasePicker.retrieveDirectoryListing(BasePicker.java:202)
        at com.BoardiesITSolutions.FileDirectoryPicker.BasePicker.permissionGranted(BasePicker.java:435)
        at com.BoardiesITSolutions.FileDirectoryPicker.PermissionManager.requestPermission(PermissionManager.java:72)
        at com.BoardiesITSolutions.FileDirectoryPicker.BasePicker.init(BasePicker.java:193)
        at com.BoardiesITSolutions.FileDirectoryPicker.DirectoryPicker.onCreate(DirectoryPicker.java:20)
        at android.app.Activity.performCreate(Activity.java:7802)
        at android.app.Activity.performCreate(Activity.java:7791)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1299)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3245)
        at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3409) 
        at android.app.servertransaction.LaunchActivityItem.execute(LaunchActivityItem.java:83) 
        at android.app.servertransaction.TransactionExecutor.executeCallbacks(TransactionExecutor.java:135) 
        at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:95) 
        at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2016) 
        at android.os.Handler.dispatchMessage(Handler.java:107) 
        at android.os.Looper.loop(Looper.java:214) 
        at android.app.ActivityThread.main(ActivityThread.java:7356) 
        at java.lang.reflect.Method.invoke(Native Method) 
        at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:492) 
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:930) 

Interestingly this worked in the application, but upon switching flavors, this picker does no longer work. Have you ever tested it with build flavors? Any ideas what could be the reason for this library to not be able to retrieve the folders in one flavor, but work fine in the other?

boardy commented 5 years ago

That seems odd. I've used build flavors related to debug and release builds and that was fine but I wouldn't have thought it should make a difference.

Are you using any other specific build flavors other than the debug and release or are you doing anything different with how the file directory picker is being initialised based on what build flavor you are using.

Thanks

Chris

apacha commented 5 years ago

I'm not talking about debug/release flavors, I'm actually referring to two different applications that use the same source code but look different visually (and have a little different functionality).

boardy commented 5 years ago

Ah I see.

So if I understand correctly you have an android library being used by two applications and the android library includes the file directory picker library.

I haven't tested this particular scenario but I'll have a look after I finish work and see if I can replicate the problem.

If this is just two different applications with a copy and paste of the source code effectively just different XML layouts for UI and each app is directly adding the file directory picker it shouldn't make any difference. There must be some difference in how the library is being initialised between the working and non working app unless I'm missing something.

On Mon, 2 Sep 2019, 13:55 Alexander Pacha, notifications@github.com wrote:

I'm not talking about debug/release flavors, I'm actually referring to two different applications that use the same source code but look different visually (and have a little different functionality).

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/BoardiesITSolutions/FileDirectoryPicker/issues/3?email_source=notifications&email_token=ABCS2MZW6DW6L75Z7I3JVTDQHUELLA5CNFSM4IS42KM2YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD5VX3MI#issuecomment-527138225, or mute the thread https://github.com/notifications/unsubscribe-auth/ABCS2M6COY5S3OZCOUCZ2ALQHUELLANCNFSM4IS42KMQ .

apacha commented 5 years ago

Ok, I've played around a little bit, and now I'm getting this error in both flavors.

boardy commented 5 years ago

So what have you changed, it must be something to do with the way you are initialising the library - admittedly the library should be protecting against the exception.

apacha commented 5 years ago

I re-installed the app in the simulator. I have one difference to the official tutorial: I'm already using SDK 29 and androidx.* library instead of appcompat.

boardy commented 5 years ago

The activities within the library does use appcompat, not sure what androidx.* is. If you've got some info on that you can send me I can give it a try and see what I can do to fix it.

There were some changes I believe in API 29 (Android Q) related to how much access android apps/libraries have to a users storage, I don't think there's a way of having a free for all on the SD card for example as it now uses scoped storage - that in the app only has access to its own files and can't see files created by other apps so this maybe the cause of the issue you are seeing.

There's more info on the scoped file storage at https://developer.android.com/preview/privacy/scoped-storage

If this is the reason I can look into adding support for this - I wasn't sure anyone was using this library that much so haven't spent a huge amount of time with it for Android Q.

apacha commented 5 years ago

I'm using Android Q and this actually seems to be the problem. I've added the

<manifest ... >
  <!-- This attribute is "false" by default on apps targeting Android Q. -->
  <application android:requestLegacyExternalStorage="true" ... >
    ...
  </application>
</manifest>

flag to the manifest and now it works in both flavors... very interesting.

If you have time, it would be great, if you could look into this.

boardy commented 5 years ago

Ah that's good. It sounds like what I thought then its to do with the new scoped storage in Android Q and that flag allows it to support the legacy storage way as previous versions used to work.

I can look into implementing this properly in Android Q so it can use app specific storage scopes. I'll let you know once I have a new release ready for you to try.

boardy commented 5 years ago

Hey, just to let you know I've just pushed out release 1.0.0.7 to properly support Android 10 and the scoped storage.

I've also made a slight change to the save file so it returns 2 parameters in the intent. If you use the key SaveFilePicker.BUNDLE_SAVE_PATH that will return the directory path instead of the full path and SaveFilePicker.BUNDLE_SAVE_FILE will return the file name.

I found this made a bit more sense when you are trying to write a file as the FileOutputStream requires the path and file as two different parameters instead of being one full path.

Let me know if you have any problems - you should be able to turn off the requestLegacyMode in your apps Android manifest.

Thanks Chris