Android Tutorial Google Elevation API Service Code

Hi,

Further to a post I made in another thread. Below is a service code that can be called to get the elevation data from the google API.

B4X:
#Region  Service Attributes 
   #StartAtBoot: False
#End Region

Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Private elevationJob As HttpJob
         
End Sub   
Sub Service_Create
elevationJob.Initialize("elevationJob",Me)
End Sub

Sub Service_Start (StartingIntent As Intent)

End Sub

Sub Service_Destroy

End Sub


Sub getElevationData(url As String) 
elevationJob.Download(url)
End Sub


Sub JobDone (Job As HttpJob)
If Job.Success = True Then
DecodeJsonResponse(Job.GetString)
Else
'Here is some code to handle an error
End If

Job.Release
End Sub


Sub DecodeJsonResponse(jsonResponse As String)

Dim JSON As JSONParser
Dim Map1 As Map
JSON.Initialize(jsonResponse)
Map1 = JSON.NextObject
Dim m As Map 'helper map for navigating
Dim ResultItems As List
ResultItems = Map1.Get("results")
For i = 0 To ResultItems.Size - 1
    m = ResultItems.Get(i)   
Next

'Now show the results. These could be assigned to global variable, saved in ini file etc etc
Log(m.Get("elevation"))
Log(m.Get("resolution"))
End Sub

This can be called from an activity with the following code.

B4X:
'Assign the values to the params required by the API request 
Dim Latitude As Double = 39.73915360
Dim Longitude As Double = -104.98470340
Dim sensor As Boolean = False
Dim url As String  = "http://maps.googleapis.com/maps/api/elevation/json?locations=" & Latitude & "," & Longitude & "&sensor=" & sensor
CallSubDelayed2(getElevationData,"getElevationData",url)

If you have any issues with the code then please let me know and I will attempt to answer any questions. If I get chance today, I will created and post a class that will handle everything :)
 

CaptainJackson

Member
Licensed User
Longtime User
Ok, I got the code working fine.

For half a day I have been wrestling with a different issue.

I make a call to the service twice: once for the first point, and once for the second point.

Using a global Boolean variable, I check whether it is the first time through or the second.

On the first pass, the first_point.altitude = m.get("elevation").
On the second pass, the second_point.altitude = m.get("elevation").

Strangely, though, both points are assigned the same value for altitude.
By logging global values, I can see that code flow is passing through the intended paths of the boolean check and different lat longs are being sent in the url, so I believe that logic is ok.

Both points are several hundred feet difference in elevation.

Is something not getting cleared in the service?
 

dealsmonkey

Active Member
Licensed User
Longtime User
Ok, I got the code working fine.

For half a day I have been wrestling with a different issue.

I make a call to the service twice: once for the first point, and once for the second point.

Using a global Boolean variable, I check whether it is the first time through or the second.

On the first pass, the first_point.altitude = m.get("elevation").
On the second pass, the second_point.altitude = m.get("elevation").

Strangely, though, both points are assigned the same value for altitude.
By logging global values, I can see that code flow is passing through the intended paths of the boolean check and different lat longs are being sent in the url, so I believe that logic is ok.

Both points are several hundred feet difference in elevation.

Is something not getting cleared in the service?

I'll have a look as I was only calling the service once.
 

dealsmonkey

Active Member
Licensed User
Longtime User
Ok, I got the code working fine.

For half a day I have been wrestling with a different issue.

I make a call to the service twice: once for the first point, and once for the second point.

Using a global Boolean variable, I check whether it is the first time through or the second.

On the first pass, the first_point.altitude = m.get("elevation").
On the second pass, the second_point.altitude = m.get("elevation").

Strangely, though, both points are assigned the same value for altitude.
By logging global values, I can see that code flow is passing through the intended paths of the boolean check and different lat longs are being sent in the url, so I believe that logic is ok.

Both points are several hundred feet difference in elevation.

Is something not getting cleared in the service?

I have been able to emulate the issue and have come across this before when using httputils2. When passing several request quickly I am only able to get the last responses .

My solution in other apps has been to resort to using the httpclient directly. Below is a new service module that uses the httpclient.

B4X:
#Region  Service Attributes 
   #StartAtBoot: False
#End Region

Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.   
   Dim hc As HttpClient
   Dim my_buffer As OutputStream   
End Sub

Sub Service_Create
End Sub

Sub getElevationData(url As String, taskID As Int) 
hc.Initialize("hc")
Dim req As HttpRequest
req.InitializeGet(url)
hc.Execute(req,taskID)
End Sub



Sub hc_ResponseSuccess (ResponseData As HttpResponse, TaskId As Int)
my_buffer.InitializeToBytesArray(5000)
'Do Something with the data that is returned.
ResponseData.GetAsynchronously("ServerResponse",my_buffer, True, TaskId)
   
End Sub

Sub hc_ResponseError (ResponseData As HttpResponse, Reason As String, StatusCode As Int, TaskId As Int)
    Log("error: " & ResponseData & " " & StatusCode)
    If ResponseData <> Null Then
        Log(ResponseData.GetString("UTF8"))
        ResponseData.Release
    End If
End Sub


Sub ServerResponse_StreamFinish (Success As Boolean, TaskId As Int)
    If Success Then
    Dim return_buffer () As Byte
       return_buffer = my_buffer.ToBytesArray
   Dim returnData As String = BytesToString(return_buffer, 0, return_buffer.Length, "UTF8")
   
   'Now we must do something with the data that has come back from the api server   
    DecodeJsonResponse(returnData)   
    
    'If it is the last Task then close the service. The value here MUST be the same as the last value passed by the activity
    If TaskId = 2 Then    
    StopService("")    
    End If
        
   End If
      
End Sub
   

Sub DecodeJsonResponse(jsonResponse As String)

Dim JSON As JSONParser
Dim Map1 As Map
JSON.Initialize(jsonResponse)
Map1 = JSON.NextObject
Dim m As Map 'helper map for navigating
Dim ResultItems As List
ResultItems = Map1.Get("results")
For i = 0 To ResultItems.Size - 1
    m = ResultItems.Get(i)   
Next

'Now show the results. These could be assigned to global variable, saved in ini file etc etc
Log("Elevation = " & m.Get("elevation"))
Log("Resolution = " & m.Get("resolution"))

End Sub

Sub Service_Start (StartingIntent As Intent)

End Sub

Sub Service_Destroy

End Sub


Below is the code that needs to be called from your activity. Note that the second value passed to the sub is a teaskID and MUST be unique for each call to the service.

B4X:
 'Assign the values to the params required by the API request 
Dim Latitude As Double =52.7083034
Dim Longitude As Double = -2.7512531
Dim sensor As Boolean = False

Dim url As String  = "http://maps.googleapis.com/maps/api/elevation/json?locations=" & Latitude & "," & Longitude & "&sensor=" & sensor
CallSubDelayed3(getElevationHC,"getElevationData",url,1)

Latitude = 52.580610
Longitude = 2.935611

Dim url As String  = "http://maps.googleapis.com/maps/api/elevation/json?locations=" & Latitude & "," & Longitude & "&sensor=" & sensor
CallSubDelayed3(getElevationHC,"getElevationData",url,2)

I have tried this with the values above and it works fine :)
 

CaptainJackson

Member
Licensed User
Longtime User
dealsmonkey

You've been very helpful. Thank you so much!


I will give the new code a try a little later today after the coffee has kicked in.
 

CaptainJackson

Member
Licensed User
Longtime User
I am stuck at work and you tease me with drinking beer!

Ok, so I tried your code. It works fine for me.

I followed the guide on how to put google maps into an app and did that.

Then added small code for placing markers.

I added a button and put your code in there to call your service. Very simple stuff. That's where the problems begin.

It's almost as if the code speeds along and doesn't wait for the http call to finish before it moves on. I have to press the calculate button 3 or 4 times to get all the values settled. Running in debug, json errors start showing up.

Very frustrating... Spent all day rewriting the code in different ways using variables, ini files, all no help.

My source is attached if you can take a look.

Thanks you
 

Attachments

  • FireBehave - Copy.zip
    64.5 KB · Views: 326

dealsmonkey

Active Member
Licensed User
Longtime User
I am stuck at work and you tease me with drinking beer!

Ok, so I tried your code. It works fine for me.

I followed the guide on how to put google maps into an app and did that.

Then added small code for placing markers.

I added a button and put your code in there to call your service. Very simple stuff. That's where the problems begin.

It's almost as if the code speeds along and doesn't wait for the http call to finish before it moves on. I have to press the calculate button 3 or 4 times to get all the values settled. Running in debug, json errors start showing up.

Very frustrating... Spent all day rewriting the code in different ways using variables, ini files, all no help.

My source is attached if you can take a look.

Thanks you


I'll have a look today for you :)
 
Top