Android Tutorial [B4A] [B4XPages] OSM Maps / FusedLocationProviderClient GMS

May 4, 2024 - Start of tutorial post...

Based on:

The original project was based on the GPS object / lib.. a power hungry outdated feature.
This example uses the latest "Fused" location provider (GMS) to accomplish the same... and more...

This tutorial shall evolve over a (short) time as discoveries are made clear to update / post. Hang in there...
This project also includes an app to feed MOCK locations (lat/lon/etc..) into the FusedLocationProvderGMS - to test your final distribution.

1) B4XPages
Although introduced long time ago - and evolved since then - this is my first introduction. (been busy sowing and harvesting my garden).
The first thing I notice is that B4A (pause and resume) complexities been (essentially) removed! Granted, there are some issues with Show and Hide ( show- B4XPages.ShowPage("destpag") hide - B4XPages.ShowPage("MainPage") but NOTHING that can't be overcome. It is all a matter of understanding what each does - and how each - PAGE - was implemented ( initialized / created / hidden).

For cross platform - (A,i,J), this IS a great leap forward. My focus shall be on B4A, for my ease of explanation...

map1.jpg


All small Red Text are comments.
The Milepost Number and Milepost Name are GPS locations, derived form a SQLlite DB (lat/lon), that are either in front / or behind you depending on your travel direction.
There are much more intricacies to this project, but we shall leave it here for now until more can be defined in a clear and succinct manner.
 
Last edited:

Harris

Expert
Licensed User
Longtime User
Just as a background for the concept of this app...

The Dalton highway is 414 miles starting north of Fairbanks, AK and terminating at the Beaufort sea (in the Arctic -Prudhoe Bay - Deadhorse) - essentially is following the AK pipeline (north and south). This stretch of road (to my understanding) covers many different environments and elevations. These can pose - at any given time - an extreme challenge (wind, snow, fog) for anyone to comprehend to know (blinded) where they are currently at - and where they can safely pull off the road until visual conditions improve.

When this app is proved to be functional, it shall be released to users that can capture important "Points" OTHER THAN what DOT-AK has provided for each Mile Post marker. These are the road side pull outs - for semi's, material sites that can safely accommodate a rig, or any other location that can safely harbor a rig off the main road where other vehicles exist. When other vehicles are trapped within this envelope of blindness, they may (radio) communicate their exact location to warn others of their current location / proximity.

More to follow...
 

Harris

Expert
Licensed User
Longtime User
Fused Location Provider - GMS - Mock Location Provider App
When trying to develop a complex app utilizing Location / GPS functions, it is helpful to implement a method to 'Feed' data to 'simulate' progressive location (Lat / Lon) changes. Fortunately, the Android OS provides functionality to do this - in Development Mode.

<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
Apparently, the above line (in Manifest) defines 'This' app as a Mock Location Provider...

The Manifest of This app:

mock manifest :
'This code will be applied to the manifest file during compilation.
'You do not need to modify it in most cases.
'See this link for for more information: https://www.b4x.com/forum/showthread.php?p=78136
AddManifestText(
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="33"/>
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
<supports-screens android:largeScreens="true"
    android:normalScreens="true"
    android:smallScreens="true"
    android:anyDensity="true"/>)
SetApplicationAttribute(android:icon, "@drawable/icon")
SetApplicationAttribute(android:label, "$LABEL$")
CreateResourceFromFile(Macro, Themes.LightTheme)

AddManifestText(<uses-permission
    android:name="android.permission.WRITE_EXTERNAL_STORAGE"
    android:maxSdkVersion="19" />
)

CreateResourceFromFile(Macro, FirebaseAnalytics.GooglePlayBase)

'End of default text.

In Developer Options, (Android 9.0 +), we see a line to 'Set mock location app'.
I think, this is what the OS uses to determine which apps have the manifest android.permission.ACCESS_MOCK_LOCATION defined within - to allow to set / Feed MOCK.
Screenshot_20240508-170438_Settings[1].jpg

When selecting this option, you choose which app will (potentially) provide MOCK locations - an app that overrides FLP from hardware (GPS chip) lat/lon values with ones that YOU inject (mock) into the underlying stack.
We choose the 'B4A FusedExample' (or whatever you rename it to).

Screenshot_20240508-170452_Settings[1].jpg


Now, whenever this app is broadcasting: Fused.SetMockLocation( mlocation ), the OS will see this as the current LocationF object - (most importantly, lat / lon) and permit it to flow through to other Fused apps expecting this data.

Attention!
The Mock Location MUST be VALID to be accepted by the OS - in order to be passed on... This was my biggest struggle when getting this to work. What I found that it needs to be based on a "real" GPS location to start with, then you can inject / replace "other" lat/lon positions into the object - to allow the system to make it all look real...



WHOOP DE DO BASIL, BUT WHAT DOES IT ALL MEAN? IT SMELLS A BIT NUTTY.... (Austin Powers)

What I discovered was quite meaningful. Feeding mock locations allowed another system (using OSM) to 'Self Populate' a table within a DB to locally store the 'tiles' data required to accompany the (Visual Map) app - using (almost) FREE WIFI rather than EXPENSIVE Cell data plans to get the same data.... The only other way to get the Map Tiles is to Drive the Actual road (assuming it has cell service) to capture this data - WITHOUT resorting to downloading regional data from the (OSM - or other) map tile providers. Doing so can amount to MANY gigs of unwanted tiles (stored data) that you don't need. In my example, the map tile data amounted to more than 800 megabyte of REQUIRED storage to cover the 4 zoom levels provided within the app - for just ONE road (compared to many gig)!


NOTE:
For those of us wishing to EDIT this content, WARNING - Start a new thread ( don't EDIT / UPDATE ). I just did and LOST 1 hour that I must now repeat....

LIVE and LEARN... geeezzzz...
Will start again tomorrow, when I get my enthusiasm back... Thx.
 
Last edited:

Harris

Expert
Licensed User
Longtime User
Mock Location Provider App - continued...

scrn1.png


This app is quite simple.
Open a table and get the UNIQUE route names from it (a unique column).
Init a Spinner with these values. Select ONE.

Determine ASC or DESC for table order (mile post number).
Set Mock Mode (ON or OFF)
Start feeding Mock Locations....

scrn2.png


For each row, the mock location provider will inject the (New Record - Row) Lat / Lon into the system to simulate the current GPS position (using the valid GPS template).
This is where it can get a bit tricky. You need to establish a correct Fused GPS record (NO ?!?) fields in the LocationF object. This is why I hammer on the DefinedFused method to ensure we get one. Otherwise, MOCK will not work (feed these table locations). A clear view of the sky (NOT deep in your Mom's basement) is where you are most likely to get a valid GPS signal.

Image BEFORE Mock... (my current location)

scrn3.png



Image AFTER Mock Enabled ... (Table Record current location). This will repeat a new position for each record in the table (every second).


scrn4.png


As stated, this will allow you to build an OSM tile set without having to drive the actual road... - PROVIDING you have an accurate data set (Milepost Markers - lat/lon) to work from... The Alaska Department of Transportation did a superb job of recording this for my attempt to provide road users with a (free) system to keep everyone safe in time of need.
 
Last edited:

Harris

Expert
Licensed User
Longtime User
Wow! Over 1.5 years since I have updated this post / tutorial... Freakin life priorities gettin in the way... What to do?

Attached is the "Mock Location Provider" App (FusedExample_Harris.zip) I created from original examples.
It "injects MOCK" (GPS) locations into your device (for your dev app) - thus over-riding the real / current GPS system location.
(explained above)...

The database file, in the Files folder (mp.db) contains a short list of locations (Lat/Lon) I was working on.
I created most of these points back in 2015, by recording these locations by actually travelling the road while on-site.

There is another database file included (mp_org.db) that was created by importing a file(s) created by the Alaska DOT. It contains many roads with government recorded Mile Posts Markers! Rename it or code to use it as you wish.

So, what is the point of this - explained again !?

I needed to create an "OFFLINE / locally stored on device" visual map (series of OPEN SOURCE MAPS tiles) of a certain geographic location / route / area (using OSM).

Once you have the data (lat / lon) of a road / area sourced from a provider (USDOT - Alaska) in a table - you can use this data to SAVE "tiles" of a map (PNG segments) to visually to display to users, without burdening resources to get from them internet while driving down a road.

This app injects the mock locations from a table... your other app reacts to the new location (ie. displaying and saving map tiles when required).

The next app shall provide how this works. I used this feeder app to provide my receiver app with maps (local disk) when access to obtain OSM tile downloads that were not available. It saves a DB that contains the tiles you need to display....

Stay tuned...
 

Attachments

  • FusedExample_Harris.zip
    24.1 KB · Views: 13

Cableguy

Expert
Licensed User
Longtime User
Man, what a timing!!!!

I am in early stages of an OSM based app, with many custom layers and line draws... so many thanks for updating this thread!
 

Harris

Expert
Licensed User
Longtime User
The OSM app (AJAK).

The map pics shown above are derived from this app. Below are the libraries required to compile.
AKapp_libs.png


If you have problems sourcing these libs, let me know and I can provide them.
The B4XMap lib (contains a custom view (cvMap) which can display Open Street Map) was sourced from this link:

I have extracted the modules from the lib and include them directly in the project. Many I have modified to suit my specific needs.

The "compassview" lib could be removed since it is only a visual asset - however it does present some interesting technics on how to implement it.

This is one of my first B4XPages apps - so there was much to learn.
For example, B4XPages will only support ONE orientation at startup. What may seem like a deterrent is actually a God send.
No more dealing with pause and resume - and ALL THAT ENTAILS in B4A (Android)!

I develop apps using a Samsung Active 8 inch tablet locked in landscape mode - what my client uses for its' industrial design.
However, this app could be used on any supported Android device in either landscape or portrait mode....
In Main, the following sets "SupportedOrientations" accordingly...


Set Screen:
#SupportedOrientations: unspecified

Sub Activity_Create(FirstTime As Boolean)
    Set_App_Port_or_Land
   
    Dim pm As B4XPagesManager
    pm.Initialize(Activity)
End Sub

Sub Set_App_Port_or_Land
 
    Dim lv As LayoutValues
    lv = GetDeviceLayoutValues
 
    If lv.Height > lv.Width Then  ' Set app Orientation to Portrait
        Log(" set portrait")
        ph.SetScreenOrientation( 1 )
        oro = 1
    Else                           ' Set app Orientation to Landscape
        Log(" set landscape")
        ph.SetScreenOrientation( 0 )
        oro = 0
       
    End If
 
End Sub

More to follow....
 
Last edited:

Harris

Expert
Licensed User
Longtime User
Ok, here is the OSM (AJAK) app. It IS complex (but not for most of you).

It uses the latest FusedLocationProvderGMS - the only one that allows GPS coords (an object) to be injected (Mocked - from the other app) into this app to build a table of map tiles stored locally. Cant say I had fun building it, but it definitely saved me from early onset dementia by keeping my brainwaves active!

Besides responding to MOCK locations, it will also run on its own - creating map (tiles) and storing them locally on your device.
These geographical "maps" (record image blobs) can become a huge device storage consumer.

As in my case, I needed their map data for a particular purpose. A Single Road (or later to find, multiple roads with a region).
This I found I could do - store locally and distribute this specific dataset to many users - without ever having to burden their server for data again ( they ban you from doing this - hammering their server).
Note: I have examined the structure of their "Tiles.db3" and I can in no way say / determine how this works -- to display the correct tile, record (image) when required... Magic.

Special Note:
Now, my immediate task is to display on this map (in view), other vehicles approaching me (or creeping up behind me) from a server that collects location data (via CELL) from each vehicle using this road (and connected / logged in). Not a simple logistic task.

There are several sections that require a deep explanation of how the app reacts (settings for one).

Stay tuned...
 

Attachments

  • B4XMap_AJAK.zip
    82.3 KB · Views: 3
Last edited:
Top