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

cas6678

Active Member
Licensed User
Yes, thanks.

B4X:
#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: True
    #ApplicationLabel: MapsForgeOsmDroid38 (mapa)
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

Sub Process_Globals
    Dim SavedMapStateFileName As String="map_state.dat"
    Dim CompassEnabled, FollowLocationEnabled, MyLocationEnabled As Boolean
    Dim Timer1 As Timer
End Sub

Sub Globals
    Dim MapView1 As MapView
    Dim ScaleBarOverlay1 As ScaleBarOverlay
    Dim MyLocationOverlay1 As MyLocationOverlay
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Timer1.Initialize("Timer1", 5000) ' 5000 = 5 seconds
    Dim MapCenter As GeoPoint
    Dim MapsForgeTileSourceName As String="MapsForge1"
    Dim MapsForgeDatabaseName As String="spain.map"
    Dim MapsForgeDatabasePath As String=File.DirRootExternal
    Dim ZoomLevel As Int
    If File.Exists(MapsForgeDatabasePath, MapsForgeDatabaseName)=False Then
        File.Copy(File.DirAssets, MapsForgeDatabaseName, MapsForgeDatabasePath, MapsForgeDatabaseName)
    End If
    MapView1.Initialize("")
    Dim CurrentTilesSources As List=MapView1.GetTileSources
    If CurrentTilesSources.IndexOf(MapsForgeTileSourceName)=-1 Then
        '    the MapsForgeTileSource has not been added to the MapView so create it and add it to the map
        Dim MapsForgeTileSource1 As MapsForgeTileSource
        '    set the required MapsForgeTileSourceOptions MapDatabaseFile and TileSourceName
        MapsForgeTileSource1.GetMapsForgeTileSourceOptions.SetMapDatabaseFile(MapsForgeDatabasePath, MapsForgeDatabaseName)
        MapsForgeTileSource1.GetMapsForgeTileSourceOptions.SetTileSourceName(MapsForgeTileSourceName)
        '    example of setting an optional MapsForgeTileSourceOptions
        '    MapsForgeTileSource1.GetMapsForgeTileSourceOptions.SetTextScale(2.0)
        '    now that the required MapsForgeTileSourceOptionshave been set we can call the MapsForgeTileSource Initialize method
        MapsForgeTileSource1.Initialize
        MapView1.AddTileSource(MapsForgeTileSource1)
    End If
    MapView1.SetMultiTouchEnabled(True)
    MapView1.SetTileSource(MapsForgeTileSourceName)
    MapView1.SetZoomEnabled(True)
    If File.Exists(File.DirInternal, SavedMapStateFileName) Then
        '    restore the saved map state
        Dim RandomAccessFile1 As RandomAccessFile
        RandomAccessFile1.Initialize(File.DirInternal, SavedMapStateFileName, True)
        MapCenter=RandomAccessFile1.ReadObject(0)
        ZoomLevel=RandomAccessFile1.ReadInt(RandomAccessFile1.CurrentPosition)
        RandomAccessFile1.Close
        MapView1.Zoom=ZoomLevel
        MapView1.SetCenter3(MapCenter)
    Else
        MapCenter=MapsForgeTileSource1.MapDatabase.MapFileInfo.StartPosition
        ZoomLevel=MapsForgeTileSource1.MapDatabase.MapFileInfo.StartZoomLevel
        If MapCenter.IsInitialized And ZoomLevel<>-1 Then
            '    the map database has a start position and a start zoom set
            '    we'll use that for the default map state
            MapView1.Zoom=ZoomLevel
            MapView1.SetCenter3(MapCenter)
        Else
            '    the default map state will be defined by the area covered by the map database
            MapView1.FitMapToBoundingBox(MapsForgeTileSource1.MapDatabase.MapFileInfo.BoundingBox)
        End If
    End If
    Activity.AddView(MapView1, 10%x, 10%y, 80%x, 80%y)
   
    Activity.AddMenuItem("Clear saved state", "Menu")
    '    initialize and add the MyLocationOverlay to the MapView, an EventName is used as we'll be listening for all three events that this overlay generates
    MyLocationOverlay1.Initialize(MapView1, "MyLocationOverlay1")
    MapView1.AddOverlay(MyLocationOverlay1)
    If FirstTime Then
        '    set the default values for the new variables
        MyLocationOverlay1.CompassEnabled=True
        MyLocationOverlay1.MyLocationEnabled=True
        MyLocationOverlay1.FollowLocationEnabled=True
        CompassEnabled=MyLocationOverlay1.CompassEnabled
        FollowLocationEnabled=MyLocationOverlay1.FollowLocationEnabled
        MyLocationEnabled=MyLocationOverlay1.MyLocationEnabled
    Else
        '    restore the MyLocationOverlay state
        MyLocationOverlay1.CompassEnabled=CompassEnabled
        MyLocationOverlay1.FollowLocationEnabled=FollowLocationEnabled
        MyLocationOverlay1.MyLocationEnabled=MyLocationEnabled
        MyLocationOverlay1.CompassEnabled=True
        MyLocationOverlay1.MyLocationEnabled=True
        MyLocationOverlay1.FollowLocationEnabled=True
    End If
    ScaleBarOverlay1.Initialize(MapView1)
    MapView1.AddOverlay(ScaleBarOverlay1)
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)
    '    save the current map zoom level and center
    Dim RandomAccessFile1 As RandomAccessFile
    RandomAccessFile1.Initialize(File.DirInternal, SavedMapStateFileName, False)
    RandomAccessFile1.WriteObject(MapView1.GetCenter, True, 0)
    RandomAccessFile1.WriteInt(MapView1.Zoom, RandomAccessFile1.CurrentPosition)
    RandomAccessFile1.Close
        '    save the MyLocationOverlay state
    CompassEnabled=MyLocationOverlay1.CompassEnabled
    FollowLocationEnabled=MyLocationOverlay1.FollowLocationEnabled
    MyLocationEnabled=MyLocationOverlay1.MyLocationEnabled
    '    disable MyLocationOverlay compass and GPS listening
    MyLocationOverlay1.CompassEnabled=False
    MyLocationOverlay1.MyLocationEnabled=False
End Sub

Sub Menu_Click
    Dim Action As String=Sender
    Select Action
        Case "Clear saved state"
            If File.Exists(File.DirInternal, SavedMapStateFileName) Then
                File.Delete(File.DirInternal, SavedMapStateFileName)
            End If
    End Select
End Sub
'    event listeners for the three events that MyLocationOverlay generates
Sub MyLocationOverlay1_FollowLocationAutoDisabled
    Log("MyLocationOverlay1_FollowLocationAutoDisabled")
    '    if FollowLocation is enabled and the map is dragged then FollowLocation is automatically disabled
    'ToastMessageShow("FollowLocation is now DISABLED due to the map being dragged", False)
    Timer1.Enabled = True
End Sub

Sub MyLocationOverlay1_LocationChanged(NewLocation As Location, IsFirstFix As Boolean)
    Log("MyLocationOverlay1_LocationChanged, Latitude="&NewLocation.Latitude&", Longitude="&NewLocation.Longitude&", IsFirstFix="&IsFirstFix)
End Sub

Sub MyLocationOverlay1_ProviderChanged(Provider As String, Enabled As Boolean)
    '    note that i have yet to see this event generated
    Log("MyLocationOverlay1_ProviderChanged, Provider="&Provider&", Enabled="&Enabled)
End Sub

Sub Timer1_Tick
   'Handle tick events
    MyLocationOverlay1.CompassEnabled=True
    MyLocationOverlay1.MyLocationEnabled=True
    MyLocationOverlay1.FollowLocationEnabled=True
End Sub
 

cas6678

Active Member
Licensed User
My map is big. I have changed it by the map of Monaco that came in the example of Martin because it is smaller
 

Attachments

  • apkmap.zip
    92.3 KB · Views: 569

tracklocator

Member
Licensed User
I am not sure in some points and there is not much information about it I hope with this you can continue
B4X:
#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: True
    #ApplicationLabel: MapsForgeOsmDroid38 (mapa)
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

Sub Process_Globals
    Dim SavedMapStateFileName As String="map_state.dat"
    Dim CompassEnabled, FollowLocationEnabled, MyLocationEnabled As Boolean
    Dim Timer1 As Timer
End Sub

Sub Globals
    Dim MapView1 As OSMDroid_MapView
    Dim ScaleBarOverlay1 As OSMDroid_ScaleBarOverlay
    Dim MyLocationOverlay1 As OSMDroid_MyLocationOverlay
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Timer1.Initialize("Timer1", 5000) ' 5000 = 5 seconds
    Dim MapCenter As OSMDroid_GeoPoint
    Dim MapsForgeTileSourceName As String="MapsForge1"
    Dim MapsForgeDatabaseName As String="monaco.map"
    Dim MapsForgeDatabasePath As String=File.DirRootExternal
    Dim ZoomLevel As Int
    If File.Exists(MapsForgeDatabasePath, MapsForgeDatabaseName)=False Then
        File.Copy(File.DirAssets, MapsForgeDatabaseName, MapsForgeDatabasePath, MapsForgeDatabaseName)
    End If
    MapView1.Initialize("")
    Dim CurrentTilesSources As List=MapView1.GetTileSources
    If CurrentTilesSources.IndexOf(MapsForgeTileSourceName)=-1 Then
        '    the MapsForgeTileSource has not been added to the MapView so create it and add it to the map
        Dim MapsForgeTileSource1 As MapsForgeTileSource
        '    set the required MapsForgeTileSourceOptions MapDatabaseFile and TileSourceName
        MapsForgeTileSource1.GetMapsForgeTileSourceOptions.SetMapDatabaseFile(MapsForgeDatabasePath, MapsForgeDatabaseName)
        MapsForgeTileSource1.GetMapsForgeTileSourceOptions.SetTileSourceName(MapsForgeTileSourceName)
        '    example of setting an optional MapsForgeTileSourceOptions
        '    MapsForgeTileSource1.GetMapsForgeTileSourceOptions.SetTextScale(2.0)
        '    now that the required MapsForgeTileSourceOptionshave been set we can call the MapsForgeTileSource Initialize method
        MapsForgeTileSource1.Initialize
        MapView1.GetTileProvider(MapsForgeTileSource1)
    End If
    MapView1.SetMultiTouchControls(True)
    MapView1.SetTileSource(MapsForgeTileSourceName)
    MapView1.SetBuiltInZoomControls(True)
    If File.Exists(File.DirInternal, SavedMapStateFileName) Then
        '    restore the saved map state
        Dim RandomAccessFile1 As RandomAccessFile
        RandomAccessFile1.Initialize(File.DirInternal, SavedMapStateFileName, True)
        MapCenter=RandomAccessFile1.ReadObject(0)
        ZoomLevel=RandomAccessFile1.ReadInt(RandomAccessFile1.CurrentPosition)
        RandomAccessFile1.Close
        MapView1.GetZoomLevel=ZoomLevel
        MapView1.GetMapCenter
    Else
        MapCenter=MapsForgeTileSource1.MapDatabase.MapFileInfo.StartPosition
        ZoomLevel=MapsForgeTileSource1.MapDatabase.MapFileInfo.StartZoomLevel
        If MapCenter.IsInitialized And ZoomLevel<>-1 Then
            '    the map database has a start position and a start zoom set
            '    we'll use that for the default map state
            MapView1.GetZoomLevel=ZoomLevel
            MapView1.GetMapCenter
        Else
            '    the default map state will be defined by the area covered by the map database
            MapView1.ZoomToBoundingBox(MapsForgeTileSource1.MapDatabase.MapFileInfo.BoundingBox)
        End If
    End If
    Activity.AddView(MapView1, 10%x, 10%y, 80%x, 80%y)
   
    Activity.AddMenuItem("Clear saved state", "Menu")
    '    initialize and add the MyLocationOverlay to the MapView, an EventName is used as we'll be listening for all three events that this overlay generates
    MyLocationOverlay1.Initialize( "MyLocationOverlay1",MapView1)
    MapView1.GetOverlays.Add(MyLocationOverlay1)
    If FirstTime Then
        '    set the default values for the new variables
'        MyLocationOverlay1.CompassEnabled=True
        MyLocationOverlay1.EnableMyLocation
        MyLocationOverlay1.EnableFollowLocation
'        CompassEnabled=MyLocationOverlay1.CompassEnabled
        MyLocationOverlay1.EnableFollowLocation
        MyLocationOverlay1.EnableMyLocation
    Else
        '    restore the MyLocationOverlay state
        '        MyLocationOverlay1.CompassEnabled=True
        MyLocationOverlay1.EnableMyLocation
        MyLocationOverlay1.EnableFollowLocation
        '        CompassEnabled=MyLocationOverlay1.CompassEnabled
        MyLocationOverlay1.EnableFollowLocation
        MyLocationOverlay1.EnableMyLocation
    End If
    ScaleBarOverlay1.Initialize
    MapView1.GetOverlays.Add(ScaleBarOverlay1)
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)
    '    save the current map zoom level and center
    Dim RandomAccessFile1 As RandomAccessFile
    RandomAccessFile1.Initialize(File.DirInternal, SavedMapStateFileName, False)
    RandomAccessFile1.WriteObject(MapView1.GetMapCenter, True, 0)
    RandomAccessFile1.WriteInt(MapView1.GetZoomLevel, RandomAccessFile1.CurrentPosition)
    RandomAccessFile1.Close
        '    save the MyLocationOverlay state
'    CompassEnabled=MyLocationOverlay1.CompassEnabled
    MyLocationOverlay1.EnableFollowLocation
    MyLocationOverlay1.EnableMyLocation
    '    disable MyLocationOverlay compass and GPS listening
'    MyLocationOverlay1.CompassEnabled=False
    MyLocationOverlay1.DisableMyLocation
End Sub

Sub Menu_Click
    Dim Action As String=Sender
    Select Action
        Case "Clear saved state"
            If File.Exists(File.DirInternal, SavedMapStateFileName) Then
                File.Delete(File.DirInternal, SavedMapStateFileName)
            End If
    End Select
End Sub
'    event listeners for the three events that MyLocationOverlay generates
Sub MyLocationOverlay1_FollowLocationAutoDisabled
    Log("MyLocationOverlay1_FollowLocationAutoDisabled")
    '    if FollowLocation is enabled and the map is dragged then FollowLocation is automatically disabled
    'ToastMessageShow("FollowLocation is now DISABLED due to the map being dragged", False)
    Timer1.Enabled = True
End Sub

Sub MyLocationOverlay1_LocationChanged(NewLocation As Location, IsFirstFix As Boolean)
    Log("MyLocationOverlay1_LocationChanged, Latitude="&NewLocation.Latitude&", Longitude="&NewLocation.Longitude&", IsFirstFix="&IsFirstFix)
End Sub

Sub MyLocationOverlay1_ProviderChanged(Provider As String, Enabled As Boolean)
    '    note that i have yet to see this event generated
    Log("MyLocationOverlay1_ProviderChanged, Provider="&Provider&", Enabled="&Enabled)
End Sub

Sub Timer1_Tick
   'Handle tick events
'    MyLocationOverlay1.CompassEnabled=True
    MyLocationOverlay1.EnableMyLocation
    MyLocationOverlay1.EnableFollowLocation
End Sub
 

Magma

Well-Known Member
Licensed User
Hi,

in b4a...
I was using Mapnik tiles (I was using Mobile Atlas - must use this tool or something else ? 1st - question) and OSM Droid 3.53 for personal use... i ve change mobile phone -took 5 inch better...
but suddenly tiles of MapNik not displaying as before - it is like resolution is different (it is different!)...

+ I am trying from b4j use the same maps with osm droid - is not possible ? something for the same use (2nd-question)

That i am telling... because i want to make an app that will be use at small phones or big or tablets and i want to use the same maps with my desktop app (i will create at b4j)...

So from now on - what type of Tiles i must use in what res / what osmdroid / for offline (ofcourse) use ? (3-5 question)
Is it possible to get geocoding without paying google (getting address name with no or the exactly lat/lon if now address) (6-question)
Is it possible to get distance between lat/lon points through roads from these maps too. (7 question)

Sorry for too many questions but i wanna update my APP and boost it (becasue is too old for my extra options)
 

tracklocator

Member
Licensed User
Hello, I am still working on my project, I use my own map tiles server and it works very well.
I have not done anything with Mapnik.
In the following link are examples of the OSMDroid library I recommend using version 4.1.
Answer first question:
You can use it in a personal or commercial way respecting the guidelines of Apache License 2.0
Answer second question:
In the examples the map fits on any screen.
Answer question 3-5
All google services are costly if they do not meet the usage conditions.
7.
I am just looking at that point and I saw a project to get routes and the distance from point A and B but it is somewhat complex http://wiki.openstreetmap.org/wiki/Valhalla

Something I've seen is that most of the sites that offer tiles and geocoding have limits that's why I've been working on my services and until now I already have my own tile server with
Https://switch2osm.org/serving-tiles/manually-building-a-tile-server-14-04/
Nominatim reverse Geocode
Http://wiki.openstreetmap.org/wiki/Nininatim/Installation
Routes and distance
Http://wiki.openstreetmap.org/wiki/Valhalla

And I am very enthusiastic trying to add opentraffic but I still do not succeed.

As you realize there is a lot of way but you can achieve a good job.
 

Magma

Well-Known Member
Licensed User
@tracklocator
Thanks for the answer...

1) Not trying to make my openstreetmap server.. i want only use local maps (like city or country) downloaded at my devices (phone, tablet) - whats the best way (app for windows) to download mapnik openstreetmap tiles to my local pc and use at my devices... what resolution i will pick...

But i want to have latest maps and working tiles...

2) can i use ready packs like *.shp.zip or *.osm.pbf from ex. geofabrik.de ?

3) is continue from 2.. .can i use .map or .pbf at B4J (not b4a).. ?

Thanks again :)
 
Last edited:

canalrun

Well-Known Member
Licensed User
Hello,

I'm using OSMDroid version 3.6. It looks like this may be an older version, but it does everything I want, and it works beautifully.

Thank you Martin.

I am showing maps on an Android Wear Watch. There is no Wi-Fi and no cellular. I download tiles for the area I will be traveling so that I can view my location.

Sometimes I will be viewing maps at, for example, zoom level 16, and I will travel outside the area for which I have tiles. But, I may have tiles stored on the watch for this location at zoom level 15.

Is there any way to detect that tiles don't exist at the current zoom level but do exist for the current location at a different zoom level?

I could then automatically switch to that zoom level.

This is not a biggie requirement, just something that might be useful if it already exists.

Barry.
 

pompierecattivo

Member
Licensed User
Hello,
i'm testing for b4a apps using offline sqlitedb maps. As others, i've obtained an empty screen using the example 11 provided at the fist page. I'm not sure what i have to indicate on SetTileSource (my map file's named "sardroidmap.sqlitedb"). Of couse i've placed it directly on osmdroid folder. I'm sure about my map file because i could open it correctly in a Locus GIS (beta) app. I'm using 3.0.8 ver of osmdroid.
Any help appreciate, thank you.
Sorry for my bad english.
 

DonManfred

Expert
Licensed User
B4X:
dim point as geopoint
point.Initialize(52.75192, 0.40505)
MapView1.SetCenter3(point)
 

js486dog

Active Member
Licensed User
what version od osmGroid are you using? i'm using 4_1.
and does not have

B4X:
MapView1.SetCenter3(point)

Maybe this one:

B4X:
Sub Process_Globals
    Dim MapCenter As OSMDroid_GeoPoint
End Sub

Sub Activity_Create(FirstTime As Boolean)

lat_deg=49.106214
lon_deg=18.926182
MapCenter.Initialize(lat_deg, lon_deg)

MapView1.GetController.SetCenter(MapCenter)

End Sub
 

jamesnz

Active Member
Licensed User
Can anyone confirm that OSMDroid_4_1 (Version (0.04)
and OSMDroid_4_1_MapsForgeTileSource are the only libraries required ?
my code below ( Martins - MapsForgeTileSource) does not recognise the MapView
This did work when using 3_08

B4X:
#Region Module Attributes
    #FullScreen: False
    #IncludeTitle: True
    #ApplicationLabel: MapsForgeTileSource
    #VersionCode: 1
    #VersionName:
    #SupportedOrientations: unspecified
    #CanInstallToExternalStorage: False
#End Region

Sub Process_Globals
    Dim SavedMapStateFileName As String="map_state.dat"
End Sub

Sub Globals
    Dim MapView1 As MapView
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Dim MapCenter As GeoPoint
    Dim MapsForgeTileSourceName As String="MapsForge1"
    Dim MapsForgeDatabaseName As String="monaco.map"
    Dim MapsForgeDatabasePath As String=File.DirRootExternal
    Dim ZoomLevel As Int
    
    If File.Exists(MapsForgeDatabasePath, MapsForgeDatabaseName)=False Then
        File.Copy(File.DirAssets, MapsForgeDatabaseName, MapsForgeDatabasePath, MapsForgeDatabaseName)
    End If

    MapView1.Initialize("")
    
    Dim CurrentTilesSources As List=MapView1.GetTileSources
    If CurrentTilesSources.IndexOf(MapsForgeTileSourceName)=-1 Then
        '    the MapsForgeTileSource has not been added to the MapView so create it and add it to the map
        
        Dim MapsForgeTileSource1 As MapsForgeTileSource
        '    set the required MapsForgeTileSourceOptions MapDatabaseFile and TileSourceName
        MapsForgeTileSource1.GetMapsForgeTileSourceOptions.SetMapDatabaseFile(MapsForgeDatabasePath, MapsForgeDatabaseName)
        MapsForgeTileSource1.GetMapsForgeTileSourceOptions.SetTileSourceName(MapsForgeTileSourceName)
        
        '    example of setting an optional MapsForgeTileSourceOptions
        '    MapsForgeTileSource1.GetMapsForgeTileSourceOptions.SetTextScale(2.0)
        
        '    now that the required MapsForgeTileSourceOptionshave been set we can call the MapsForgeTileSource Initialize method
        MapsForgeTileSource1.Initialize
        MapView1.AddTileSource(MapsForgeTileSource1)
    End If
    
    MapView1.SetMultiTouchEnabled(True)
    MapView1.SetTileSource(MapsForgeTileSourceName)
    MapView1.SetZoomEnabled(True)
    
    If File.Exists(File.DirInternal, SavedMapStateFileName) Then
        '    restore the saved map state
        Dim RandomAccessFile1 As RandomAccessFile
        RandomAccessFile1.Initialize(File.DirInternal, SavedMapStateFileName, True)
        MapCenter=RandomAccessFile1.ReadObject(0)
        ZoomLevel=RandomAccessFile1.ReadInt(RandomAccessFile1.CurrentPosition)
        RandomAccessFile1.Close
        MapView1.Zoom=ZoomLevel
        MapView1.SetCenter3(MapCenter)
    Else
        MapCenter=MapsForgeTileSource1.MapDatabase.MapFileInfo.StartPosition
        ZoomLevel=MapsForgeTileSource1.MapDatabase.MapFileInfo.StartZoomLevel
        If MapCenter.IsInitialized And ZoomLevel<>-1 Then
            '    the map database has a start position and a start zoom set
            '    we'll use that for the default map state
            MapView1.Zoom=ZoomLevel
            MapView1.SetCenter3(MapCenter)
        Else
            '    the default map state will be defined by the area covered by the map database
            MapView1.FitMapToBoundingBox(MapsForgeTileSource1.MapDatabase.MapFileInfo.BoundingBox)
        End If
    End If
    
    Activity.AddView(MapView1, 0, 0, 100%x, 100%y)
    
    Activity.AddMenuItem("Clear saved state", "Menu")
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)
    '    save the current map zoom level and center
    Dim RandomAccessFile1 As RandomAccessFile
    RandomAccessFile1.Initialize(File.DirInternal, SavedMapStateFileName, False)
    RandomAccessFile1.WriteObject(MapView1.GetCenter, True, 0)
    RandomAccessFile1.WriteInt(MapView1.Zoom, RandomAccessFile1.CurrentPosition)
    RandomAccessFile1.Close
End Sub

Sub Menu_Click
    Dim Action As String=Sender
    Select Action
        Case "Clear saved state"
            If File.Exists(File.DirInternal, SavedMapStateFileName) Then
                File.Delete(File.DirInternal, SavedMapStateFileName)
            End If
    End Select
End Sub
 

fernando.oliboni

Member
Licensed User
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.



Hello warwound, why doesn't your OSMDroid library need to be declared in B4A's #Region Module Attributes?
 

junglejet

Active Member
Licensed User
Is there any update out there for B4A that is based on a newer library of the guthub project? OSM-Droid 4.1 for B4A does not load tiles from https servers or servers that redirect their http calls to https. Also http calls have been slowed down on newer Androids by Google making loading tiles a pain.
 
Top