question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Osmdroid cache location becomes not readable on upgrade to Android 11

See original GitHub issue

Issue Type

[ ] Question [x] Bug [x] Improvement [ ] Build system related [ ] Performance [ ] Documentation

Description and/or steps/code to reproduce the problem

In the documentation at https://osmdroid.github.io/osmdroid/Important-notes-on-using-osmdroid-in-your-app.html I read the following about the cache location:

Handling Cache Storage

osmdroid does not work without somewhere to cache the tiles. The first time starting an application using osmdroid will scan for all available, writable mount points on the device. It auto selects the largest mount point. This, of course can be changed via the IConfigurationProvider. If that mount point suddenly becomes read only or disappears, osmdroid will not handle this scenario. Instead, users will get the familiar gray grid with no map tiles being displayed (uh oh). To overcome this, applications using osmdroid should probably check on startup to see what the selected cache location is via ConfigurationProvider.getOsmdroidTileCache() source then by checking StorageUtils.isWritable. If it is writable, no further action is required. Otherwise, you should probably prompt the user or autoselect the next best location.

A user of my app has recently upgraded from Android 10 to Android 11. After the upgrade my app does not load the map tiles, and the following is shown in logcat:

01-10 19:37:11.902 14023 14056 E SQLiteLog: (14) os_unix.c:38589: (13) open(/storage/emulated/0/osmdroid/tiles/cache.db) - 
01-10 19:37:11.908 14023 14056 E SQLiteDatabase: Failed to open database '/storage/emulated/0/osmdroid/tiles/cache.db'.
01-10 19:37:11.908 14023 14056 E SQLiteDatabase: android.database.sqlite.SQLiteCantOpenDatabaseException: Cannot open database '/storage/emulated/0/osmdroid/tiles/cache.db': File /storage/emulated/0/osmdroid/tiles/cache.db is not readable
01-10 19:37:11.908 14023 14056 E SQLiteDatabase: 	at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:252)
...
01-10 19:37:11.909 14023 14056 E OsmDroid: Unable to start the sqlite tile writer. Check external storage availability.
01-10 19:37:11.909 14023 14056 E OsmDroid: android.database.sqlite.SQLiteCantOpenDatabaseException: Cannot open database '/storage/emulated/0/osmdroid/tiles/cache.db': File /storage/emulated/0/osmdroid/tiles/cache.db is not readable
01-10 19:37:11.909 14023 14056 E OsmDroid: 	at android.database.sqlite.SQLiteConnection.open(SQLiteConnection.java:252)
...

A simple cache clear and files clear and even a reinstall of the same version of the app does not work.

The only thing that solved the issue was to downgrade the version to an older version that did have Android 11 support.

After this the logcat output looks like this:

01-10 21:52:10.646  9528  9528 I StorageUtils: /data/user/0/org.ttnmapper.phonesurveyor/files is writable
01-10 21:52:10.649  9528  9528 I StorageUtils: /storage/emulated/0/Android/data/<REDACTED>/files is writable
01-10 21:52:10.649  9528  9528 I StorageUtils: /data/user/0/<REDACTED>/files is writable
01-10 21:52:10.649  9528  9528 I StorageUtils: /storage/emulated/0/Android/data/<REDACTED>/files is writable

01-10 21:52:10.659  9528  9528 I OsmDroid: Tile cache increased from 0 to 9

01-10 21:52:10.668  9528  9528 I OsmDroid: Using tile source: Mapnik
01-10 21:52:10.668  9528  9528 I OsmDroid: Tile cache increased from 0 to 9

What I believe happens here is the following:

  • Android 10, app is installed
  • At first run osmdroid scans for writable locations, finds /storage/emulated/0/ to be writable and chooses it for the cache location
  • Cache location is remembered by storing it in SharedPreferences (or I hope so)
  • Android updates to 11
  • App starts up and gets the cache location from SharedPreferences
  • Cache location is not accessible anymore under Android 11, we get the error, and tiles do not load
  • A downgrade of the app forces a shared preferences clear, which a cache clear, file clear and reinstall did not
  • Downgraded version of the app on Android 11 finds a new readable and writable location for the cache

Unfortunately I have to speculate as I do not have a way to downgrade and upgrade the Android version on a device or emulator.

Workaround

I hope I can work around this by detecting when the SDK version changes and then clearing the SharedPreferences with code similar to this. That is assuming that osmdroid stores the cache location in SharedPreferences.

        // Handle android version upgrades
        val currentApiVersion = Build.VERSION.SDK_INT
        val previousApiVersion = prefs.getInt("apiVersion", 0)

        if(currentApiVersion != previousApiVersion) {
            try {
                val editor = prefs.edit();

                // Before API 30 we need to handle osmdroid's wrong storage location
                if(previousApiVersion < 30) {
                    editor.clear()
                }

                editor.putInt("apiVersion", currentApiVersion)
                editor.apply()
            } catch(e: Exception) {
                Log.e(TAG, "Can't migrate preferences")
                e.printStackTrace()
            }
        }

A more elegant solution from osmdroid’s side would be great. Is there perhaps something opposite of ConfigurationProvider.getOsmdroidTileCache() that will clear and auto select the next best location?

If it’s a bug, version(s) of android this affects:

Upgrade from Android 10 to Android 11, aka SDK 29 to SDK 30, aka Android Q to Android R

Version of osmdroid the issue relates to:

6.1.9-SNAPSHOT

Issue Analytics

  • State:open
  • Created 3 years ago
  • Comments:13

github_iconTop GitHub Comments

1reaction
taiffucommented, Apr 25, 2021

So far looking good in my own tests. Waiting more information from others.

0reactions
mikebravoyescommented, Dec 9, 2021

My smartphone “Google Pixel 3” was delivered with Android 11 (API 30).

Originally, my app Sensor Recording was compiled with the following settings in build.gradle:

compileSdkVersion 30
defaultConfig {
    targetSdkVersion 30
    …
}
dependencies {
    implementation group: 'org.osmdroid', name: 'osmdroid-android', version: '6.1.11'
    …
}

Some weeks ago, my phone was updated automatically to Android 12 (API 31). Everything continued to work without any problems.

When I changed the build.gradle to

compileSdkVersion 31
defaultConfig {
    targetSdkVersion 31
    …
}

I got the following error message from the compiler:

Manifest merger failed : android:exported needs to be explicitly specified for <activity>. Apps targeting Android 12 and higher are required to specify an explicit value for android:exported when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.

So I amended the AndroidManifest.xml with

<activity
   …
   android:exported="true">

And everything was fine again. No need to do anything with the osmdroid cache. I also tested on a tablet “Samsung Galaxy Tab A LTE 10.5” with Android 10 (API 29) without any problems.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Osmdroid maps not loading on my device - Stack Overflow
Default cache location with osmdroid 5.6 and up is the largest writable storage partition. This will then be saved as a preference (again ......
Read more >
osmdroid
It might be because in Android 9+, http (and not httpS) URLs are not ... I change where osmdroid looks for tile archives...
Read more >
osmdroid and mapsforge - Google Groups
OSMDroid does not need patching for this to work. ... org.mapsforge.android.maps/cache/' folder either. Martin.
Read more >
Index (osmdroid-android 6.0.1 API) - Javadoc.io
cacheCapacity () - Method in class org.osmdroid.tileprovider.cachemanager. ... Enable receiving location updates from the provided IMyLocationProvider and ...
Read more >
Google Codelabs
Google Developers Codelabs provide a guided, tutorial, hands-on coding experience. Most codelabs will step you through the process of building a small ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found