getSpecialLocation causing app crashes with Android 8.1.0

Hey there

Is anyone finding that with Projucer 5.4.2/Dev (Feb11 Commit 9d6b393aa) the Android application will crash on file access?

“[App name] has stopped. Open app again”

I’m finding this to be the case with the device simulator and on a physical device running 8.1.0 (SDK 27).

Enabling/disabling Read from External, Write to External, Content Sharing seems to have no bearing on this issue.

An example of getSpecialLocation that I’m using is:

File myDirUserRoot = File::getSpecialLocation (File::userDocumentsDirectory);

or:

File myDirUserRoot = File::getSpecialLocation(File::userApplicationDataDirectory)

These both work great with iOS and MacOS, but not joy at all with Android.

Any advice or thoughts would be very much appreciated!

Jeff

In case anyone happens upon the same issue when trying to compile for Android, I’m putting this here :slight_smile: Thanks to Daniel and MatKat for pointing me in the right direction.

iOS requests permissions ahead of time, so the permission request can be handled using the Projucer setting/manifest. Android as of API level 23 and up requires to the permission request to be handled in the running code itself.

https://docs.juce.com/develop/classRuntimePermissions.html#details

RuntimePermissions::request (RuntimePermissions::writeExternalStorage, [this] (bool granted)
{ doStuffThatYouWantedToDo
   if (! granted)
   {handleRejection}
});```

Cheers

Did you check if enabling this setting in Projucer for the iOS exporter target solves it?

Whoops, just saw you said Android, not iOS

Android has this:

As splintersilk pointed out, Android now uses RuntimePermissions, and they recommend that you ask for the permission when you need it. (https://developer.android.com/distribute/best-practices/develop/runtime-permissions)

Right. doesn’t that setting in ProJucer’s exporter settings add the necessary boilerplate to our projects automatically when it’s enabled?

I believe that setting just does the right things in the manifest. I’ve run into the same issue with recording and using the file chooser, ie. needing to add code to invoke the RuntimePermissions code. I’ve even requested that the JUCE team add the permissions request to the FileChooser dialog, so we don’t have to do it every place we user that class… (Any plans for making RuntimePermissions part of FileChooser?)

1 Like

I’m not an Android user, but it seems a little odd/frustrating to have your user experience repeatedly interrupted by “Allow X to do Y” all the time. Why not just ask all the permissions you’re likely to need at the start and be done with it? I’m probably missing some use-case concept.

For now I’m experimenting with a struct that gets instantiated at the start which in turn triggers permissions to be asked for all the stuff I’m going to need later. It seems to make for a more usable app experience so far. I realise this contravenes Android Best Practice #3 but I’m only playing and learning at the moment so whatever.

Anyway thanks MatKat and cpr for your thoughts and input :slight_smile:

@splintersilk, it doesn’t ask all the time. It asks once and remembers. A call to RuntimePermissions::request will only query the user if the permission hasn’t been granted already. Of course, you can choose to ask at startup if you like, but per the link I posted, ‘Android best practices’ recommends that you don’t ask until the user needs the permission. The link explains the rational as well. Having said that, for an audio app that wants to record, I would request the permission at startup, since that is kind of a given based on the app type.