Android Q: file.mkdirs() returns false

khusrav picture khusrav · Jun 29, 2019 · Viewed 15.2k times · Source

We have an app that uses external storage to store some temporary files: images, binary data. The code for that has been working for a few years without big changes until recently. On Android Q it doesn't work:

File f = new File(Environment.getExternalStorageDirectory().toString() + File.separator + MainActivity.APP_DIR)
f.mkdirs();
// do sth with f

The mkdirs now returns just false.

Required permission is provided in the manifest:

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

The code works fine on previous versions of Android. Is there some system level change to this type of access? If so, what is the workaround?

Answer

Pawel picture Pawel · Jun 30, 2019

There was huge privacy change in android Q by introducing Scoped Storage.

Since Q beta 4 it's possible to opt-out of that feature by:

  • targeting API 28 (or lower)
  • using requestLegacyExternalStorage manifest attribute (while targetting API 29):

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

edit: as mentioned in other answer this does not work if app is targeting API 30 - Android 11 devices will ignore legacy storage flag.

edit 2: heads up for anyone planning to publish on play store - soon usage of this flag will be restricted (new and updated apps won't be accepted) unless its required for core functionality (e.g. file manager)