1

My Android app using OpenStreetMap, which has been perfectly working for months, is now not able anymore to display the OpenStreetMap map. Despite the WRITE_EXTERNAL_STORAGE permission granted, I get messages like these :

E/OsmDroid: Unable to start the SQLite tile writer. Check external storage availability.
I/StorageUtils: /storage/emulated/0 is NOT writable

As I am targetting API29 and running on an Android 10 phone, I suppose the problem is related to the new policy about external storage access and the requirement to use the Storage Access Framework. Am I right?

No matter if I am right or wrong, does anyone know how I could fix this?

Shalu T D
  • 3,921
  • 2
  • 26
  • 37
Zelig63
  • 1,592
  • 1
  • 23
  • 40
  • Yes on Android Q that path is not writable. You should know that by now as your problem has been reported here five times a week for the last months. – blackapps Jun 07 '20 at 07:03
  • https://stackoverflow.com/a/57653808/588532 – Uriel Frankel Jun 07 '20 at 07:09
  • @Uriel Frankel, please dont advertise your hack as a fix. Your hack will not live long also. – blackapps Jun 07 '20 at 07:39
  • @blackapps You are right – Uriel Frankel Jun 07 '20 at 07:39
  • 1
    @blackapps but the official Android docs says: Running on Android 10 If your app targets Android 10 (API level 29), opt-out of scoped storage and continue using the approach for Android 9 and lower to perform this operation. – Uriel Frankel Jun 07 '20 at 08:12
  • Yes, then lower target level. – blackapps Jun 07 '20 at 08:31
  • Going back to API level 27 solved my problem (the logcat now tells me external storage is writable). Unfortunately, visually, it doesn't change anything : still no map but only the grid, the compass and the zoom buttons. In the logcat, I don't see any error or warning message, only `D/FA: Connected to remote service` which really looks like a good news, but don't know if it is related to OSM. – Zelig63 Jun 07 '20 at 15:12
  • Better now I have changed the data source from `HIKEBIKEMAP` to `MAPNIK`! – Zelig63 Jun 07 '20 at 15:28

2 Answers2

3

Because you are targeting Andorid 10 - api 29, the official Android docs states:

Running on Android 10

If your app targets Android 10 (API level 29), opt-out of scoped storage and continue using the approach for Android 9 and lower to perform this operation.

So you need to add to the AndroidManifest.xml:

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

@blackapps This is not a hack.

Uriel Frankel
  • 14,304
  • 8
  • 47
  • 69
  • It is a hack that helps for a certain amount of time. A hack propagated by Google indeed. You better solve a problem right away. – blackapps Jun 07 '20 at 08:33
0

A better approach is to move the storage used for cache from external to internal. This must be done before the view is loaded/inflated.

For an Activity:

Configuration.getInstance().osmdroidTileCache = filesDir

For a fragment:

Configuration.getInstance().osmdroidTileCache = requireContext().filesDir

If using Activity binding, you must change the directory right before calling this:

binding = ActivityNameBinding.inflate(layoutInflater)

Otherwise, the map view will be built and automatically attempt to access external storage.