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:

jamesnz

Active Member
Licensed User
Longtime User
Just an idea I had re tile servers.
You can initialise a mapview and tile server based on your location.
eg if you have a custom tile server that covers a small area you can test that users device is 'outside' this area and use the standard OSM tile server, if inside the area you can use your own tile server. This solves the problem of having to host millions of tiles that are irrelevant to your needs.
 

georm

Member
Licensed User
Longtime User
Hello,
I want to add a new TileSource just Offline, never online. Is-it possible ?

Laurent.
 

georm

Member
Licensed User
Longtime User
Hello
I generated a set of zip tiles like offline_tile_cahe_myraster.zip and i want to use always offline.

Laurent
 

TAK

Member
Licensed User
Longtime User
Hello,
what i have to do, if i want use Compass, ScaleBar, Spinner...? If i only copy the code, its doesnt work.
 

warwound

Expert
Licensed User
Longtime User
Hello,
what i have to do, if i want use Compass, ScaleBar, Spinner...? If i only copy the code, its doesnt work.

You need to experiment with the manifest file.
Targeting an android api version of Honeycomb and newer and adding the android:hardwareAccelerated="false" attribute to the application element should work.

Have a look at this page: http://developer.android.com/guide/topics/graphics/hardware-accel.html.

  • The activity that displays the MapView needs hardware acceleration disabled.
  • Hardware acceleration is enabled by default for all activities in your application if your Target API level is >=14.
  • Hardware acceleration can be enabled or disabled for all activities or single activities using the manifest.
  • Hardware acceleration can also be disabled using code, this java method disables hardware acceleration for the MapView only:
    B4X:
    private void setHardwareAccelerationOff() {
    	if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
    		myMapView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }
    You can probably use JavaObject to execute this java and that would mean you don't have to modify the manifest.

Martin.
 
  • Like
Reactions: TAK

davelew1s

Active Member
Licensed User
Longtime User
Hi!
I've been through this thread but cannot find what I'm looking for .... I'm using ver 4.1.
I have an app which works ok what I want to do now is hide the map and replace it with a black screen, so that
I can put a pathsoverlay on and draw some shapes in white. I need to be able to switch back and forward.
Any help would be appreciated. Thanks Dave.
 

warwound

Expert
Licensed User
Longtime User
Hi!
I've been through this thread but cannot find what I'm looking for .... I'm using ver 4.1.
I have an app which works ok what I want to do now is hide the map and replace it with a black screen, so that
I can put a pathsoverlay on and draw some shapes in white. I need to be able to switch back and forward.
Any help would be appreciated. Thanks Dave.

I'd try a custom tile layer and use the same image for each and every tile.
A 256 pixel square black PNG is all you need.

Have a look thru the examples i uploaded to here: http://b4a.martinpearman.co.uk/osmdroid/
I'm sure there's a custom tile example in there somewhere.

Martin.
 

davelew1s

Active Member
Licensed User
Longtime User
Hi Martin!
Sorry to be a pain ...... but I cannot find anything in the link you provided, I've also checked this thread again with no luck. I know you are busy but can you offer any further pointers?
Thanks Dave.
 

warwound

Expert
Licensed User
Longtime User
Hi Martin!
Sorry to be a pain ...... but I cannot find anything in the link you provided, I've also checked this thread again with no luck. I know you are busy but can you offer any further pointers?
Thanks Dave.

I'll take a look in the morning.
 

warwound

Expert
Licensed User
Longtime User
I've spent the moring trying to create a new TileSource that'd allow you to use a local (file based) tile instead of an online tile.
I just couldn't get it to work.

So another solution is this:

B4X:
Sub Process_Globals
	Dim Constants1 As OSMDroid_Constants
End Sub

Sub Globals
	Dim InitialGeoPoint As OSMDroid_GeoPoint
	Dim MapView1 As OSMDroid_MapView
End Sub

Sub Activity_Create(FirstTime As Boolean)
	'	check the manifest for edits made re hardware acceleration
	
	MapView1.Initialize("")
	
	Dim MyTileSourceName As String="MyTileSourceName"
	Dim TileSourceFactory1 As OSMDroid_TileSourceFactory
	If Not(TileSourceFactory1.ContainsTileSource(MyTileSourceName)) Then
		Dim MyTileSource As OSMDroid_UrlTileSource
		MyTileSource.Initialize(MapView1, MyTileSourceName, "http://b4a.martinpearman.co.uk/osmdroid/plain_black_tile.png", 0, 16, 256)
		TileSourceFactory1.AddTileSource(MyTileSource)
	End If
	
	MapView1.SetTileSource(TileSourceFactory1.GetTileSource(MyTileSourceName))
	
	MapView1.GetOverlayManager.GetTilesOverlay.SetLoadingBackgroundColor(Colors.Green)
	MapView1.GetOverlayManager.GetTilesOverlay.SetLoadingLineColor(Colors.Red)
	MapView1.SetBuiltInZoomControls(True)
	MapView1.SetMultiTouchControls(True)
	
	'	now set the initial view
	'	set the zoom before the center
	InitialGeoPoint.Initialize(52.75240, 0.4040)
	MapView1.GetController.SetZoom(12)
	MapView1.GetController.SetCenter(InitialGeoPoint)
	
	Activity.AddView(MapView1, 0,0, 100%x, 100%y)
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

I created a plain black 256 pixel square tile and uploaded it to my server.
Then created a UrlTileSource which fetches this plain black tile for all map tiles.

It works but has one disadvantage...
OSMDroid will automatically cache all tiles to the external memory - that cant be prevented.
So your device will end up with this plain black tile cached many times, each time with a different filename.

Run the attached example then pan and zoom the map.
Now use a file manager app to browse on your device to the external memory, look for the path osmdroid/tiles/MyTileSourceName.
In that folder you'll find the black tile cached with a different file name for each time it's been used on the map.
Guess you could run a 'cleanup' within your app to delete these cached black tiles?

Martin.
 

Attachments

  • UrlTileSource.zip
    6.5 KB · Views: 441

davelew1s

Active Member
Licensed User
Longtime User
Thanks Martin! you can't blacker than that ... I'm working on it ....will let you know the results.
Dave.
 

GaNdAlF89

Active Member
Licensed User
Longtime User
Hi, I have a question: I want to block the mapview (to always show the same position in the map) but I need the markers_click event to open info about the marker clicked.
How can I do this? Thanks
 
Last edited:

TAK

Member
Licensed User
Longtime User
  • B4X:
    private void setHardwareAccelerationOff() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
            myMapView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
    }
    You can probably use JavaObject to execute this java and that would mean you don't have to modify the manifest.

Martin.
Hi Martin,
on which place do I have to paste this code?
 

PABLO2013

Well-Known Member
Licensed User
Longtime User
HI, MARTIN
I NOT KNOW THE WAY OR FORM TO PUT THIS IN MY APPLICATION ... AS I DO

private void setHardwareAccelerationOff() {if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
myMapView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
}

TKS
 
Top