Android Question Httputils2 with multiple requests

jgbozza

Member
Licensed User
Longtime User
Hello,

I have a local database (SQLite) capturing GPS coordinates from time to time. When the user is whether close to its WiFi router or have 3G reception I call a service to make the batch process of posting each pair of coordinates to the server and the asp page returns a number previously posted by the tablet that is the the key of the register inside the SQLite database, so the android knows that the data has been successfully posted to the server and now it can be deleted locally where cod = job.getstring.

Below there's the structure, not actually the real code.
B4X:
job.Initialize("Job", Me)



for i = 0 to recordset.rowcount - 1
rs.position = i
job.PostString("192.168.0.1/check.asp?", "lat=" & rs.getstring("lat") & "&lng=" & rs.getstring("lng") & "cod=" & rs.getstring("cod") -- rs is the record set from a select * from table
next


If Job.Success = True then
   If Job.Jobname = "Job" then
      SQL.ExecuteNonQuery ("DELETE FROM table WHERE cod = " & job.getstring)
  end if
end if

The problem is that I might have more than 400 registers to be posted one by one in order to populate the database in the server side but I cannot handle these requests correctly which cause the android to post 400 registers in a row without the response from the server.

Is there a way to create something like a job array or handle the independently ?

Thanks in advance!
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
There is somewhere a library with which you can make things like an queue, a stack...

1. Build a stack/queue with - maybe ids in the database of positions which have to be transfered.
2. Then you start the job after you get the first item of your queue...
3. In JobDone you remove that item from the queue.
4. Exit your batch if queue is empty.
5. If queue is not empty go back to 2
 
Upvote 0

DonManfred

Expert
Licensed User
Longtime User
As a simple solution to be used as queue you can use a simple listview. write the location in the items along with the database-id in the TAG of each item. in jobdone you remove that item or mark it as transfered... like a queue you can iterate throu the items, sending http-reuests for each item. and in jobdone you mark an entry transfered or delete it, what ever... A Listbox has the sideeffects that you can see what happening (one position after the other are delteted from "queue" :)
 
Upvote 0

jgbozza

Member
Licensed User
Longtime User
DonManfred, I got your point, thanks for helping but my problem is not building a stack since the recordset has all the items that I need. I can navigate thru them using rs.position (SQL).
My concern is how should I start a job #1, wait untill it get done and then start the job #2 and so on.
The way I did turns out into several posts in a short time without getting any response from the server and in the other side the posts are not getting completed so the server won't have enough time to read the information and run the script effectively.

Any idea?
 
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Seems to me that a better option will modify the server and allow sending multiple coordinates at once.

However if you want to send the coordinates one after another then:
- Create a List with the data you want to sent.
- Send List.Get(0) and remove it from the list.
- In JobDone check whether the size of List is larger than 0.
- If yes then submit the next job (List.Get(0)) and remove if from the list.
 
Upvote 0

beni_feld

Member
Licensed User
Longtime User
If you do not want to mess with lists.
Another option although not most efficient is to limit the SELECT to one record at a time, send data to server, wait for "JobDone" , delete record from DB , select one record again and continue process until table is empty .

BN
 
Last edited:
Upvote 0

jgbozza

Member
Licensed User
Longtime User
I got it friends...I'm just in doubt on how to call a job after the previous is done. Should use job.postring inside the job done sub and use it recursively until I got all registers in database posted ? Is anywhere I can find a piece of code?
Erel, you said that would be better sending all registers once, do you mean using something like XML or Json ?

Thanks.
 
Upvote 0

jgbozza

Member
Licensed User
Longtime User
Here is the code:

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Dim latitude, longitude, nome, dt, str, cod As String
    Dim i As Int
    Dim SQL1 As SQL
End Sub
Sub Service_Create
    SQL1.Initialize(File.DirDefaultExternal, "bd.db", True)
End Sub

Sub Service_Start (StartingIntent As Intent)
    Main.tem_lastcall = False //
    Dim rs As Cursor
    rs = SQL1.ExecQuery("SELECT * FROM last_call")
    If rs.RowCount <= 0 Then
          Main.tem_lastcall = False // FOR THE PROGRAM TO KNOW THAT THERE IS NO REGISTERS LEFT IN THE DATABASE
          StopService("")
    Else
        grava_lastcall_remoto // CALL THE SUBROUTINE
    End If
    rs.Close
End Sub
Sub grava_lastcall_remoto
    i = i + 1
    Dim rs As Cursor
    rs = SQL1.ExecQuery ("SELECT * FROM last_call")
    If rs.RowCount > 0 Then
    rs.Position = 0
            latitude = rs.GetString("latitude")
            longitude = rs.GetString("longitude")
            nome = rs.GetString("operador")
            cod = rs.GetString("cod")
            DateTime.DateFormat = "dd/MM/yyyy"
            dt = DateTime.date ( rs.GetString("data") )
            dt = dt & "%20"
            dt = dt & DateTime.Time ( rs.GetString("data") )
            str = "latitude=" & latitude & "&longitude=" & longitude & "&operador=" & nome & "&data=" & dt & "&cod=" & cod & "&tag_comboio=CB1"
           Dim job As HttpJob
            job.Initialize("job_lastcall"&i, Me)
            job.PostString(Main.IP & "cb_remoto_lastcall.asp?",str)
    Else
            StopService("")
    End If
    rs.Close
End Sub

Sub JobDone (job As HttpJob)
    If job.JobName = "job_lastcall"&i Then
        If job.Success = True Then
           Log ("index " & i)
            Log("getstring " & job.GetString)
                Dim codx = job.GetString
                job.Release
                SQL1.ExecNonQuery("DELETE FROM last_call WHERE cod = '" & codx & "'")
                grava_lastcall_remoto // CALL THE SUBROUTINE AGAIN THAT CALLS THE JOB WITH A NEW REGISTER
        Else
            Main.server_ok = False
            job.Release
            Main.tem_lastcall = True
            i = 0
            StopService("")
        End If    
    End If
End Sub
Sub Service_Destroy
      CancelScheduledService ("")
    StopService("")
End Sub


Sometimes it post a specific register more than once, specially when other services comes up calling other jobs. How to go around it and certify that one job is done prior to call the next one ?
 
Last edited:
Upvote 0

Erel

B4X founder
Staff member
Licensed User
Longtime User
Please use [ code ] [ /code ] tags (without spaces) when posting code.

Erel, you said that would be better sending all registers once, do you mean using something like XML or Json ?
Yes. Or any other format you like.

See the steps I previously posted about sending the next job when the previous one completes.
 
Upvote 0

jgbozza

Member
Licensed User
Longtime User
Erel,
I've done this list-type algorithm but sometimes it ends up losing some register os posting it twice.
I believe that the best practice would be using something I could parse at the other end like xml or json.
Do you know if there's a restriction on the amount of bytes to send over a single XML file to be read by an ASP script ?

Anyway, thanks for helping
 
Upvote 0

jgbozza

Member
Licensed User
Longtime User
Thank you DonManfred. I have just written the server-side parser and tomorrow I'll work on the android side. Will limit the number of bytes in less than 64Kb to avoid problems.
 
Upvote 0

raphaelcno

Active Member
Licensed User
Longtime User
Below there's the structure, not actually the real code.
B4X:
job.Initialize("Job", Me)


for i = 0 to recordset.rowcount - 1
rs.position = i
job.PostString("192.168.0.1/check.asp?", "lat=" & rs.getstring("lat") & "&lng=" & rs.getstring("lng") & "cod=" & rs.getstring("cod") -- rs is the record set from a select * from table
next


If Job.Success = True then
   If Job.Jobname = "Job" then
      SQL.ExecuteNonQuery ("DELETE FROM table WHERE cod = " & job.getstring)
  end if
end if

The problem is that I might have more than 400 registers to be posted one by one in order to populate the database in the server side but I cannot handle these requests correctly which cause the android to post 400 registers in a row without the response from the server.

Is there a way to create something like a job array or handle the independently ?

Hello,

I know this is an old thread, but other people may have a similar question in the future.
The problem in the code above seems to be that you have "Dim job" and "job.Initialize" before the For-Next loop.
You should write these lines inside the loop, so you initialize one job for each request:

B4X:
'job.Initialize("Job", Me)  ' <== Remove


for i = 0 to recordset.rowcount - 1
   rs.position = i
   Dim job As HttpJob  ' <== New
   job.Initialize("Job", Me)  ' <== New
   job.PostString("192.168.0.1/check.asp?", "lat=" & rs.getstring("lat") & "&lng=" & rs.getstring("lng") & "cod=" & rs.getstring("cod") -- rs is the record set from a select * from table
next


If Job.Success = True then
   If Job.Jobname = "Job" then
      SQL.ExecuteNonQuery ("DELETE FROM table WHERE cod = " & job.getstring)
  end if
end if

I hope this can help.
 
Upvote 0

jgbozza

Member
Licensed User
Longtime User
I apreciate your concern but I resolved this issue a long time ago! Anyone who faces the same problem can ask for help if they need!
 
Upvote 0
Top