Android Question when do apps not sequentially execute instructions

jamesnz

Active Member
Licensed User
Hi,
It seems when I have a function that calls another function that makes a call to a webservice my app does not wait for the completion of this job, instead it moves to subsequent lines of code in the calling function and executes them while the webapi is yet to respond. My debugging didn't catch this because it had plenty of time.

Does this just occur with web jobs ? If I called another function that performed a large loop would the calling function wait, till now I assumed everything was done line by line and the jobdone sub would have to finish before subsequent lines of code were executed

This app worked differently a few years ago, perhaps because it used a built in geocoder

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
'Dim Geocoder1 As Geocoder
Dim VR As VoiceRecognition
Dim TTS1 As TTS
End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.

Dim RadioButtonFastest As RadioButton
Dim RadioButtonShortest As RadioButton
Dim EditTextCurrentAddr As EditText
Dim EditTextDestinationAddr As EditText
Dim ButtonGetDirections As Button

Dim Destination As geocodedLocation
Dim Origin As geocodedLocation
Dim Buttonsentvoice As String = "none"
Dim Mode As String = "shortest"
Dim key As String ="*******************" ' mapquest
Dim OpenRouteAPIKey As String = "******************"
Dim parser As JSONParser

   
    Dim ButtonVoiceCurrentAddr As Button
    Dim ButtonVoiceDestAddr As Button
    Private ButtonDebug As Button
   
    Dim leavereason As String
   
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'load the layout file created with the visual designer.
    If FirstTime Then
    'initialise voice recog and tts
    VR.Initialize("VR")
        TTS1.Initialize("TTS1")
       
    End If
   
    'always Load screen
    Activity.LoadLayout("2GetDirections")
'check if VR is supported
If VR.IsSupported Then
        'ToastMessageShow("Voice recognition is supported.", False)
    Else
        ToastMessageShow("Voice recognition is not supported.", True)
    End If
VR.Prompt = "Number / Street / City/ Country"
Destination.Initialize
Origin.Initialize
Log("end of activity create")
End Sub

Sub Activity_Resume

'If leavereason = "voice" Or leavereason ="geocode" Then
''do nothing
'    Else
'        Log ("running from resume")
'        Findcurrentaddressfromlatlng
'
'End If
End Sub

Sub Activity_Pause (UserClosed As Boolean)
' save stuff here
'leavereason = "sleep"
End Sub



Sub ButtonGetDirections_Click
    Log("get directions click event")
    If Origin.Latitude = 0 Then
         getORIGINlatlng
    End If
   
ButtonGetDirections.text = EditTextCurrentAddr.Text & " " & EditTextDestinationAddr .Text

getdestlatlng

makestringfordirections (Origin , Destination )  '<== EXECUTES THIS BEFORE gestdestlatlng HAS A RESULT

End Sub

Sub LatLngFromAddress( address As String,purpose As String)
   
    ' SENDS AN ADDRESS STRING FOR GEOCODING - returns a lat lng
    Dim job1 As HttpJob
    job1.Initialize("geocodeaddresstolatlng",Me)
    job1.Tag=purpose
   
   
    job1.Download2("https://api.openrouteservice.org/geocode/search",     Array As String("api_key", OpenRouteAPIKey, "text", address))
    Log(job1)
End Sub


Sub Findcurrentaddressfromlatlng
    'if we have gps we use the lat/lng to find the address string and display it to the user
    'run by resume and create
    If Main.LastLatitude <> 0 Then
    AddressfromLatLng(Main.LastLatitude, Main.LastLongitude,"origin")
    EditTextCurrentAddr.Text=""
    EditTextCurrentAddr.Text = Origin.label  
    Else
        Log( "GPS is zero")
        EditTextCurrentAddr.RequestFocus
    End If
   
   
End Sub

Sub getdestlatlng
LatLngFromAddress(EditTextDestinationAddr .Text,"destination")
End Sub

Sub getORIGINlatlng
If EditTextCurrentAddr.Text.Length>3 Then

   
    LocationName2=EditTextCurrentAddr .Text
    LatLngFromAddress(LocationName2,"origin")
    Else
    ToastMessageShow( "in the top box. tell us where you are", True)
  End If
   
End Sub




#End Region
#Region geocoding

#region HttpStuff
'HTTP JOB

Sub AddressfromLatLng( latitude As Float , longitude As Float, purpose As String)
' SENDS LAT/LNG pair for REVERSE GEOCODING - returns an address string
    'leavereason="geocode"
    Dim job1 As HttpJob
    job1.Initialize("ORSCoordinatesToAddress",Me)
    job1.Tag = purpose
    job1.Download("https://api.openrouteservice.org/geocode/reverse?api_key=*********************************&point.lon="& longitude &"&point.lat="& latitude &"boundary.circle.radius=.1&size=2&sources=openstreetmap")
End Sub

Sub  JobDone (job As HttpJob)

Log("tag"&job.Tag)

    If job.Success = True Then
   
        Log(job.GetString)
            If job.Tag ="origin" Or job.Tag="destination" Then
                Dim jp As JSONParser
                jp.Initialize(job.GetString)
                Dim m As Map = jp.NextObject
       
                Dim results As List = m.Get("features")
                Dim bb As List = m.Get("bbox")
                If results.Size > 0 Then
                    Dim first As Map = results.Get(0)
                    Dim geometry As Map = first.Get("geometry")
                    Dim properties As Map = first.Get("properties")
                   
                    'Log("this is the property map"& properties)
                   
                    Dim coordinates As List = geometry.Get("coordinates")
               
                    If job.Tag="origin" Then
                        Origin.latitude= coordinates.Get(1)
                        Origin.Longitude =coordinates.Get(0)
                        Origin.gid=properties.Get("id")
                        Origin.id=properties.Get("gid")
                        Origin.layer=properties.Get("layer")
                        Origin.source=properties.Get("source")
                        Origin.source_id=properties.Get("source_id")
                        Origin.name=properties.Get("name")
                        Origin.housenumber=properties.Get("housenumber")
                        Origin.street=properties.Get("street")
                        Origin.confidence=properties.Get("confidence")
                        If properties.ContainsKey("distance") Then
                        Origin.distance=properties.Get("distance")
                        End If
                        Origin.accuracy=properties.Get("accuracy")
                        Origin.country=properties.Get("country")
                        Origin.country_gid=properties.Get("country_gid")
                        Origin.country_a=properties.Get("country_a")
                        Origin.region=properties.Get("region")
                        Origin.region_gid=properties.Get("region_gid")
                        Origin.region_a=properties.Get("region_a")
                        Origin.county=properties.Get("county")
                        Origin.county_gid=properties.Get("county_gid")
                        Origin.county_a=properties.Get("county_a")
                        Origin.locality=properties.Get("locality")
                        Origin.locality_gid=properties.Get("locality_gid")
                        Origin.continent=properties.Get("continent")
                        Origin.continent_gid=properties.Get("continent_gid")
                        Origin.label=properties.Get("label")
                        Origin.BoundingBox=bb
                        Log("Origin SUCCESFULLY SET = " & Origin)
                       
                    else if job.Tag ="destination" Then
                   
                            Destination.latitude= coordinates.Get(1)
                            Destination.Longitude =coordinates.Get(0)
                             Destination.gid=properties.Get("id")
                            Destination.id=properties.Get("gid")
                            Destination.layer=properties.Get("layer")
                            Destination.source=properties.Get("source")
                            Destination.source_id=properties.Get("source_id")
                            Destination.name=properties.Get("name")
                            Destination.housenumber=properties.Get("housenumber")
                            Destination.street=properties.Get("street")
                            Destination.confidence=properties.Get("confidence")
                            If properties.ContainsKey("distance") Then
                            Destination.distance=properties.Get("distance")
                            End If
                            Destination.accuracy=properties.Get("accuracy")
                            Destination.country=properties.Get("country")
                            Destination.country_gid=properties.Get("country_gid")
                            Destination.country_a=properties.Get("country_a")
                            Destination.region=properties.Get("region")
                            Destination.region_gid=properties.Get("region_gid")
                            Destination.region_a=properties.Get("region_a")
                            Destination.county=properties.Get("county")
                            Destination.county_gid=properties.Get("county_gid")
                            Destination.county_a=properties.Get("county_a")
                            Destination.locality=properties.Get("locality")
                            Destination.locality_gid=properties.Get("locality_gid")
                            Destination.continent=properties.Get("continent")
                            Destination.continent_gid=properties.Get("continent_gid")
                            Destination.BoundingBox=bb
                            Destination.label=properties.Get("label")
                       
                            Log("DESTINATION SUCCESSFULLY SET  = " & Destination)
                    End If
               
                End If
        End If
        job.Release
    Else
        Log("job was an utter failure")
        job.Release
    End If

    job.Release
    Log( "end of job done")
End Sub
#End Region


#End Region

#Region make_strings_for_url_requests
Sub makestringfordirections (Origin1 As geocodedLocation, Destination1 As geocodedLocation)

' Look up the updates to the mapquest api http://open.mapquestapi.com/directions/
Main.mapquesturl ="http://open.mapquestapi.com/guidance/v2/route?key="&Main.mapquestapikey&"&callback=renderAdvancedInformation&outFormat=json&routeType=shortest&narrativeType=text&shapeFormat=raw&generalize=0&generalizeAfter=500&direction=-1&avoidManeuverDuration=-1&unit=k&from="&Origin1.Latitude &","&Origin1.Longitude&"&to="&Destination1.Latitude&","&Destination1.Longitude&"&fishbone=false"
Log(Main.mapquesturl)
'send this to web

'Activity.Finish

End Sub

#End Region
#Region voice

Sub ButtonVoiceDestAddr_Click
    leavereason = "voice"
    VR.Listen 'calls the voice recognition external activity
    Buttonsentvoice = "Destination"
End Sub

Sub ButtonVoiceCurrentAddr_Click
    leavereason = "voice"
    VR.Listen 'calls the voice recognition external activity
    Buttonsentvoice = "Current"
End Sub

Sub VR_Result (Success As Boolean, Texts As List)
    If Success = True Then
        If Buttonsentvoice = "Current" Then
        EditTextCurrentAddr .Text = Texts.get(0)
        ' geocode the new origin address
        getORIGINlatlng
        End If
       
        If Buttonsentvoice = "Destination" Then
        EditTextDestinationAddr .Text = Texts.get(0)
        End If
       
        TTS1.Speak(Texts.get(0), True)
    End If
End Sub
#End Region

Sub determineifOriginNeedsGeocoding () As Boolean
    Dim result As Boolean
   
    If Origin.IsInitialized Then
        Dim l As Location
        l.Initialize2(Main.LastLatitude, Main.LastLongitude)
        Dim O As Location
        O.Initialize2(Origin.Latitude, Origin.Longitude)
        Log("distance  moved since geode, or geocode error is : " & O.DistanceTo(l))
        If (O.DistanceTo(l) > 40) Then
            Log ("weve probably moved from the point we got here with ")
            result = True
        End If
       
    Else
        result= True
    End If
                Return result
End Sub



Sub ButtonDebug_Click
    Findcurrentaddressfromlatlng

End Sub
 
Last edited:

Computersmith64

Well-Known Member
Licensed User
You probably need to do some searching on the forum for topics like Wait For, asynchronous processing, etc...

There are a lot of tasks that use callbacks to handle the result of a function call - eg: pretty much anything where the result is not returned instantaneously - otherwise an app would be stopping & starting, giving the user a very bad experience. A few off the top of my head:

* HTTPJob requests (you knew that one already)
* Database queries
* Calls to Google Play Games Services
* Google Maps
* MsgBoxAsync
* Network sockets

If you can be a bit more specific about the actual issue you are having somebody might be able to help you get it sorted.

- Colin.
 

MarkusR

Well-Known Member
Licensed User

jamesnz

Active Member
Licensed User
The problem is I have a single sub " ButtonGetDirections" that calls two other subs, and those two subs call further subs with web jobs .
I need both of those web jobs to finish so I can use the result of them to construct a string. but even with the wait-for's in place on the webjob the original sub executes the string construction "makestringfordirections " prior to the webjobs finishing
 

MarkusR

Well-Known Member
Licensed User
The problem is I have a single sub " ButtonGetDirections" that calls two other subs, and those two subs call further subs with web jobs .
I need both of those web jobs to finish so I can use the result of them to construct a string. but even with the wait-for's in place on the webjob the original sub executes the string construction "makestringfordirections " prior to the webjobs finishing
i guess u just need one more "wait for" for the sub that contains the web job.
 

jamesnz

Active Member
Licensed User
Yes, this works,
each calling sub, right back to the activating button needs the 'wait for' with the return handled each time
cheers

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.

End Sub

Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim key As String ="888888888888888" ' mapquest
    Dim OpenRouteAPIKey As String = "88888888888888888888888"
    Dim Destination As geocodedLocation
    Dim Origin As geocodedLocation
    Private EditTextOriginAddr As EditText
    Private ButtonGetDirections As Button
    
End Sub

Sub Activity_Create(FirstTime As Boolean)
    'Do not forget to load the layout file created with the visual designer. For example:
    Activity.LoadLayout("Layout1")
    Destination.Initialize
    Origin.Initialize
End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub


Sub determineifOriginNeedsGeocoding () As Boolean
    Dim result As Boolean = True
  
        Dim l As Location
        l.Initialize2(-37.7738616,175.2755251)
        Dim O As Location
        O.Initialize2(Origin.Latitude, Origin.Longitude)
        
        Log("distance  moved since geode, or geocode error is : " & O.DistanceTo(l))
        ' if distance is close then we must have geocoded recently
        If (O.DistanceTo(l) < 40) Then
            Log ("weve probably moved from the point we got here with ")
            result = False
        End If
          
    Return result
End Sub

Sub Findcurrentaddressfromlatlng
'if we have gps we use the lat/lng to find the address string and display it to the user
'run by resume
'If Main.LastLatitude <> 0 Then
If True = True Then
    'AddressfromLatLng(Main.LastLatitude, Main.LastLongitude,"origin")
    AddressfromLatLng(-37.77378, 175.27516,"origin")
    EditTextOriginAddr.Text=""
    EditTextOriginAddr.Text = Origin.label
Else
    Log( "GPS is zero")
    EditTextOriginAddr.RequestFocus
End If
End Sub


Sub ButtonGetDirections_Click
Log("fired get directions click event")
    If Origin.Latitude = 0 Then
        Log("Origin not geocoded, geocoding Origin")
         wait for (getORIGINlatlng) Complete (result As Boolean)
    End If
    
ButtonGetDirections.text = EditTextOriginAddr.Text & " " & "25 Opoia St hamilton NZ "
 wait for (getdestlatlng) complete ( result As Boolean)

makestringfordirections (Origin , Destination )
If Destination.Latitude= 0 Then
    ' geocode any ungeocoded fields
    

    
End If
End Sub


Sub getdestlatlng As ResumableSub
    wait for (LatLngFromAddress("25 opoia rd hamilton new zealand","destination")) Complete (Result As Boolean)
    Return Result
End Sub


Sub getORIGINlatlng As ResumableSub
    EditTextOriginAddr.Text="450 river rd hamilton"
    If EditTextOriginAddr.Text.Length>3 Then

        ' add nz to end of current_address string
        Dim LocationName2 As String
        If EditTextOriginAddr.Text.ToUpperCase.Contains ("NZ") Or  EditTextOriginAddr.Text.ToUpperCase.Contains ("NEW ZEALAND") Then
            Log("contains nz")
        Else
            Log("added nz")
            EditTextOriginAddr.Text = EditTextOriginAddr.Text  & " NZ"
        End If
    
        LocationName2=EditTextOriginAddr .Text
    
        wait for (LatLngFromAddress(LocationName2,"origin")) complete (Result As Boolean)
        Log("result from latlng from address was "& Result)
    Else
        ToastMessageShow( "in the top box. tell us where you are", True)
        ' if we have gps we need to run find address from latlng
    End If
    Return Result
End Sub



Sub LatLngFromAddress( address As String,purpose As String)As ResumableSub
    
    ' SENDS AN ADDRESS STRING FOR GEOCODING - returns a lat lng
    Dim job2 As HttpJob
    job2.Initialize("geocodeaddresstolatlng",Me)
    job2.Tag=purpose
    
    
    job2.Download2("https://api.openrouteservice.org/geocode/search",     Array As String("api_key", OpenRouteAPIKey, "text", address))
    Log(job2)
    
    Wait For (job2) JobDone(job As HttpJob)
    Log("This should be the job "&job)
    If job.Success = True Then
        Log(job.GetString)
        ProcessReturn(job)
    End If
    job.Release
    Return job.Success
End Sub

Sub AddressfromLatLng( latitude As Float , longitude As Float, purpose As String)
' SENDS LAT/LNG pair for REVERSE GEOCODING - returns an address string
    'leavereason="geocode"
    Dim job1 As HttpJob
    job1.Initialize("ORSCoordinatesToAddress",Me)
    job1.Tag = purpose
    job1.Download("https://api.openrouteservice.org/geocode/reverse?api_key=88888888888&point.lon="& longitude &"&point.lat="& latitude &"boundary.circle.radius=.1&size=2&sources=openstreetmap")
    
    Wait For (job1) JobDone(job As HttpJob)
    If job.Success = True Then
    Log(job.GetString)
    ProcessReturn(job)
    job.Release
    End If
    
    End Sub
    
    
    Sub  ProcessReturn (job As HttpJob)

Log("Process return tag"&job.Tag)

    If job.Success = True Then
    
        Log(job.GetString)
            If job.Tag ="origin" Or job.Tag="destination" Then
                Dim jp As JSONParser
                jp.Initialize(job.GetString)
                Dim m As Map = jp.NextObject
        
                Dim results As List = m.Get("features")
                Dim bb As List = m.Get("bbox")
                If results.Size > 0 Then
                    Dim first As Map = results.Get(0)
                    Dim geometry As Map = first.Get("geometry")
                    Dim properties As Map = first.Get("properties")
                    
                    'Log("this is the property map"& properties)
                    
                    Dim coordinates As List = geometry.Get("coordinates")
                
                    If job.Tag="origin" Then
                        Origin.latitude= coordinates.Get(1)
                        Origin.Longitude =coordinates.Get(0)
                        Origin.gid=properties.Get("id")
                        Origin.id=properties.Get("gid")
                        Origin.layer=properties.Get("layer")
                        Origin.source=properties.Get("source")
                        Origin.source_id=properties.Get("source_id")
                        Origin.name=properties.Get("name")
                        Origin.housenumber=properties.Get("housenumber")
                        Origin.street=properties.Get("street")
                        Origin.confidence=properties.Get("confidence")
                        If properties.ContainsKey("distance") Then
                        Origin.distance=properties.Get("distance")
                        End If
                        Origin.accuracy=properties.Get("accuracy")
                        Origin.country=properties.Get("country")
                        Origin.country_gid=properties.Get("country_gid")
                        Origin.country_a=properties.Get("country_a")
                        Origin.region=properties.Get("region")
                        Origin.region_gid=properties.Get("region_gid")
                        Origin.region_a=properties.Get("region_a")
                        Origin.county=properties.Get("county")
                        Origin.county_gid=properties.Get("county_gid")
                        Origin.county_a=properties.Get("county_a")
                        Origin.locality=properties.Get("locality")
                        Origin.locality_gid=properties.Get("locality_gid")
                        Origin.continent=properties.Get("continent")
                        Origin.continent_gid=properties.Get("continent_gid")
                        Origin.label=properties.Get("label")
                        Origin.BoundingBox=bb
                        Log("Origin SUCCESFULLY SET = " & Origin)
                        
                    else if job.Tag ="destination" Then
                    
                            Destination.latitude= coordinates.Get(1)
                            Destination.Longitude =coordinates.Get(0)
                             Destination.gid=properties.Get("id")
                            Destination.id=properties.Get("gid")
                            Destination.layer=properties.Get("layer")
                            Destination.source=properties.Get("source")
                            Destination.source_id=properties.Get("source_id")
                            Destination.name=properties.Get("name")
                            Destination.housenumber=properties.Get("housenumber")
                            Destination.street=properties.Get("street")
                            Destination.confidence=properties.Get("confidence")
                            If properties.ContainsKey("distance") Then
                            Destination.distance=properties.Get("distance")
                            End If
                            Destination.accuracy=properties.Get("accuracy")
                            Destination.country=properties.Get("country")
                            Destination.country_gid=properties.Get("country_gid")
                            Destination.country_a=properties.Get("country_a")
                            Destination.region=properties.Get("region")
                            Destination.region_gid=properties.Get("region_gid")
                            Destination.region_a=properties.Get("region_a")
                            Destination.county=properties.Get("county")
                            Destination.county_gid=properties.Get("county_gid")
                            Destination.county_a=properties.Get("county_a")
                            Destination.locality=properties.Get("locality")
                            Destination.locality_gid=properties.Get("locality_gid")
                            Destination.continent=properties.Get("continent")
                            Destination.continent_gid=properties.Get("continent_gid")
                            Destination.BoundingBox=bb
                            Destination.label=properties.Get("label")
                        
                            Log("DESTINATION SUCCESSFULLY SET  = " & Destination)
                    End If
                
                End If
        End If
        job.Release
    Else
        Log("job was an utter failure")
        job.Release
    End If

    job.Release
    Log( "end of job done")
End Sub


Sub makestringfordirections (Origin1 As geocodedLocation, Destination1 As geocodedLocation)

    ' Look up the updates to the mapquest api http://open.mapquestapi.com/directions/
    Dim mapquesturl As String  ="http://open.mapquestapi.com/guidance/v2/route?key="&key&"&callback=renderAdvancedInformation&outFormat=json&routeType=shortest&narrativeType=text&shapeFormat=raw&generalize=0&generalizeAfter=500&direction=-1&avoidManeuverDuration=-1&unit=k&from="&Origin1.Latitude &","&Origin1.Longitude&"&to="&Destination1.Latitude&","&Destination1.Longitude&"&fishbone=false"
    Log(mapquesturl)
    'send this to web

    'Activity.Finish

End Sub
 
Top