B4A Library OSMDroid - MapView for B4A

Here we have my latest library - OSMDroid provides a MapView for B4A.

More info on the original (native Android) OSMDroid project can be found here: osmdroid - OpenStreetMap-Tools for Android - Google Project Hosting.

Library reference is no longer included in this post due to limits on the number of characters allowed in a single post.

I have created some tutorials to show basic usage of the library and will update this thread with a link to them as soon as i have them all uploaded.

** Your attention is drawn to the included file Apache License Version 2.0.txt, which is a copy of the Apache License Version 2.0 under which the native Android OSMDroid library is released **

Martin.
 

Attachments

  • OSMDroid_3_0_8_v3.60.zip
    361.9 KB · Views: 4,075
Last edited:

DonManfred

Expert
Licensed User
Longtime User
I think he means that he HAS an sqlite-db with waypoints and want to put a way based on this waypoints on the map...
 

merlin2049er

Well-Known Member
Licensed User
Longtime User
What I mean is there a app that I can generate a route with then export those sets of waypoints into my own sqlite table.

I'd then be able to edit the table by adding links to media within the table.
 

canalrun

Well-Known Member
Licensed User
Longtime User
Hello,
I have used OSMDroid very successfully using both online and off-line data (generated with both Mobile Atlas Creator and Maperitive) – Thank you for the library.

I wonder if there is a way to generate off-line tiles from within OSMDroid without having to use a third-party application to acquire the tiles then transfer to the device.

Something like – the user presses a button in the B4A/OSMDroid App. The App requests the tiles for the area represented on the display (for each required zoom level) then saves them to the OSMDroid directory.

Something similar to the way Google Maps allows you to collect off-line data.

Thanks,
Barry.
 

warwound

Expert
Licensed User
Longtime User
I've seen a similar request a few times in regard to the original android OSMDroid library.
People wanting to run the osmdroid tile packager on the device to build an offline tile cache.

First i'll say i never did get the osmdroid tile packager to even work on a desktop computer.
But i'm sure it uses packages that are only available on desktop java and not available in android's java implementation - so technically just will not work on an android device.

I suppose in theory you could take a GeoPoint and radius and download all tiles within the radius of the GeoPoint and save them to the external memory 'osmdroid' cache folder.
Or download those same tiles and package them as a .zip format offline tile archive - saving the archive in the same 'osmdroid' folder.

Apart from the time it'd take to write the code to download the tiles you'd probably find that most free online tile servers would treat such bulk downloading as abuse and either refuse to serve all requested tiles or limit the download rate so as not to let your device hog the tile server resources.

Did you see my MapsForgeTileProvider library for use with the GoogleMaps library?
I have a similar library for use with OSMDroid - the library renders tiles on the fly on the device from raw open street map vector data.
The raw data is typically far far smaller in size than the equivalent tiles you'd need to provide offline tiles for the same area.

You could in theory create a number of map databases - a map database is the raw open street map data - for various areas and offer your users the chance to download a map database for an area to allow them to view that area offline.
It'd take time to create a number of map databases for lots of small areas but it is i think workable.
Or you could create map databases that cover a larger area and reduce the number of databases to create - though your users would then have to download more MBs of map database before being ready to go offline.

If you wanna try the OSMDroid version of MapsForgeTileProvider then send me a PM and i'll let you have a link to the library and a working demo project.

Martin.
 

canalrun

Well-Known Member
Licensed User
Longtime User
I suppose in theory you could take a GeoPoint and radius and download all tiles within the radius of the GeoPoint and save them to the external memory 'osmdroid' cache folder.
Or download those same tiles and package them as a .zip format offline tile archive - saving the archive in the same 'osmdroid' folder.

Apart from the time it'd take to write the code to download the tiles you'd probably find that most free online tile servers would treat such bulk downloading as abuse and either refuse to serve all requested tiles or limit the download rate so as not to let your device hog the tile server resources.

Thanks for the quick reply.

Setting a geo-point and downloading all the tiles within the radius of the geo-point is, I think, what I had mind. I have had the problem of download limiting while using the third-party tile-fetch tools, but the area I'm downloading is small so it has not been bad.

I have not tried the Google tools. I have had great success using your OSMDroid library, a good portion of my users still use less than Android 3.0, so I have not really had the incentive to try Google mapping.

Is it realistically possible to accomplish what you mentioned above - set a geo-point and radius then download and store the tiles. It would be acceptable to step through the zoom levels in software to acquire the tiles for each zoom level. As you suggest, I would download the tiles, store them somewhere, put them in a zip file, and then move them to the OSMDroid folder.

The length of time this operation would take is not too much of a concern and the area would be relatively small (maybe 10 mi.²).

Looking through your HTML documentation, I did not see a way to accomplish this.

If you wanna try the OSMDroid version of MapsForgeTileProvider then send me a PM and i'll let you have a link to the library and a working demo project.
Martin.

Thanks. I will also send PM.

Barry.
 

canalrun

Well-Known Member
Licensed User
Longtime User
Setting a geo-point and downloading all the tiles within the radius of the geo-point is, I think, what I had mind.

I found a good source of information at:
http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames

Using the new B4J I made a test application that chooses the tiles within a lat/lon bounding region. I've attached my test application.

For the region I've chosen, near Syracuse New York USA, the tile Zoom/X/Y coordinates produced for the tiles are the same that are produced by the Maperitive map generation program. This gives me a little confidence, but more testing is needed.

The next step would be to use HTTPUtils library to download the tiles then store them in the correct directory structure.

Barry.
 

Attachments

  • OSM.png
    OSM.png
    7.2 KB · Views: 202
  • RegToTiles.zip
    2.1 KB · Views: 210

warwound

Expert
Licensed User
Longtime User
An idea might be to set up a server to create these offline tile packages for your users.

Your app could send a lat, long coordinate to the server.
The server would request all the tiles from a tile server and package them into a zip offline tile package and then notify your app user that the offline tile package is ready to download.

It'd be much better for the app user to download a single tile archive from your server than it would be to download each and every tile they require and create the tile archive on the device.
A server with PHP and cURL support would make easy work of creating the tile archives - as long as your server IP doesn't get banned from the tile servers.
A variable length delay inbetween tile requests from your server to the tile server would probably reduce the risk of a ban.

If you had a decent server you could even set it up as a tile server of your own.
http://lowendbox.com/blog/weloveservers-19year-1gb-openvz-in-buffalo-dallas-la-kent-uk-and-orlando/ see how only $19 a year will get you a VPS that could probably handle tile serving?
Though a lot depends on what size area you want to server tiles for - if you want to serve tiles for the entire planet you might find that VPS hasn't got enough memory to import the required OSM data.
With Ubuntu 12.04 installed on the VPS you'd find the instructions HERE are all that needs to be followed to have your very own tile server.

Martin.
 

canalrun

Well-Known Member
Licensed User
Longtime User
Hello,
Take a look at this thread:
http://www.b4x.com/android/forum/threads/b4j-getting-httputils2-error.34840/

I have written a B4J app to identify and download tiles for a region given latitude and longitude. It doesn't currently work on my computer, but Erel has said he does not see the same error.

I agree with your concern about downloading and storing too many tiles.

OpenStreetMaps defines heavy usage as 4000 tiles per second (http://developer.mapquest.com/web/products/open/map , Terms of Use, bottom of page). I doubt my app will ever be responsible for 4000 tiles per Year. I will also limit the number of tiles that can be downloaded at a time to 50 or 100.

Barry.
 

peacemaker

Expert
Licensed User
Longtime User
Is it possible to use several overlays together ?
Say - Markers, MarkersFocus and TouchEvents ?
 

warwound

Expert
Licensed User
Longtime User
You can add several overlays but will find that only the last added overlay will receive any touch events.

Martin.
 

peacemaker

Expert
Licensed User
Longtime User
Yes, i have found this and that's why i'm asking :)
Exactly about possibility to use several (most of the functinality of map function) at once.
Impossible with the single common map ?
 

warwound

Expert
Licensed User
Longtime User
Looking at the library source code i see that the TouchEventsOverlay callbacks can be updated to return a Boolean value.
So i've updated the library so B4A now must return a Boolean value from it's callbacks:

B4X:
Sub TouchEventsOverlay1_Click(GeoPoint1 As GeoPoint) As Boolean

End Sub

Sub TouchEventsOverlay1_LongClick(GeoPoint1 As GeoPoint) As Boolean

End Sub

Cab you test the attached update?
Make sure that your TouchEventsOverlay is the last overlay that you add to your map and return False from these two Click and LongClick Subs.

Does the next overlay - the overlay added to the map before the TouchEventsOverlay - now raise an event?
If so then i'll look at the other overlays and see if their events can be updated to return a Boolean value too.

Martin.

EDIT: I've just uploaded an update, this update applies these same changes to both MarkersOverlay and MarkersEventsOverlay.
So Subs that handle events raised by TouchEventsOverlay, MarkersOverlay and MarkersEventsOverlay must now return a Boolean value to indicate whether or not the Sub has handled the event.
Return False from these Subs and the event has not been handled - hopefully the touch event will then be passed to the preceding overlay object.
 
Last edited:

peacemaker

Expert
Licensed User
Longtime User
Yesss ! Seems, works, thanks ! All 3 overlays events are OK on a single map.
 

warwound

Expert
Licensed User
Longtime User
Yesss ! Seems, works, thanks ! All 3 overlays events are OK on a single map.

Great!

Now i have to decide - shall i release this as a 'proper' update or not...
It's not a backwards compatible update and will break existing code that uses these three objects.
But of course for the extra functionality that the update provides i think it's reasonable to expect library users to make minor modifications to their projects.

Martin.
 

peacemaker

Expert
Licensed User
Longtime User
So, just fork the project. Make the lib with this new feature - i'm sure very important - as v.4.0, additional to 3.0.8
 

warwound

Expert
Licensed User
Longtime User
So, just fork the project. Make the lib with this new feature - i'm sure very important - as v.4.0, additional to 3.0.8

Version 4 is reserved for a yet to be completed b4a wrapper of the very latest version of OSMDroid, take a look at the changelog:
http://code.google.com/p/osmdroid/wiki/Changelog.

The current b4a wrapper library is using a version of OSMDroid that is 3 versions old and there have been many bug fixes and improvements.
Pinch to zoom even works as expected in the new version - zooming on the point of pinch instead of the map center.
Lots of memory management improvements too apparently in the new version.

If you wanna try the official demo for version 4.0 then you can download it from here:
http://b4a.martinpearman.co.uk/osmdroid/.

I have no idea when i shall have the new b4a library complete, it's in the very early stages of development.
The new b4a library will not be backwards compatible with the existing b4a library - there will be more than a few syntax changes.
But the syntax changes will ultimately give the b4a developer much more access to the features of the wrapped OSMDroid library so i think it's worth breaking compatibility with the old version.

Martin.
 

canalrun

Well-Known Member
Licensed User
Longtime User
Hello,
Is it possible to get the BoundingBox or Northwest and Southeast Geo points of the area that is currently displayed in the MapView?

This is kind of like FitMapToBoundingBox only in reverse – GetMapBoundingBox

Thanks,
Barry.
 

warwound

Expert
Licensed User
Longtime User
Can you try the attached update?

The MapView has two new methods:

  • GetBoundingBox As BoundingBoxE6Wrapper
  • GetBoundingBox2 (ViewWidth As Int, ViewHeight As Int) As BoundingBoxE6Wrapper

I can find no documentation on these methods so assume that they return the BoundingBox of the current MapView.
So try the GetBoundingBox method first, if that causes an exception or returns the wrong result then try GetBoundingBox2 passing the MapView width and height.
If in your code you have only just created a MapView and try to get it's BoundingBox, and the MapView has not been fully rendered to the screen then GetBoundingBox may fail as it may not know the MapView size, using GetBoundingBox2 implicitly tells the MapView it's size so should work even when the MapView is still being initially rendered.
(That last paragraph is all guesswork by the way).

The attached update incorporates the as yet unpublished updates from post #233: http://www.b4x.com/android/forum/threads/osmdroid-mapview-for-b4a.16309/page-12#post-207826.

So Subs that handle events raised by TouchEventsOverlay, MarkersOverlay and MarkersEventsOverlay must now return a Boolean value to indicate whether or not the Sub has handled the event.

If you use any of those 3 objects you'll have to make slight changes to your code - return a Boolean value from the Subs that handle the object events.

Martin.
 

Attachments

  • OSMDroid_3_0_8_get_map_bounds.zip
    341.1 KB · Views: 234

canalrun

Well-Known Member
Licensed User
Longtime User
Can you try the attached update?
The MapView has two new methods:

  • GetBoundingBox As BoundingBoxE6Wrapper
  • GetBoundingBox2 (ViewWidth As Int, ViewHeight As Int) As BoundingBoxE6Wrapper

Martin.

Fantastic!

I use the GetBoundingBox version. It works perfectly.

Thanks,
Barry.
 

canalrun

Well-Known Member
Licensed User
Longtime User
Hello,
I am using your "GetBoundingBox" update of the OSMDroid library – Thanks this added function works very well.

But, I am seeing a problem with my MarkersOverlay Events. I use both Click and LongClick. When I do a LongClick, it also fires the Click event. When I do a click event, only the Click event fires – as it should. Using previous versions of the libraries (one or two before the Boolean return values were added to the callback events) I did not see this problem.

I have added Boolean return values of true (event was handled) to the overlay event callbacks, but this did not make a difference.

Any ideas?

Thanks,
Barry.
 
Top