B4A Library OSMDroid - MapView for B4A

Here we have my latest library - OSMDroid provides a MapView for B4A.

More info on the original (native Android) OSMDroid project can be found here: osmdroid - OpenStreetMap-Tools for Android - Google Project Hosting.

Library reference is no longer included in this post due to limits on the number of characters allowed in a single post.

I have created some tutorials to show basic usage of the library and will update this thread with a link to them as soon as i have them all uploaded.

** Your attention is drawn to the included file Apache License Version 2.0.txt, which is a copy of the Apache License Version 2.0 under which the native Android OSMDroid library is released **

Martin.
 

Attachments

  • OSMDroid_3_0_8_v3.60.zip
    361.9 KB · Views: 4,226
Last edited:

mortenplaya

Member
Licensed User
Longtime User
Redrawing TilesOverlay

Hi Martin,
I made a strange discovery when testing TilesOverlay with TMS tiles. It seems like the process of redrawing tiles fails at certain zoom levels depending on the data set.
I was playing around with the MapView SetDataConnectionEnabled method TilesOverlay DataconnectionEnabled property to see if it would make any difference. It didn’t . Then I decided to go completely offline turning the flight mode on. Again some of the tiles failed to redraw when zooming in and out. The tiles immediately emerge when panning the map (all tiles are stored on the SD card).
The XYZTileSource method doesn't seem to have this behavior. I have also been testing the sea map overlay example. At certain zoom levels some of the wind mills areas were filled with grey color failing to redraw completely. The same happens when using the android emulator(platform 2.2).However it is a minor problem since the tiles will pop up when the user is moving around at the same zoom level:D. Maybe the conslusion is that I should exchange my old phone. Feel free to try my test data set. See url description in my previous post.

Thanks:)!
Morten
 

warwound

Expert
Licensed User
Longtime User
The XYZTileSource method doesn't seem to have this behavior.

The TilesOverlay uses an XYTileSource (internally) to manage tile requests, so there's no difference to the way tiles are requested.

TilesOverlay is an Overlay and some Overlays require manually calling the MapView Invalidate method or panning/zooming the map to force a redraw.

An XYTileSource custom tile layer is not an Overlay so is refreshed in a different way.

I think the problem is that if a tile request does not complete within a certain time then the library cancels the thread that would render the tile when it downloads.
So some tiles will take a while to download, get cached but not rendered until the map is panned or zoomed.

A slow tile server and/or a slow device will make the problem worse.
My 600Mhz ZTE Blade shows the problem quite often whereas my faster 1GHz Huawei Ascend shows the problem only with a slow tile server.

If i can make time i'll give your tile server a test - too busy at the moment though.

Martin.
 

warwound

Expert
Licensed User
Longtime User
Hello warwound! Thanks for your efforst!

I use the data of the gps-lib in a service because, I need the gps-data not only in my mapview-activity. There are some other activities, which needs the gps-data. Also I need the satellites in use, the speed and the altitude, so I think, that I can not miss the gps-library for my application. The only thing I need is to show an icon on a gps-position, which is centered on the position. Than I can show my own icon with an arrow for the bearing....:sign0148:

Thanks for an answer and greetings from germany..

What errors appear in the (unfiltered) log when you use both GPS library and OSMDroid MyLocationOverlay at the same time?

There is a post on the forum from BarrySumpter where he was trying to rotate a marker icon.
I've searched but cannot find it - you might find it worth searching for.

Otherwise i'll try and think of a solution myself.

Martin.
 

warwound

Expert
Licensed User
Longtime User
OSMDroid updated to version 3.30

This updates add support for Tile Map Service (TMS) tile servers.
You can use a TMS tile server as a custom TileSource or as a source for a TilesOverlay.
See this thread for more details about TMS: http://www.b4x.com/forum/additional.../16309-osmdroid-mapview-b4a-9.html#post124016

TilesOverlay is updated with two new methods Initialize3 and Initialize4:

TilesOverlay
Properties:
  • DataConnectionEnabled As Boolean
    Get or Set whether this TilesOverlay will use the device's data connection.
  • LoadingBackgroundColor As Int
    Get or Set the background color displayed while waiting for a tile to be downloaded.
    Setting a value of Colors.TRANSPARENT will disable the display of any background color.
    The default value is Colors.TRANSPARENT, no background color is displayed.
  • LoadingLineColor As Int
    Get or Set the line color used to separate the background color drawn while waiting a tile to be downloaded.
    The line color will only be drawn if the background color is NOT set to transparent.
    The default value is Colors.rgb(200, 192, 192).
Methods:
  • Initialize (Name As String, MinZoomLevel As Int, MaxZoomLevel As Int, TileSize As Int, TileFilenameEnding As String, BaseUrl As String)
    Initialize the TilesOverlay, the TileSource must implement the Slippy map tile naming convention.
  • Initialize2 (Name As String, MinZoomLevel As Int, MaxZoomLevel As Int, TileSize As Int, TileFilenameEnding As String, BaseUrls As String())
    Initialize the TilesOverlay, the TileSource must implement the Slippy map tile naming convention.
    An Array of Strings is passed for the BaseUrls parameter.
  • Initialize3 (Name As String, MinZoomLevel As Int, MaxZoomLevel As Int, TileSize As Int, TileFilenameEnding As String, BaseUrl As String)
    Initialize the TilesOverlay, the TileSource must implement the TileMapService (TMS) map tile naming convention.
  • Initialize4 (Name As String, MinZoomLevel As Int, MaxZoomLevel As Int, TileSize As Int, TileFilenameEnding As String, BaseUrls As String())
    Initialize the TilesOverlay, the TileSource must implement the TileMapService (TMS) map tile naming convention.
    An Array of Strings is passed for the BaseUrls parameter.
  • IsInitialized As Boolean

And XYTileSource has a new property named TMSMode:

XYTileSource
Properties:
  • TMSMode As Boolean
    Get or Set whether Tile Map Service (TMS) mode is enabled or not.
    By default TMS mode is NOT enabled.
Methods:
  • Initialize (Name As String, MinZoomLevel As Int, MaxZoomLevel As Int, TileSize As Int, TileFilenameEnding As String, BaseUrl As String)
    Initialize the XYTileSource object.
    The XYTileSource must implement the Slippy map tile naming convention.
  • Initialize2 (Name As String, MinZoomLevel As Int, MaxZoomLevel As Int, TileSize As Int, TileFilenameEnding As String, BaseUrls As String())
    Initialize the XYTileSource object.
    The XYTileSource must implement the Slippy map tile naming convention.
    An Array of Strings is passed for the BaseUrls parameter.
  • IsInitialized As Boolean

The tutorials for both of these objects remains valid - if you want to use a TMS tile server instead of a slippy map tile server then choose the relevant option to enable TMS support instead of slippy map support.

Version 3.30 is attached to the first post in this thread.

Martin.
 

schimanski

Well-Known Member
Licensed User
Longtime User
Problem with saving a list of markers

I can't find the mistake...:BangHead:

When I use this code to save the list of markers, I always get a problem with
reading the list.

B4X:
Sub Globals 
   Dim MarkerListe As List
End Sub

Sub Activity_Create(FirstTime As Boolean)

    Dim raf As RandomAccessFile 
    raf.Initialize(File.DirInternal,"Marker.dat",False)  
    MarkerListe = raf.ReadObject(0) 
    raf.Close
...
end sub

Sub Activity_pause
    Dim raf As RandomAccessFile

    raf.Initialize(File.DirInternal,"Marker.dat",False) 
    raf.WriteObject(MarkerListe,True,0)
    raf.Close
...
end sub

In the log i get this:

B4X:
** Activity (mapviewer2) Resume **
(ArrayList) [null, null, null, null, null, null, null]
java.lang.NullPointerException
   at org.osmdroid.views.overlay.ItemizedOverlay.draw(ItemizedOverlay.java:117)
   at uk.co.martinpearman.b4a.osmdroid.views.overlays.MyItemizedOverlayWithFocus.draw(MyItemizedOverlayWithFocus.java:145)
   at org.osmdroid.views.overlay.OverlayManager.onDraw(OverlayManager.java:119)
   at org.osmdroid.views.MapView.dispatchDraw(MapView.java:867)
   at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
   at android.view.View.draw(View.java:6883)
   at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
   at android.view.View.draw(View.java:6883)
   at android.widget.FrameLayout.draw(FrameLayout.java:357)
   at android.view.ViewGroup.drawChild(ViewGroup.java:1646)
   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
   at android.view.ViewGroup.drawChild(ViewGroup.java:1644)
   at android.view.ViewGroup.dispatchDraw(ViewGroup.java:1373)
   at android.view.View.draw(View.java:6883)


   at android.widget.FrameLayout.draw(FrameLayout.java:357)
   at com.android.internal.policy.impl.PhoneWindow$DecorView.draw(PhoneWindow.java:2092)
   at android.view.ViewRoot.draw(ViewRoot.java:1565)
   at android.view.ViewRoot.performTraversals(ViewRoot.java:1301)
   at android.view.ViewRoot.handleMessage(ViewRoot.java:1914)
   at android.os.Handler.dispatchMessage(Handler.java:99)
   at android.os.Looper.loop(Looper.java:130)
   at android.app.ActivityThread.main(ActivityThread.java:3906)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:507)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:840)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:598)
   at dalvik.system.NativeStart.main(Native Method)
** Service (widget2x1) Start **

It seems, that I save an emty list????

Thanks for help...
 

warwound

Expert
Licensed User
Longtime User
Try debugging it by adding this code after the raf.Close in Activity_Create:

B4X:
Dim Marker1 As Marker
Dim i, j As Int
j=MarkerListe.Size-1
Log("MarkerListe contains "&(j+1)&" Marker objects)
For i=0 To j
   Marker1=MarkerListe.Get(i) '   put a breakpoint on this line and run in debug mode, is the object a Marker or a MarkerWrapper?
   Log(Marker1.GeoPoint)
Next

I suspect that using RandomAccessFile to save instances of the Marker class may not be as straightforward as it seems...

Martin.
 

schimanski

Well-Known Member
Licensed User
Longtime User
Hello Martin,

I have checked the size of the file, but it is always nothing and the code above doesn't get some data of a marker. It seems, that it is not possibel to save markers on this way. But is there another way to save the data of the markerslist?
 

warwound

Expert
Licensed User
Longtime User
Well the Marker has properties Description, GeoPoint and Title so as long as you have a reference to each Marker then you can get the Marker's various properties and save them (in theory).

Are you keeping a reference to each Marker when you create them or looking for a method to return a collection of Markers from an Overlay layer?

If you have the Marker references then there's various options:

1) You could use a SQLite database table to store all Marker properties.
Not quick n simple to implement but powerful if at any point in time you want to start filtering Markers or other advanced things.

2) Can RandomAccessFile successfully save a List of Maps?
If so then i'd create a Map for each Marker, create keys for Description, Latitude, Longitude and Title and populate each Map in the List with a Marker's properties.
Quick n simple to implement and should be quick to recreate your Markers when your app reloads.

Martin.
 

warwound

Expert
Licensed User
Longtime User
OSMDroid updated to version 3.40

This updates adds:
  • MapView has a new MapOrientation property.
    Get or Set the MapOrientation in degrees, rotates the MapView.
    This feature was requested and i've implemented it BUT it is not perfect.
    See this post for details: http://www.b4x.com/forum/basic4andr...droid-mapview-b4a-tutorial-15.html#post126163
  • Marker now has a new (write only) property MarkerHotspot.
    Set the offset where the Marker will be anchored to the MapView.
    Possible values are:
    • CENTER
    • BOTTOM_CENTER (default)
    • TOP_CENTER
    • RIGHT_CENTER
    • LEFT_CENTER
    • UPPER_RIGHT_CORNER
    • LOWER_RIGHT_CORNER
    • UPPER_LEFT_CORNER
    • LOWER_LEFT_CORNER
    • NONE

I shall upload some demo code to the OSMDroid tutorial thread shortly.

Version 3.40 of OSMDroid is attached to the first post in this thread.

Martin.
 

warwound

Expert
Licensed User
Longtime User
OSMDroid updated to version 3.41

This update is just a bug fix.

The PathOverlay AddPoints method previously expected a List of GeoPointWrapper objects.
The GetAllPoints method returns a List of GeoPointWrapper objects, but if you programmatically created a List of GeoPointWrapper objects then the GeoPointWrapper objects would be turned into native GeoPoint objects.

Passing a List of GeoPoint objects to AddPoints caused a Class cast exception, this update fixes that.
AddPoints will now automatically handle a List of GeoPointWrapper OR GeoPoint objects.

I also fixed a bug where AddPoints added all items in the list except for the last item.

Version 3.41 of OSMDroid is attached to the first post in this thread.

Martin.
 

cirollo

Active Member
Licensed User
Longtime User
Still having problem with multimarkers

OSMDroid updated to version 2.00

This is an important update even though it has no new features or methods.

For a technical insight into why the update was required please read this thread: http://www.b4x.com/forum/libraries-...1-wrappedobject-becomes-object.html#post93413.

Your existing code should work without modification unless you have incorporated the example code for MarkersOverlay or MarkersFocusOverlay into your project.

I have updated both those threads to make them work with version 2.00, the only change required was the way that the List was Initialized with the Marker objects.

Old code:

B4X:
Markers.Initialize2(Array As Marker(Marker1, Marker2))

New code:

B4X:
Markers.Initialize2(Array As Object(Marker1, Marker2))

The library is now more compatible with the way that B4A handles object wrappers.

Version 2.00 is attached to the first post in this thread.

Martin.

Hi Martin!
Using your method for multi markers I get the error in the attached jpg here:

http://www.emmecisistemi.com/ERRORE_OSMDROID.jpg
What could be????
 
Last edited:

warwound

Expert
Licensed User
Longtime User
Try changing your AnArray from an array of Marker type to an array of Object type:

B4X:
Dim AnArray(recno) As Object

Now when you add a Marker to the array it maintains it's original wrapped state.
Adding a Marker to the array of Marker types transforms the wrapped Marker into a bare Marker and causes the class cast exception.

Martin.
 

warwound

Expert
Licensed User
Longtime User
I shall have to update the AddMarkers method of all of the Overlay layers so that they accept either a List of wrapped Marker objects or a List of unwrapped Marker objects.

I did a similar bug fix to the PathOverlay recently - it was the only way to ensure the PathOverlay AddPoints method could handle a List of wrapped GeoPoints or a List of unwrapped GeoPoints.

Leave it with me - i can probably post an alpha library update for you to test a bit later, and if it works i'll make the update 'official'.

Martin.
 

warwound

Expert
Licensed User
Longtime User
Just looking at updating the library and realised i need a bit more info...

Can you export your project File menu Export as ZIP and post it in this thread?

Thanks.

Martin.
 

cirollo

Active Member
Licensed User
Longtime User
here it is

let me know....

regards

ciro
 

Attachments

  • estasi_project.zip
    48.5 KB · Views: 285

cirollo

Active Member
Licensed User
Longtime User
Solved!

made this change following Avoid a Crime example

B4X:
   Case FRIENDS_LIST
         'add the countries to the ListView
         Dim nearfriends As List
         nearfriends = parser.NextArray 'returns a list with maps
         Dim Markers As List
         Markers.Initialize
         For i = 0 To nearfriends.Size - 1
            Dim m As Map
            m = nearfriends.Get(i)
            'markers
            Dim Marker1 As Marker
            Marker1.Initialize(m.Get("name"),m.Get("address"), m.Get("lat"),m.Get("lng"), Icon)
            Markers.Add(Marker1)
         Next      
          ' add the List of Markers to the MarkersOverlay
            MarkersOverlay1.AddMarkers(Markers)
         ProgressDialogHide

now it works!
just 1 question....

how can I refresh the map for example every 5 minutes???
I need to check if there are new markers
 

javiers

Active Member
Licensed User
Longtime User
Hello, first congratulations on your work.

One question:

tight orbit would draw a square or at a particular point OSM map, and that this remains to move the map. Is it possible?.

I appreciate your help.
 

warwound

Expert
Licensed User
Longtime User
Hello, first congratulations on your work.

One question:

tight orbit would draw a square or at a particular point OSM map, and that this remains to move the map. Is it possible?.

I appreciate your help.

You want to draw a square that remains fixed- just like the compass and zoom controls remain fixed?

There currently no way to do that within OSMDroid but you can add a normal B4A View (such as a Panel) to your Activity and draw a square to that Panel.
Position the square where you desire.
The result would look the same but note that your Panel must not consume any touch events that would otherwsie be consumed by the MapView.

Martin.
 

canalrun

Well-Known Member
Licensed User
Longtime User
OSMDroid ScaleBar window size

Hello,
First, thanks for a great library.

Is there a way to get the size of the ScaleBarOverlay?

I would like to reposition it on the screen, on the right-hand side, using the top or bottom locations and offsets. Having the overlay width and height would allow me to dynamically place it a little more accurately making sure it does not conflict with any of my views.

Thanks,
Barry.
 
Top