Osmdroid cache location becomes not readable on upgrade to Android 11
See original GitHub issueIssue 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:
- Created 3 years ago
- Comments:13
So far looking good in my own tests. Waiting more information from others.
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
: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
toI 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
withAnd 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.