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,794
Last edited:

BarrySumpter

Active Member
Licensed User
Longtime User
You need to use the command line and the adb tool.

Have a look on Google for various techniques - not all are guaranteed to work so you'll have to experiment until you find one that does: https://www.google.co.uk/search?q=android+emulator+adb+push+to+sd+card&ie=UTF-8&oe=UTF-8.

Watch that if your OSMDroid uses the MyLocationOverlay it will possibly crash on the emulator when the app tries to enables sensors.

I gave up using the emulator when testing MyLocationOverlay apps but i see a possible workaround.

Open AVD Manager and select your virtual device.
Click Edit.
Now under the Hardware section you can click New and a dialog opens.
In the dialog is a Property drop down list where you can set or enable various hardware settings in the virtual device.

If you add GPS support and/or Magnetic field support then the virtual device might be configured with software emulation for the sensors and no longer crash.
This is on my list of things to do so may or may not work.

Note that i have found that if you change any settings in the Hardware dialog then the next time you start the virtual device all installed apps will be gone - it looks like changing a Hardware setting causes a device reset.

Have a look through the other available options - you can set device RAM size and density and some other values too which might be useful.

Martin.

I'm trying to get me head around using virtualBox>
Its so much faster.

The emulator wasn't getting far enough before crash cause it couldn't find my map cache on the SDCard.

Thanks for the heads up.
Gives me a good reason to stop chasing the enulator and just test on physical device.

With VirtualBox its all a hack and has to be done via the command line.
But at least I can save a snapshot.
Shapshots take about 2 seconds to load and your off.

I'll have to look into GPS and magnetic field support for VirtuaBox.

Thanks heaps yet again for all the support and verbose replies.
 

BarrySumpter

Active Member
Licensed User
Longtime User
I've just uploaded a new library ImageButtonsView.

You (Barry that is or anyone) might find it useful to create map controls.

Here's a screenshot of how i've used it in an app i'm developing:



Got a map type button, center the map button and a button to show a list of places currently on the map.

Along with the AHQuickAction3D library it adds a bit more function to the map.

Martin.

Jeez! Did you hear me scream?

So glad I switched to b4a full time.
I'm thinking the "clone Martin" idea was pretty good.

Martin, your work makes b4a apps look sooooo professional.

Now I can really enjoy thinking of apps to use these controls on.

:sign0188:
 

BarrySumpter

Active Member
Licensed User
Longtime User
OK, I've sorted out the transparent panel over the compass.
Very nice.

Was also successful in setup of ftp server and getting 550 mg maps to VirtualBox emulator.

I've left the 10 second timer in.
Although I want to reset the timer each time the map is moved but the MyLocationOverlay1_FollowLocationAutoDisabled event doen't fire each time.
I don't know why.

I had a flash this morning about setting a global flag of some sort to tell me that the map is still being manually panned around.
Then once the map has stopped being manipulated to start the 10 seconds timer then.
But got distracted with mothers day breakie n lost me focus.

I've left the zoom 18 to stretch at zoom 19 displaying the grid if my location changes off the current map. I'll return later to see what I can do with it.
Maybe just click the compass to reset zoom to 18.

---

For now, I'm looking at Map 13 - Get(GPS)Location.
I'd like to implement this in my app to where I want to select a location
for my bike buddies to meet for a kickoff and where to meet at lunch or for a coffee etc.

Is there a way to change the Manual Man icon to a cross hair icon?

I'll have a look at changing that GPS Lat n Lng into GeoLocation.



tia
 
Last edited:

warwound

Expert
Licensed User
Longtime User
For now, I'm looking at Map 13 - Get(GPS)Location.
I'd like to implement this in my app to where I want to select a location
for my bike buddies to meet for a kickoff and where to meet at lunch or for a coffee etc.

Is there a way to change the Manual Man icon to a cross hair icon?

Look in the folder res/drawable-nodpi - the folder that's part of the library download.

These are the default drawables that OSMDroid uses: direction_arrow.png and person.png.

You should find that replacing those drawables will do the job.
If you replace them with a drawable of a different size then you might find the drawable is not positioned correctly.

I think the drawable dimensions are NOT hardcoded into OSMDroid core so any size drawable should be ok but there is a chance that the replacement drawables must be the same size.

Martin.
 

BarrySumpter

Active Member
Licensed User
Longtime User
Thanks for that martin.
I'll have a look at that next.

FollowMe6a.zip
Used a single overlay to switch between followMyLocation and ManualSelectLocation.

Used a transparent panle to display a crosshair.

Added GeoLocation as well.
 

Attachments

  • Map 17 - OverlayMap - FollowMe6a.zip
    46.4 KB · Views: 746

PeakW

Member
Licensed User
Longtime User
How to mapview specified in the longitude and latitude location display information?

How to mapview specified in the longitude and latitude location display information?:sign0085:
 

PeakW

Member
Licensed User
Longtime User
I want to directly in the designated location, show the information such as place names, and don't click events to show, have a way? Like BalloonMarker no?:sign0085:
 

warwound

Expert
Licensed User
Longtime User
I want to directly in the designated location, show the information such as place names, and don't click events to show, have a way? Like BalloonMarker no?:sign0085:

The only way you can do that is to create images to use as labels/custom Marker icons and add them to a MarkersOverlay.

You'd not need be wanting to listen for tap or long tap events on the labels i think but you'll find that's currently the only way to add labels to the map.

Martin.
 

warwound

Expert
Licensed User
Longtime User
Just found this google maps markers library

Markers Google Maps icons | Map Icons Collection

Can we build a mobile interface to allow us to select our own markers?

Do you mean an interface that's part of your application so that users can choose what icons your MapView uses?

Would the interface offer a limited selection of icons that you have already downloaded and packed with your app's resources OR would it offer all the options available on that web page and the interface would download icons as chosen in the interface?

Easiest way i think for an interface that offers all icons in whatever colors and downloads them would be to use a WebView and write a mobile version of the page at Markers Google Maps icons | Map Icons Collection.
Shame that web site doesn't have an API that you could use to query for available icons and then request icons.

Martin.
 

PeakW

Member
Licensed User
Longtime User
I'm B4A novice, want to consult: whether can directly Lable on designated longitude and latitude location? Can you give some examples?
 

BarrySumpter

Active Member
Licensed User
Longtime User
Do you mean an interface that's part of your application so that users can choose what icons your MapView uses?

Would the interface offer a limited selection of icons that you have already downloaded and packed with your app's resources OR would it offer all the options available on that web page and the interface would download icons as chosen in the interface?

Easiest way i think for an interface that offers all icons in whatever colors and downloads them would be to use a WebView and write a mobile version of the page at Markers Google Maps icons | Map Icons Collection.
Shame that web site doesn't have an API that you could use to query for available icons and then request icons.

Martin.


Looks like thre is a zip download. 5.5 meg for all zips and 27 meg expanded.
So we can included in our own install or host on our own server or on dropbox.
I wonder what the rules for dropbox are.

And I wonder if we already have a routine for extracting .png files from .zip files here on b4a forums.
Kinda like extracting the map tiles.



Markers map markers

Note : Hotlinking is not allowed on this site. Please download and host the icons on your own server or Dropbox.
 

Attachments

  • Downloaded Map Marker to be Hosted on your own server.png
    Downloaded Map Marker to be Hosted on your own server.png
    41.8 KB · Views: 503
Last edited:

warwound

Expert
Licensed User
Longtime User
I'm B4A novice, want to consult: whether can directly Lable on designated longitude and latitude location? Can you give some examples?

Look at the attached project:

B4X:
Sub Process_Globals
   Dim MapCenter As GeoPoint
   Dim ZoomLevel As Int
End Sub

Sub Globals
   Dim MapView1 As MapView
   
   '   create the LabelsOverlay
   Dim LabelsOverlay As MarkersOverlay
End Sub

Sub Activity_Create(FirstTime As Boolean)
   '   update the MenuItems
   Activity.AddMenuItem("Fit map to labels", "MenuItemSelect")
   
   MapView1.Initialize("MapView1")
   Activity.AddView(MapView1, 0, 0, 100%x, 100%y)
   
   MapView1.SetMultiTouchEnabled(True)
   MapView1.SetZoomEnabled(True)
   
   '   initialize the LabelsOverlay and add it to the MapView
   '   no EventName is required as we will not listen for the it's events
   LabelsOverlay.Initialize(MapView1, "")
   MapView1.AddOverlay(LabelsOverlay)
   
   '   create and initialize 2 labels (Markers with custom icons)
   
   Dim Icon As BitmapDrawable
   Icon.Initialize(LoadBitmap(File.DirAssets, "label1.png"))
   
   Dim Label1 As Marker
   Label1.Initialize("", "", 52.75610, 0.39748, Icon)
   
   Dim Icon2 As BitmapDrawable
   Icon2.Initialize(LoadBitmap(File.DirAssets, "label2.png"))
   Dim Label2 As Marker
   Label2.Initialize("", " Market", 52.93819, 0.48414, Icon2)
   
   '   create a List and initialize it with the 2 Markers
   Dim Labels As List
   Labels.Initialize2(Array As Object(Label1, Label2))
   
   '   add the List of Labels to the LabelsOverlay
   LabelsOverlay.AddMarkers(Labels)
   
   If FirstTime Then
      '   fit the MapView to the LabelsOverlay
      MapView1.FitMapToBoundingBox(LabelsOverlay.GetBoundingBox)
   Else
      '   restore saved zoom level and map center
      MapView1.Zoom=ZoomLevel
      MapView1.SetCenter3(MapCenter)
   End If
   
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
   MapCenter=MapView1.GetCenter
   ZoomLevel=MapView1.Zoom
End Sub

Sub MapView1_ZoomChanged
   Log(MapView1.Zoom)
   If MapView1.Zoom<9 Then
      MapView1.RemoveOverlay(LabelsOverlay)
   Else
      MapView1.AddOverlay(LabelsOverlay)
   End If
End Sub

Sub MenuItemSelect_Click
   Dim MenuItem As String
   MenuItem=Sender
   Select MenuItem
      Case "Fit map to markers"
         '   fit the MapView to the LabelsOverlay
         MapView1.FitMapToBoundingBox(LabelsOverlay.GetBoundingBox)
   End Select
End Sub

I'm just adding two Marker objects to the MarkersOverlay and adding the MarkersOverlay to the MapView.

The custom icons are in effect the labels you want to display.

The MapView ZoomChanged event listener removes the labels when the map zooms out past zoom level 9.

Martin.
 

Attachments

  • MapLabels.zip
    10.7 KB · Views: 692
Last edited:

BarrySumpter

Active Member
Licensed User
Longtime User
MapLabels.zip
Very smart.

Is there a way we can create our labels as in the
BalloonMarkersDemo.b4a
Using Marker4 BalloonMarker Label of title, description, and font

And then creating a graphic of that label
out of Marker4 BalloonMarker Label
and using that graphic instead of an icon from a physical file?

B4X:
...
    Dim Marker4 As BalloonMarker
...
     Marker4.Initialize("Sunny Hunstanton", "The seaside resort of Hunstanton is very popular with the tourists.",  52.9379, 0.4833, Null)
...
Marker4.LayoutName="custom_balloon_overlay"
...
    Markers.Initialize2(Array As Object(Marker0, Marker1, Marker2, Marker3, Marker4))
 
Last edited:

warwound

Expert
Licensed User
Longtime User
In theory yes but not with the current library code.

The map itself is a canvas object and marker icons are drawn to this canvas.
It would be much the same to draw a label instead of an icon.

Look at the MarkersFocusOverlay, the code that draws it's balloon could probably be re-used to dynamically create labels instead of having to manually create drawables for each label.

I shan't have time to look at this now though - gotta get busy with various other things this week.

Martin.
 

Attachments

  • screengrab.jpg
    screengrab.jpg
    71.2 KB · Views: 588

BarrySumpter

Active Member
Licensed User
Longtime User
No Prob Martin.
It was just a flash of an idea at the time.
---

At the moment I'm concerned with the views on the mapping levels.

Doesn't matter which map provider I use
the street names seem so small all the time.

But when I look at the miniMap the words seem so large.

I'd like to be able to magnify or perhaps stretch the image so i can see better.

Maybe have the miniMap able to drag around the map to magnify?

Gotta be some way to calculate the same maps at magnify by say 70% and still tile when needed.

update:
For some reason the miniMap zoomDifference can't be a negative number.
 
Last edited:

dunski

Member
Licensed User
Longtime User
Current Lcation

Hi warwound!

I'm new to b4a and have been playing around with your lib the last few days and have to say that its been a lot of fun. Fair play to you!

I was just wondering one thing, maybe I missed it in one of your sample projects but how do you get the current latitude and longitude positions of a phone.

So If I have an app and when I turn it on it brings up a map of where I am right now no matter where I am.

Thanks again for sharing this great code and excellent samples...
Best regards,

Donagh:sign0087::sign0098:
 

warwound

Expert
Licensed User
Longtime User
You can use the OSMDroid MyLocationOverlay and it's various GPS features to do that.

There's an example here: http://www.b4x.com/forum/basic4andr...-osmdroid-mapview-b4a-tutorial.html#post92653.

And another example here http://www.b4x.com/forum/basic4andr...smdroid-mapview-b4a-tutorial-4.html#post93131.

Alternatively you can use the B4A GPS library and use that to set the MapView center.

Or there's various other GPS related 3rd party libraries available as an alternative to the B4A GPS library.

Martin.
 
Top