Android Tutorial OSMDroid - MapView for B4A tutorial

You can find the OSMDroid library thread here: http://www.b4x.com/forum/additional...tes/16309-osmdroid-mapview-b4a.html#post92643.

AIM: Create and initialize a MapView, enable the map zoom controller and multitouch controller, set a zoom level then center the map on a location.

B4X:
Sub Process_Globals
End Sub

Sub Globals
   Dim MapView1 As MapView
End Sub

Sub Activity_Create(FirstTime As Boolean)
   If File.ExternalWritable=False Then
      '   OSMDroid requires the use of external storage to cache tiles
      '   if no external storage is available then the MapView will display no tiles
      Log("WARNING NO EXTERNAL STORAGE AVAILABLE")
   End If
   
   '   no EventName is required as we don't need to listen for MapView events
   MapView1.Initialize("")
   Activity.AddView(MapView1, 0, 0, 100%x, 100%y)
   
   '   by default the map will zoom in on a double tap and also be draggable - no other user interface features are enabled
   
   '   enable the built in zoom controller - the map can now be zoomed in and out
   MapView1.SetZoomEnabled(True)
   
   '   enable the built in multi touch controller - the map can now be 'pinch zoomed'
   MapView1.SetMultiTouchEnabled(True)
   
   '   set the zoom level BEFORE the center (otherwise unpredictable map center may be set)
   MapView1.Zoom=14
   MapView1.SetCenter(52.75192, 0.40505)
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

The code is pretty self-explanatory.

I've added the code to check if the device has available external storage as OSMDroid will not display any tiles if no external storage is available.
External storage is used to save/cache all downloaded tiles - no external storage means no map!
(I'll omit that check from future tutorials but it's something to bear in mind - not that i know of any Android devices that have no external storage).

Create and initialize a MapView, add it to the Activity 100% width and 100% height.
Enable the zoom and multi-touch controller.
Zoom in to level 14 then set the MapView center to a location (sunny Norfolk, UK!).

I've found that setting the map center and then immediately setting the zoom level does not work as expected.
I think that while the MapView is setting the map center it also zooms in so the end result is unpredictable.

Pan and zoom the map, now rotate your device and you'll see the map returns to it's initial state of zoom level 14, center (52.75192, 0.40505).

I shall show you how to save and restore the MapView state next...

Martin.
 

Attachments

  • 01 - SimpleMap.zip
    5.8 KB · Views: 4,645
Last edited:

synapse

Member
Licensed User
Longtime User
You're a star! I'd hoped you'd discovered the Grail. By the way is there any progress on vector maps?
Best regards
 

warwound

Expert
Licensed User
Longtime User
Vector maps in a GoogleMap - yes look here: http://www.b4x.com/android/forum/threads/googlemapsextras.26277/page-4#post-199801

Vector maps in OSMDroid - it can be done, i have a library that will do exactly as the above MapsForgeTileProvider but in OSMDroid.
It works but isn't great, rendering is a slow single threaded process and tiles aren't cached - performance and useability suffer.
PM me if you want to try vector maps in OSMDroid.

Martin.
 

GaNdAlF89

Active Member
Licensed User
Longtime User
Hi, I have a problem with map: now I see an image of "OPNKARTE" with message "The map is designed for online use." Can you help me?
 

warwound

Expert
Licensed User
Longtime User
Hi, I have a problem with map: now I see an image of "OPNKARTE" with message "The map is designed for online use." Can you help me?

What value are you passing to the MapView SetTileSource method?
OSMDroid contains various built in tile sources but not all are free to use - some require a licence and/or API key from the tile source provider.
I'd guess you've selected a tile source that is not free to use and without a licence/API key the tiles do not get downloaded.

Martin.
 

GaNdAlF89

Active Member
Licensed User
Longtime User
Thanks Martin!! The problem was exactly what you said!!
I used "OSMPublicTransport" and previously I remember that it worked...Why now it doesn't work?
 
Last edited:

warwound

Expert
Licensed User
Longtime User
I just tried my demo app from this post: http://www.b4x.com/android/forum/threads/osmdroid-mapview-for-b4a-tutorial.16310/#post-92646.
And as you have reported the OSMPublicTransport tile source is no longer available in OSMDroid - i see the same 'The map is designed for online use' tiles.

Generally this means that the tile server has blocked access to tiles from requests that it considers 'not authorised'.
When OSMDroid included OSMPublicTransport tiles it worked, at some point OSMPublicTransport have decided to restrict access to tiles and OSMDroid is just one user of the tiles that have been blocked.
Most of these free online tile servers operate on a limited budget and can't afford to allow access from anyone and everyone.

So your only solution is to find another free tile provider - not easy these days as more and more tile providers are blocking/restricting access from 3rd parties.
Try http://cloudmade.com/products/map-tiles, currently they allow up to 500,000 tiles per month to be downloaded for free - after that you have to pay.
Depending on the number of users of your app you might find that to be enough.
Cloudmade have a selection of different styled map tiles - though i'm not sure if they have something that resembles the OSMPublicTransport tiles.
Some info on using Cludmade tiles in OSMDroid can be found here: http://www.b4x.com/android/forum/threads/osmdroid-mapview-for-b4a-tutorial.16310/#post-92864.

Martin.
 

Beja

Expert
Licensed User
Longtime User
currently they allow up to 500,000 tiles per month to be downloaded for free - after that you have to pay.

Hi Martin,
Thanks for the info... Question: is the 500.000 per user (per device)? If not then how
do they distinguish between different apps written by different people?
e.g. if my app users sent 200,000 requests, and another B4A app users written by someone else
sent 300,001 requests, yet another one sent a few requests.. All 3 apps used the B4A example. then
how do they know and which one they block?
 

warwound

Expert
Licensed User
Longtime User
You sign up for a Cloudmade developer API key and use that API key in your aplication - see link in my previous post for how to add the API key to an OSMDroid project.

Now your project can request up to 500,000 tiles per day from Cloudmade tile servers - the API key identifies your app from other apps.
Remember that OSMDroid will cache all downloaded tiles and that can save an awful lot of requests/bandwidth.

Martin.
 

Dario126

Member
Licensed User
Longtime User
I use markers at MarkersBalloonOverlay and .FocusedMarker method to make title/description visible. But, title/description box is hiding top part of my marker. Can this box be positioned higher for some 10 or 20 pix? How?

I tried to change some values in balloon_overlay.xml, but nothing works then ..
 
Last edited:

warwound

Expert
Licensed User
Longtime User
I seem to remember this being a problem when using the built in default OSMDroid Marker, but with custom Marker icons there was no problem.
The problem relates to the device scaling the icon based on screen density.

Are you using your own icon or the built in OSMDroid Marker/icon?

Can you post a screenshot?

Martin.
 

Dario126

Member
Licensed User
Longtime User
Can you post a screenshot?
Martin.

Here it is, tried now with default 27x48pix icon (left image) and custom 32x48 pix icon (right image, note that custom image is doubled when put on screen):

default marker 27x48 pix.png
custom icon 32x48 pix.png
 
Last edited:

warwound

Expert
Licensed User
Longtime User
You have two options:
Martin.
 

warwound

Expert
Licensed User
Longtime User
Here it is, tried now with default 27x48pix icon (left image) and custom 32x48 pix icon (right image, note that custom image is doubled when put on screen):

View attachment 21600 View attachment 21601

What device is this on?
What is the device screen density?
Can you try the same code on other devices - a device with say a medium screen density - and see if the balloon position is still incorrect?

Martin.
 

Dario126

Member
Licensed User
Longtime User
What device is this on?
What is the device screen density?
Can you try the same code on other devices - a device with say a medium screen density - and see if the balloon position is still incorrect?

Screenshoot is from Huawei P6 (4.7in, 720x1280, pixel density of 312ppi) and custom icon is doubled in size. Also BaloonMarker's on icons (either of them (custom or default) are not on top of icons, but start somewhere in middle (as visible in screenshoots).

I tried same app on Asus Eee Pad Transformer tablet (10.1in, 1280x800, pixel density of 150ppi). Here is all ok, custom icon is normal size, and baloonmarker correctly above marker icon.

It look's like screen density issue?


Btw. is property MarkersBalloonOverlay.mFocusItemOnTap available for set by code? I see this in debug mode, but is not available in b4a. I have markers on MarkersBalloonOverlay, but when clicked, baloon is not shown up. However I can "pop it up" by setting MarkersBalloonOverlay.FocusedMarker, but is not practical ..

This is how I put marker's but' baloon's thus not not show up when clicked:
B4X:
Dim tmpMarker As Marker
tmpMarker.Initialize("HS1", "desc1" , latitude, longitude, Null)
HSMarkers.Clear
HSMarkers.Add(tmpMarker)

MarkersBalloonOverlay1.RemoveMarkers
MarkersBalloonOverlay1.AddMarkers(HSMarkers)
MapView1.Invalidate
 

Dario126

Member
Licensed User
Longtime User
Do You have any idea how can get around screen density issue?
Is this also causing labels of the street to be very small (even on max zoom)?

And, also this other question about markers which don't pup-up on click. What am I doing wrong? As temp solution I have put MarkersEventsOverlay which listen for clicked marker's and make them focused. But this is one more overlay and i'm afraid that is to complicated for process. Balloon markers demo from this thread works fine on my device, I tried to reproduce this, but it's not working. Maybe I have too many overlays?
B4X:
Sub Globals
    Dim MapView1 As MapView
    Dim MyLocationOverlay1 As MyLocationOverlay
    Dim TouchEventsOverlay1 As TouchEventsOverlay
    Dim MarkersEventsOverlay1 As MarkersEventsOverlay
    Dim MarkersBalloonOverlay1 As MarkersBalloonOverlay
    Dim MarkersBalloonOverlay3 As MarkersBalloonOverlay
End Sub
Sub Activity_Create(FirstTime As Boolean)
    MapView1.Initialize("")
    pnlMap.AddView(MapView1, 0, 0, pnlMap.Width, pnlMap.Height)
    MapView1.SetMultiTouchEnabled(True)
    MapView1.SetZoomEnabled(False)
    MapView1.SetCenter3(MapCenter)
    MapView1.Zoom=DefZoomLevel

    'add MyLocationOverlay
    MyLocationOverlay1.Initialize(MapView1, "MyLocationOverlay1")
    MapView1.AddOverlay(MyLocationOverlay1)
    MyLocationOverlay1.MyLocationEnabled=True

    'add MarkersBalloonOverlay            
    MarkersBalloonOverlay1.Initialize(MapView1, "", "balloon_overlay")
    MapView1.AddOverlay(MarkersBalloonOverlay1)        

    'add MarkersBalloonOverlay            
    MarkersBalloonOverlay3.Initialize(MapView1, "", "balloon_overlay")
    MapView1.AddOverlay(MarkersBalloonOverlay3)        

    'touch overlay
    TouchEventsOverlay1.Initialize("TouchEventsOverlay1")
    MapView1.AddOverlay(TouchEventsOverlay1)

    'add MarkersEventsOverlay
    MarkersEventsOverlay1.Initialize(MapView1, "MarkersEventsOverlay1")
    MapView1.AddOverlay(MarkersEventsOverlay1)
End Sub
'PUT NEW MARKERS ON MAP
Sub DrawHotSpotMarkers 'this procedure is called when click on some button
    MarkersBalloonOverlay1.RemoveMarkers
    MarkersBalloonOverlay1.AddMarkers(Service1.HotSpotMarkers)
    MapView1.Invalidate
End Sub
Sub TouchEventsOverlay1_Click(GeoPoint1 As GeoPoint)
    NextMapRecenterTime=DateTime.Now+MapRecenterInterval*1000
    MarkersBalloonOverlay3.UnsetFocusedMarker
    MarkersBalloonOverlay1.UnsetFocusedMarker
End Sub
Sub MarkersEventsOverlay1_Click(ClickedMarker As Marker)
    Log("MarkersEventsOverlay1_Click on: "  & ClickedMarker.Title)
    MarkersBalloonOverlay3.FocusedMarker=ClickedMarker
    MapView1.Invalidate
End Sub

SERVICE1 module:
Sub CreateMarkers
Marker1.Initialize4(ID, Title, Desc, Lat, Lon, Null)
    HotSpotMarkers.Add(Marker1)
End Sub
 
Last edited:

warwound

Expert
Licensed User
Longtime User
I'll take a look at the screen density issue a bit later hopefully.
Reinstalling Windows 8 on my laptop today so no programming til that's done.

Meanwhile have a read through this other thread from post #230 onwards.

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

So there's a modified version of the b4a library that addresses this issue - your overlay event handling subs have to return a boolean value to tell the library whether to pass the event on to the next underlying overlay or not.

That modified version is currently attached to post #239 as OSMDroid_3_0_8_get_map_bounds.zip.

Try the modified library - be sure to update your code so that all subs that handle overlay events return a boolean value.
Hopefully that'll be the balloon problem fixed for you.

Martin.
 
Top