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

warwound

Expert
Licensed User
Longtime User
Well after much panning around i think that tile represents (0, 0) - at zoom level 17 of course...

Google Maps API Tilenames

Probably downloaded when you centered a map to (0, 0) and zoomed in then panned immediately elsewhere never to return to (0, 0)?

Martin.
 

warwound

Expert
Licensed User
Longtime User
Version 3.22 of OSMDroid introduces the TouchEventsOverlay

TouchEventsOverlay is used to detect Clicks and LongClicks on the MapView.

TouchEventsOverlay has just one method:

Initialize (EventName As String)

TouchEventsOverlay raises two events:

Click (GeoPoint1 As GeoPoint)

LongClick (GeoPoint1 As GeoPoint)

You add a TouchEventsOverlay to a MapView using the MapView AddOverlay method and creates Subs to listen for either or both events.
The event Subs are pass the point clicked or long-clicked as a GeoPoint object:

B4X:
Sub Process_Globals
End Sub

Sub Globals
   Dim MapView1 As MapView
   Dim PathOverlay1 As PathOverlay
   Dim TouchEventsOverlay1 As TouchEventsOverlay
End Sub

Sub Activity_Create(FirstTime As Boolean)
   MapView1.Initialize("")
   MapView1.SetMultiTouchEnabled(True)
   MapView1.SetZoomEnabled(True)
   Activity.AddView(MapView1, 0, 0, 100%x, 100%y)
   
   MapView1.Zoom=14
   MapView1.SetCenter(52.75192, 0.40505)
   
   PathOverlay1.Initialize(MapView1, Colors.Red)
   PathOverlay1.StrokeWidth=4dip
   MapView1.AddOverlay(PathOverlay1)
   
   TouchEventsOverlay1.Initialize("TouchEventsOverlay1")
   MapView1.AddOverlay(TouchEventsOverlay1)
End Sub

Sub Activity_Resume
End Sub

Sub Activity_Pause (UserClosed As Boolean)
End Sub

Sub TouchEventsOverlay1_Click(GeoPoint1 As GeoPoint)
   Log("Click")
   PathOverlay1.AddPoint3(GeoPoint1)
   MapView1.Invalidate
End Sub

Sub TouchEventsOverlay1_LongClick(GeoPoint1 As GeoPoint)
   Log("LongClick")
   PathOverlay1.ClearPath
   PathOverlay1.AddPoint3(GeoPoint1)
   MapView1.Invalidate
End Sub

Here i add a PathOverlay to the MapView and then add the TouchEventsOverlay.
A click on the map adds the clicked point to the path overlay.
A long-click on the map clears any existing path overlay path and adds the long-clicked point to the path overlay.

It's required to call the MapView Invalidate method to cause the map to update itself.

If you have other overlay layers added to the map and those overlay layers detect click or long click events then you will have to experiment with the order in which you add all your overlay layers to the map to determine which overlay layer receives the click or long click events.

Martin.
 

Attachments

  • TouchEventsOverlayDemo.zip
    5.7 KB · Views: 594

wm.chatman

Well-Known Member
Licensed User
Longtime User
Hello warwound

My name is William. This is Very enjoyable material.
I am very glad to have found B4ppc and now, B4A. And of course "Thank You", for being so generous, and posting this "GREAT KILLER OPEN SOURCE".

this is bad to the bone... :sign0098:
 
Last edited:

abdulla

Member
Licensed User
Longtime User
Does OSMDROID Use Google maps

Does it use Google maps , or How would you specify to use Google Maps , if it uses it.
 

BarrySumpter

Active Member
Licensed User
Longtime User
Hi abdula,

We've discussed this thuroughly in the previous posts in this thead.

You'll need to read Martins comments on the legalities of using Goodle Maps.

Then you have to create your own Google Maps Tiles.zip.
---

I used Mobile Atlas Creator v1.8 for creating Google Maps tiles.

Kinda a pain as the more tiles you create the bigger the zip.
And the longer it takes.

Copilot Live has a 3 gig file for maps for Australia.

So I limited my tiles creation to only the area in which I would likely travel
on a daily basis thruought the year.

Then if I were to take a holiday I would generate tiles for that area under a differnet zip file and pick item in my app.

Then if I had to go somewhere I didn't have tiles for I'd just use Google Maps Apps for the interum.
---

Then update your apps script to use your tiles.zip.
Also, discussed in the previous posts of this thread.

hth
 
Last edited:

BarrySumpter

Active Member
Licensed User
Longtime User
Hi Martin,
Would you have an opinion on using the Location Manager Library as an alternative?
As I've mentioned before my GPS location drives me mad taking so long to discover when sitting at my PC and in various locations mentioned.
(update: and at different times of the day)

http://www.b4x.com/forum/additional.../13337-locationmanager-library.html#post75151

Could we implement in latest osmDroid map samples?
 
Last edited:

warwound

Expert
Licensed User
Longtime User
Hi Barry.

This does not make sense...

On your device go to Settings > Locations & security and disable 'Use wireless networks' and 'UseGPS satellites'.

Now run the LocationManager example project.
Click the Menu key and select Update location.

On my ZTE Blade (CyanogenMod7 Gingerbread) i get a dialog that states 'Provider disabled'.

I thought the B4A LocationManager library used CellId and did not use wireless or GPS to obtain a location.

Now i've looked at the B4A LocationManager source code and also the B4A OSMDroid MyLocationOverlay source code and they both basically do the same thing...

If GPS is available and enabled then GPS is used to obtain the device location.

Otherwise if the Settings option 'Use wireless networks'is enabled then the device location is obtained using wireless.

Neither seem to contain any code that uses the currently connected mobile CellId to obtain the device location.

Can you run the B4A LocationManager sample with the settings i mentioned above both disabled and let me know whether or not you get a location based on connected CellId?

I seem to remember many months ago reading that obtaining location by connected mobile CellId was being phased out as it was impractical/impossible for Google to maintain an up to date database of all mobile CellIds and locations of each cell for the entire planet - not sure where i read that though.

Martin.
 

warwound

Expert
Licensed User
Longtime User
A little update...

Have a read of this page: Location-Based Services Using CellID in Android

Obtaining a device location based on connected mobile CellId requires the use of a secret, unofficial and undocumented API!

If you've ever used Google Maps for Mobile, you'll be familiar with the My Location feature. This feature allows you to show your current location on the map, even if you don't have GPS on the device. How does Google Maps do this? The trick lies in obtaining the Cell ID contained on your device. My Location obtains the CellID and sends it sent back to a secret API at Google Maps. This API then returns the latitude and longitude that corresponds to the Cell ID. Apparently, Google Maps has a huge database containing all the world's cell IDs (at least it worked pretty well for me in Singapore).

To obtain latitude and longitude information using the cell ID and LAC, open an HTTP connection to the Google Maps API an send it some proprietary data.

Note that this method of resolving Cell ID and LAC information to latitude and longitude is not supported by Google. Chances are that Google may decide to remove this feature anytime they realize that it is being misused.

More positive info can be found here: Understanding Android: Three Ways to Find Your Location

The long way is the first one you’ll find when searching for Android Cell-ID. This involves creating an instance of TelephonyManager to acquire the Cell-ID, then routing it through a super-secret-special Google Maps API for which a Java code routine has been widely published online. But forget all that: what few sites mention is that the standard requestLocationUpdates() called on NETWORK_PROVIDER already uses your Cell-ID to obtain your location so long as you have your mobile network enabled.

So if wireless and/or GPS is enabled in location settings then the device will automatically try to use the CellId to get an initial location fix and then try to refine the accuracy of that fix using wireless or GPS.

Seems as though only Google products such as the Android Map app can officially make use of Google's mobile CellId database.

Martin.
 

BarrySumpter

Active Member
Licensed User
Longtime User
Wow!
Thanks for all the work in considering this option.
And the verbose replies.

I've had a super long day today so I might be a bit off at the mo.

I was thinking if current methods didn't work then try this one.
But if its the same method as the others then fair enough.

I could swear the location manager reported my lat lng almost immediately.
But at the time the gps was on.

And now you are correct, after turning the gps off locman won't report my latlng.

And was hoping the locman author had stumbled onto something we hadn't.


I don't understand this:
...
then routing it through a super-secret-special Google Maps API for which a Java code routine has been widely published online
...
As in aren't there java experts here that can implement this java code in b4a to take advantage of this super-secret-special Google Maps API?
Or maybe thats what you're writing is: No.
And I'm asking the same thing in circle.

I know that another AndApp my Taxi has got to be using this technique as it is so freakin fast find my location.
Perhaps without permission as risking Googles wrath.

Or maybe one can request and receive Googles permission to use it.

I'll have another go tomorrow with a fresh mind.
 
Last edited:

warwound

Expert
Licensed User
Longtime User
Using Google's database might work now, it might already have access restricted to it, or at any point in the future Google might restrict access to it.

Using a private non-documented and un-official API might work today but you risk creating an app that could break at any point in the future - depending on how Google treat unauthorised access to their database.

There seems to be an alternative: OpenCellID.

This project is an open source project, aiming to create a complete database of CellID worlwide, with their locations
Project will provides free access to tools, data to not only create this database, but also retreive location informations.

Look on the 'Browse cells' page and there's a link to a KML file showing all currently registered cells, here's the link: http://www.opencellid.org/cells.kml.

Open that KML file in Google Earth and browse the area where you're hoping to get device locations by CellId.
Do you see any or many cells?

if so then you can look at registering for an API key and using the service, you won't need any B4A library etc as it's standard web service you can access using HttpClient or HttpUtils etc.

Martin.
 

GaNdAlF89

Active Member
Licensed User
Longtime User
please help me, I don't find the required library to include for mapview
 
Last edited:

GaNdAlF89

Active Member
Licensed User
Longtime User
Sorry, I don't understand...What should I do to include the library in my project?
Thanks.
 

warwound

Expert
Licensed User
Longtime User
Have you added additional libraries to your B4A projects before?

Look in the B4A IDE under the Tools menu for Configue Paths - see the screengrab attached.
All additional libraries that you download and use must be placed in the Additional libraries folder.

So once you have downloaded the OSMDroid archive from the first post in this thread you need to copy both OSMDroid.jar and OSMDroid.xml to your Additional libraries folder.

Now restart the B4A IDE or select the Libs panel, right click and choose Refresh.

The OSMDroid library is now available to use in your B4A projects.

You might as well then take a look at the OSMDroid tutorials thread: http://www.b4x.com/forum/basic4andr...-osmdroid-mapview-b4a-tutorial.html#post92644

Martin.
 

Attachments

  • additional_libraries_path.jpg
    additional_libraries_path.jpg
    38.4 KB · Views: 316

WDanny

New Member
Licensed User
Longtime User
Own Map

Thanks a lot,

How do I add my own map? (I would like it to be a private - The app is not going to be on Play/Market)

Danny
 

warwound

Expert
Licensed User
Longtime User
Hi.

The answer depends entirely upon what you mean by own map...

Do you have your own custom map already rendered as tiles?
Are those tiles named according to the slippy map tile naming convention?

If so then you can create an offline tile archive using those tiles and use that tile archive as a custom TileSource - or host those tiles online and do the same, retrieving the tiles via the internet instead of having the tiles available offline.
Look here for some B4A code: http://www.b4x.com/forum/additional...s/16309-osmdroid-mapview-b4a-4.html#post96419.

Do you have an image - a map image - that you'd like to cut into tiles and display?
That's more complicated.
You might be able to use MapTiler to cut an image into tiles and then proceed from as above.
MapTiler looks to be able to cut an image into tiles and (importantly) name those tiles according to the slippy tile naming convention.

It's essential that any tiles displayed by OSMDroid be named according to the slippy map tile name convention - there's programs out there that will cut an image into tiles but unless they are 'slippy' named then they won't be useable in OSMDroid.

Martin.
 
Top