New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Osmdroid 6.0.2, cannot switch from SqlTileWriter to TileWriter (local storage) #1172

Closed
DimMad opened this Issue Oct 23, 2018 · 17 comments

Comments

Projects
None yet
3 participants
@DimMad

DimMad commented Oct 23, 2018

Hello. I am playing around with Osmdroid for use in an application. I already have a tiles server and want to use those tiles. Looked into docs used setTileSource(new XYTileSource()) magic happened. I have to mention that the documentation is a bit stale on many parts.

The tiles of the aforementioned server are already used in the app in a different feature. As logic dictates I want to use the same cache location so that I do not have to have duplicates of the tiles in the system. Again through docs, used Configuration.getInstance().setOsmdroidTileCase(new File("path")) and again everything is going just fine. This was not so easy though as the documentation refers to the Osmdroids Constants class which is changed in the latest stable.

Then last part is to change from the SqlTileWriter to a normal TileWriter as we already have the image files downloaded from the other feature. This is where I cannot figure it out. I am using:

MapTileProviderBasic tileProvider = new MapTileProviderBasic(getActivity(), new XYTileSource("My Tiles", 5, 16, 256, ".png",
            new String[]{"SERVER_URL"}), new TileWriter());
mMap.setTileProvider(tileProvider);

and things get weird. The images are actually downloading but the map shows just the loading background. In the logs I got StorageUtils telling me that the storage is not writable. Gave permissions to the app, now writable, still nothing. I noticed that except from the tiles folder the .db files have been created but the tiles table is empty. I went back to the above code and replaced the new TileWriter() with a new SQLTileWriter() just for sanity check and the map works just fine, without any permissions.

Trying to figure out what I am doing wrong I entered the realm of the libs code. I am not sure yet if this might be the issue as I do not have a full understanding of the code, but in the lib's MapTileProviderBasic lines 76 to 95 we have the following code:

        if (cacheWriter != null) {
		tileWriter = cacheWriter;
	} else {
		if (Build.VERSION.SDK_INT < 10) {
			tileWriter = new TileWriter();
		} else {
			tileWriter = new SqlTileWriter();
		}
	}
	final MapTileAssetsProvider assetsProvider = new MapTileAssetsProvider(
			pRegisterReceiver, pContext.getAssets(), pTileSource);
	mTileProviderList.add(assetsProvider);

	final MapTileFileStorageProviderBase cacheProvider;
	if (Build.VERSION.SDK_INT < 10) {
		cacheProvider = new MapTileFilesystemProvider(pRegisterReceiver, pTileSource);
	} else {
		cacheProvider = new MapTileSqlCacheProvider(pRegisterReceiver, pTileSource);
	}
	mTileProviderList.add(cacheProvider);

In the last if statement the cacheProvider is basically version forced to a MapTileSqlCacheProvider.

Could that be the problem or am I doing something wrong?

@monsieurtanuki

This comment has been minimized.

Collaborator

monsieurtanuki commented Oct 24, 2018

@DimMad I agree with you, there seems to be an inconsistency in MapTileProviderBasic: if ever you want a (file-based) TileWriter (which is not in the general the best option, but it's your choice), the MapTileFileStorageProviderBase should match it and choose MapTileFilesystemProvider regardless of the build version.
I may be wrong but roughly said, I think the tileWriter in your code excerpt is about how to store the new downloaded tiles, and the cacheProvider is about adding a source.

I would suggest you to duplicate MapTileProviderBasic in order to run tests: the only thing you'd change is unconditionally making cacheProvider an instance of MapTileFilesystemProvider.

Is the current code to be fixed, and how? Perhaps by creating a new protected method in MapTileProviderBasic called buildCacheProvider, to be called in the constructor, and that would contain some lousy tip-tap code including tileWriter instanceof TileWriter and/or Build.VERSION.SDK_INT < 10 tests. And for flexibility, whoever needs more finesse may override this method.

Would you try first to duplicate MapTileProviderBasic in your project as suggested, and tell us if it worked? Thanks!

@DimMad

This comment has been minimized.

DimMad commented Oct 25, 2018

@monsieurtanuki Thank you for your reply. I did not get the chance to work on my tests since my OP. I will try your recommendation as soon as I get the chance and post back. Thanks again.

@monsieurtanuki monsieurtanuki self-assigned this Oct 26, 2018

@fariz-siracli

This comment has been minimized.

fariz-siracli commented Oct 26, 2018

Hello. I how can i disable default map? I use Custom tile provider to show tiles from my own server.

@monsieurtanuki

This comment has been minimized.

Collaborator

monsieurtanuki commented Oct 26, 2018

@fariz-siracli I guess the first step is to create your own TileSource; for that you'll find inspiration in TileSourceFactory or in this wiki page.
Then create an instance of a provider that includes a MapTileDownloader that uses your TileSource, for instance using MapTileProviderBasic(Context pContext, ITileSource pTileSource).
I hope this helps.

@monsieurtanuki

This comment has been minimized.

Collaborator

monsieurtanuki commented Oct 26, 2018

@fariz-siracli After re-reading your question, if it's strictly about disabling other map tile providers, duplicate MapTileProviderBasic and remove from the constructor all the providers you don't want to use.

monsieurtanuki added a commit that referenced this issue Oct 26, 2018

bug/#1172 - consistency between tile writer and tile provider
Impacted classes:
* `MapTileProviderBasic`: new `static` method `getMapTileFileStorageProviderBase` that fixes the possible inconsistency between the `IFilesystemCache` and the `MapTileFileStorageProviderBase`; used this method the constructor; unrelated constructor gentle refactoring
* `GeoPackageProvider`: used new `static` method `MapTileProviderBasic.getMapTileFileStorageProviderBase` in the constructor
* `SampleLieFi`: used new `static` method `MapTileProviderBasic.getMapTileFileStorageProviderBase` in `MapTileProviderLieFi`'s constructor
@monsieurtanuki

This comment has been minimized.

Collaborator

monsieurtanuki commented Oct 26, 2018

Fixed by #1174.

monsieurtanuki added a commit that referenced this issue Oct 26, 2018

Merge pull request #1174 from osmdroid/bug/#1172
bug/#1172 - consistency between tile writer and tile provider
@fariz-siracli

This comment has been minimized.

fariz-siracli commented Oct 26, 2018

I could create an example which uses my server url. The problem is that when map is downloaded, user can see default map (i think openstreetmap) behind. So i want to disable it. In google maps i did this by
map.setMapType(GoogleMap.MAP_TYPE_NONE);
Isn't it possible?

@monsieurtanuki

This comment has been minimized.

Collaborator

monsieurtanuki commented Oct 26, 2018

@DimMad I've just merged #1174, which fixes your issue. Feel free to reopen this issue if needed.

@fariz-siracli I don't think there's a shortcut in osmdroid looking like your MAP_TYPE_NONE.
I think the way to achieve what you want is by creating your own map tile provider as stated in my previous post. Please try this suggested solution, and if ever it doesn't work, please do open a new issue as this one has nothing to do with your (legitimate) question.

@fariz-siracli

This comment has been minimized.

fariz-siracli commented Oct 26, 2018

Ok. I will try it later and write the result here. Thank you.

@DimMad

This comment has been minimized.

DimMad commented Oct 29, 2018

@monsieurtanuki I just tried what we had discussed and it was indeed an issue of the wrong Provider being selected. Thank you very much for the fix.

@fariz-siracli

This comment has been minimized.

fariz-siracli commented Oct 29, 2018

@monsieurtanuki, I'm sorry, but i could not understand what you you exactly mean by "duplicate MapTileProviderBasic and remove from the constructor all the providers ". Below is the code which i modified from sample.

final MapTileProviderBasic tileProvider = new MapTileProviderBasic(getApplicationContext());

   tileProvider.setTileSource(new OnlineTileSourceBase("USGS Topo", 0, 18, 256, "",
            new String[]{"https://xxxxxxx.az/smoothtiles/mobiletile.do?lng=az"}) {
        @Override
        public String getTileURLString(long pMapTileIndex) {
            String url = getBaseUrl() + "&x=" + MapTileIndex.getX(pMapTileIndex) + "&y=" + MapTileIndex.getY(pMapTileIndex) + "&z=" + MapTileIndex.getZoom(pMapTileIndex) + "&f=png&dp=0";
            Log.i("OSM", "url = " + url);
            return url;
        }
    });
   
    tileProvider.setTileRequestCompleteHandler(mMapView.getTileRequestCompleteHandler());
    final TilesOverlay tilesOverlay = new TilesOverlay(tileProvider, this.getBaseContext());
    tilesOverlay.setLoadingBackgroundColor(Color.TRANSPARENT);

    mMapView.getOverlays().add(tilesOverlay);
@monsieurtanuki

This comment has been minimized.

Collaborator

monsieurtanuki commented Oct 29, 2018

@fariz-siracli I meant that you can create you own MyOwnMapTileProviderBasic class, that is a copy/paste of osmdroid's MapTileProviderBasic. Then, you can edit the code and do whatever you want, including removing tile providers that you don't want to use.
If that doesn't solve your issue, as already stated, please create a distinct issue.

@fariz-siracli

This comment has been minimized.

fariz-siracli commented Oct 29, 2018

i'm looking at MapTileProviderBasic class's implementation and can not find anything that may remove default map...
About new issue, ok. But first, i wanna be sure that your suggest does not solve my question..

@DimMad

This comment has been minimized.

DimMad commented Oct 29, 2018

@fariz-siracli You said that you are using you tile provider, correct? In that case what do you mean by removing the default map? You have already replaced the Tile provider so you should already be using you own map and not the default.

@fariz-siracli

This comment has been minimized.

fariz-siracli commented Oct 29, 2018

@DimMad Yes i'm already using it. But when map downloads default map is seen behind my map and after my tile overlay finishes downloading tile overlay covers default map.
Now i want to avoid downloading default map, because it doubles traffic usage and other there also other reasons..
Thanks.

@DimMad

This comment has been minimized.

DimMad commented Oct 29, 2018

Oh, I see... That is certainly a weird behavior. Personally I didn't have that issue just setting the mMap.setTileSource(new XYTileSource("My Tiles", 5, 16, 256, ".png", new String[]{"https://my.server.url/"})); did it. The reason I looked into providers was to change my TileWriter.

Just one idea. Did you make the tiles change after you first used the app and if so, did you try to clean the cache before running with the new tile source? Just throwing ideas here but maybe you have a dirty cache? If you are fully clean and still having the issue I would also suggest to start a new issue and throw some of you code there for people to try and help.

@fariz-siracli

This comment has been minimized.

fariz-siracli commented Oct 30, 2018

Guys i found solution.
mMapView.getTileProvider().detach();
before adding any overlay could solve it.
Thanks for attention.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment