Android Tutorial OSMDroid - MapView for B4A tutorial

You can find the OSMDroid library thread here: http://www.basic4ppc.com/forum/addi...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,101
Last edited:

Spectre

Active Member
Licensed User
Hmmm...
That's odd.

I would ask you to post your project so i can take a look but bet it's not something you want to post and also it's probably a big project too?
How can i help you debug the problem?

Can you post just the code that creates the ViewHost and ViewHostOverlay?

Martin.

Hi!!
I saw something that the labels seem to turn bad compared to the map. I set the orientation map with the magnetic sensor, it seems that overlay the label is in a different orientation or different overlay...
I confirm that depends on the orientation map ... If you orient the map with the compass labels moving ... if I disable orientation map it all works ...

Best Regards, Riccardo
 

eronquillo

Member
Licensed User
@eronquillo

I don't think you'll find a specific example that'll do as you require.

You say an MySQL database so presumably you're storing the coordinates online and not locally on the device?
Take a look at this Google search https://www.google.co.uk/search?q=mysql spatial extensions&ie=UTF-8&oe=UTF-8.
You'd make things easier to do if you use MySQL spatial extensions to store the coordinate data.
It'll take a bit more time to set up table columns using a spatial data type instead of a float or double data type but once set up you'll be able to make much more efficient queries.

Next, if each time the map is panned or zoomed you query your database for coordinates within the map bounds then you'll probably find you're making too many queries - if the user slowly pans the map bit by bit for example you don't want to query the database repeatedly.
I'm not sure what best to suggest here, ideally you want to have the database locally on the device so you don't have to wait for network requests to complete.

Have you seen the Spatialite library?
Spatialite is basically SQLite with spatial extensions.
A local (device based) spatialite database would enable you to make queries much faster and more efficiently than a remote MySQL database.

I think what i'd try to do is:
  • Fetch all coordinates from the database in a single query.
  • Create a b4a Type with properties to contain the coordinate data, use a GeoPoint type for the coordinate property.
  • Iterate through the database query result creating a List of these b4a Type objects - an object for each row in the results.
So you now have a List of objects, each object has a GeoPoint type property.
When you want to update the Markers, get the map bounds as a BoundingBox and iterate through the List of objects:
  • If the object's GeoPoint is within the BoundingBox and the object hasn't yet been added to the map as a Marker then create and add a Marker to the map.
    If a Marker has already been created for the object and added to the map then do nothing.
  • If the object's GeoPoint is not within the BoundingBox and the object has a corresponding Marker on the map then remove the Marker.
    If the object has no corresponding Marker then do nothing.

Martin.

Hi Martin, thanks for your help on this. It gives me something to move forward with. Thanks again!
 

warwound

Expert
Licensed User
@Spectre

Ah so that was the cause.
The map is a Canvas that can be rotated.
The Labels are Views added to the layout, anchored to a GeoPoint on the Canvas BUT the anchor point does not take into account map rotation.

There is a possibility that these Views (ViewHost objects) could be converted to a Bitmap and then drawn onto the map Canvas instead of being added to the layout as Views.
I looked at this while developing the ViewHostOverlay - hoping to make it an option to draw a View on the Canvas OR add it to the layout.
Time is the limiting factor here and i just didn't have time to create such an option.

I'm likely to be busy for a couple for weeks here getting some work done but will think again about this option when i next update OSMDroid.

Martin.
 

Spectre

Active Member
Licensed User
@Spectre

Ah so that was the cause.
The map is a Canvas that can be rotated.
The Labels are Views added to the layout, anchored to a GeoPoint on the Canvas BUT the anchor point does not take into account map rotation.

There is a possibility that these Views (ViewHost objects) could be converted to a Bitmap and then drawn onto the map Canvas instead of being added to the layout as Views.
I looked at this while developing the ViewHostOverlay - hoping to make it an option to draw a View on the Canvas OR add it to the layout.
Time is the limiting factor here and i just didn't have time to create such an option.

I'm likely to be busy for a couple for weeks here getting some work done but will think again about this option when i next update OSMDroid.

Martin.

Hi Martin...
Important thing is to have found the problem, for now I will visualize the label on the map, my project can be expected in the meantime I will go on with other parties. It seems like a good option to convert to a bitmap and then add to a single overlay.
I also thought I had to work around the problem of generating an icon with the name of the point and then use it on the map ...

Riccardo.
 

fabio.guerrazzi

Member
Licensed User
I didn't figured out wich one should I follow for my app, Google Maps v2 Tutorial or OSMDroid MapView. I just installed the first one, created signature, got api key.. now I realized this. What is the best way in your opinion? thank you
 

Spectre

Active Member
Licensed User
I didn't figured out wich one should I follow for my app, Google Maps v2 Tutorial or OSMDroid MapView. I just installed the first one, created signature, got api key.. now I realized this. What is the best way in your opinion? thank you

osmodroid in my opinion is the most complete and versatile ... You can use off-line maps and the new version 4.1 beta is very good though.
 

warwound

Expert
Licensed User
In my opinion the GoogleMaps library is far more 'professional' and is also regularly updated with new features.
GoogleMaps does though mean that your app will only be compatible with devices running a version of android Honeycomb and later - it doesn't support the older 2.? versions of android.
GoogleMaps is also limited from a developers point of view as it lacks any way to enhance it with your own objects and classes.

OSMDroid is 'functional' and feature rich and allows developers to enhance it's functionality with their own objects and classes.
Just a couple of weeks ago i created the new CircleOverlay for Spectre to use in the new version 4.1 of OSMDroid.
OSMDroid is compatible with just about every version of android so no problems with older devices.
OSMDroid is updated 'regularly' but not as often as GoogleMaps is updated.

Each has it's good points and weak points.

Martin.
 

Spectre

Active Member
Licensed User
[Quote = "warwound, palo: 247.086, membro: 11161"] A mio parere la biblioteca GoogleMaps è molto più 'professionale' e viene regolarmente aggiornato con nuove funzionalità.
GoogleMaps non significa però che la vostra applicazione sarà compatibile solo con i dispositivi che esegue una versione di Android Honeycomb e poi - non supporta la vecchia 2.? versioni di Android.
GoogleMaps è limitata anche da un punto di vista gli sviluppatori in quanto manca qualsiasi modo per migliorare con i propri oggetti e classi.

OSMDroid è 'funzionale' e ricco di funzionalità e consente agli sviluppatori di migliorare la sua funzionalità con i propri oggetti e classi.
Solo un paio di settimane fa ho creato il nuovo CircleOverlay per Spectre da utilizzare nella nuova versione 4.1 di OSMDroid.
OSMDroid è compatibile con quasi tutte le versioni di Android quindi niente problemi con i dispositivi più vecchi.
OSMDroid è aggiornato 'regolarmente', ma non così spesso come GoogleMaps viene aggiornato.

Ognuno ha la sua buona punti e punti deboli.

Martin. [/ Quote]
;)
 

warwound

Expert
Licensed User
Hi! Martin ... Some news for the bug rotation label on the map?
Spectre...

lol it'll be a while before i have time to look at that - gotta get some other work done first.
Updating the ViewHost so that Views are drawn onto the map Canvas instead of being displayed as 'standard' Views isn't an easy bit of code to write, so i'll look at it when i know i have enough time to get it working.

Martin.
 

Spectre

Active Member
Licensed User
lol it'll be a while before i have time to look at that - gotta get some other work done first.
Updating the ViewHost so that Views are drawn onto the map Canvas instead of being displayed as 'standard' Views isn't an easy bit of code to write, so i'll look at it when i know i have enough time to get it working.

Martin.
Tanks...;)
 

jamesnz

Active Member
Licensed User
what an awesome library, the only issue I have is with screen rotation I get out of memory errors, usually after 2 'rotations' , not sure why but otherwise it's really great, well done
 

Mbm

Member
Licensed User
Is there any way to use OSMDroid library together with googlemaps api in the same proyect? Both libraries have a class called Marker and the IDE doesn´t allow the same short name for classes...
 

warwound

Expert
Licensed User

Sam H

Member
Licensed User
I was trying to use the example in post #375, however I get the following error message during compilation:
"A referenced library is missing: slf4j-android-1.6.1-rc1". I have the following librarys referenced:
OSMDroid_3_0_8
OSMDroid_4_1
OSMDroid_4_1_MapsForgeTileSource.

What am I missing?, thanks in advance.
 

warwound

Expert
Licensed User
I was trying to use the example in post #375, however I get the following error message during compilation:
"A referenced library is missing: slf4j-android-1.6.1-rc1". I have the following librarys referenced:
OSMDroid_3_0_8
OSMDroid_4_1
OSMDroid_4_1_MapsForgeTileSource.

What am I missing?, thanks in advance.

That example uses OSMDroid version 4.1 - you don't need version 3.0.8 to run it and you don't need MapsForgeTileSource either.
The latest version 4.1 library files can be downloaded from here: http://b4a.martinpearman.co.uk/osmdroid/OSMDroid_library_files_v4.1_20140428.zip (not sure if you have the latest version 4.1 or not).

Can you make sure you have OSMDroid version 4.1 library checked in the b4a ide and no other libraries checked?

Martin.
 

Sam H

Member
Licensed User
Thanks, I have found the slf4j-android-1.6.1-rc1 library reference in the files from the download link and added it to the librarys folder. That seems to have done it.

Thanks again

sam
 

Sam H

Member
Licensed User
A few slight problems since upgrading the library from OSMDroid 3_0_8 to OSMDroid 4_1. I can no-longer trigger the following sub by clicking on any of the markers:
Sub MarkersOverlay1_Click(Title As String, Description As String, Point As OSMDroid_GeoPoint)
coding
End Sub

Any ideas?

Also the mylocationOverlay didn't work.

Are there any tutorials/examples for OSMDroid 4_1, like there were for 3_1 on the first page of this tutorial as they were really useful?

Thanks

Sam
 
Top