Android Tutorial HttpUtils2 - Web services are now even simpler

HttpUtils2 was replaced with OkHttpUtils2: https://www.b4x.com/android/forum/threads/okhttp-replaces-the-http-library.54723/
Both libraries are included in the IDE.


HttpUtils2 is a small framework that helps with communicating with web services (Http servers).

HttpUtils2 is an improved version of HttpUtils.

The advantages of HttpUtils2 over HttpUtils are:
  • Any number of jobs can run at the same time (each job is made of a single task)
  • Simpler to use
  • Simpler to modify
  • Supports credentials
  • GetString2 for encodings other than UTF8
  • Download2 encodes illegal parameters characters (like spaces)

HttpUtils2 requires Basic4android v2.00 or above.
It is made of two code modules: HttpUtils2Service and HttpJob (class module).
The two code modules are included in HttpUtils2 (attached project).
It depends on the following libraries: Http and StringUtils

How to use
- Dim a HttpJob object
- Initialize the Job and set the module that will handle the JobDone event.
The JobDone event is raised when a job completes.
The module can be an Activity, Service or class instance. You can use the Me keyword to reference the current module.
Note that CallSubDelayed is used to call the event.
- Call one of the following methods:
Download, Download2, PostString, PostBytes or PostFile. See HttpJob comments for more information.
- Handle the JobDone event and call Job.Release when done.
Note that the completion order may be different than the submission order.

To send credentials you should set Job.UserName and Job.Password fields before sending the request.

For example the following code sends three request. Two of the responses will be printed to the logs and the third will be set as the activity background:
B4X:
Sub Activity_Create(FirstTime As Boolean)
   Dim job1, job2, job3 As HttpJob
   job1.Initialize("Job1", Me)

   'Send a GET request
   job1.Download2("http://www.b4x.com/print.php", _
      Array As String("first key", "first value :)", "second key", "value 2"))

   'Send a POST request
   job2.Initialize("Job2", Me)
   job2.PostString("http://www.b4x.com/print.php", "first key=first value&key2=value2")

   'Send a GET request
   job3.Initialize("Job3", Me)
   job3.Download("http://www.b4x.com/forum/images/categories/android.png")
End Sub

Sub JobDone (Job As HttpJob)
   Log("JobName = " & Job.JobName & ", Success = " & Job.Success)
   If Job.Success = True Then
      Select Job.JobName
         Case "Job1", "Job2"
            'print the result to the logs
            Log(Job.GetString)
         Case "Job3"
            'show the downloaded image
            Activity.SetBackgroundImage(Job.GetBitmap)
      End Select
   Else
      Log("Error: " & Job.ErrorMessage)
      ToastMessageShow("Error: " & Job.ErrorMessage, True)
   End If
   Job.Release
End Sub

This example and an example of downloading several images from Flickr are attached:

flickr_viewer1.png


Starting from B4A v2.70, HttpUtils2 is included as a library in the IDE.

Relevant links

ImageDownloader - Service that makes it simple to efficiently download multiple images. Note that a simpler "FlickrViewer example" is available there.
DownloadService - Download files of any size with DownloadService. Includes progress monitoring and the ability to cancel a download.
 

Attachments

  • FlickrViewer.zip
    10.7 KB · Views: 9,005
  • HttpUtils2.zip
    8.5 KB · Views: 11,268
Last edited:

padvou

Active Member
Licensed User
Longtime User
How do you set the timeout on a request so that jobs don't get stuck?
B4X:
Dim job1 As HttpJob
           job1.Initialize("MyJobName",Me)
      job1.download("http://someurl")
      job1.GetRequest

I changed my code like this:
B4X:
job1.GetRequest.Timeout=3000

Still I'm missing something, since jobs start
and in some "random" point the whole process is stuck..

Seems like at some point Job Done is never reached..
 
Last edited:

padvou

Active Member
Licensed User
Longtime User
Your code looks correct. There are cases when it might take longer for a request to be cancelled. It will happen if the server is responding very slowly.

The process should never be stuck because of waiting requests. How many requests are you submitting?

The requests were about 50.
I tried to send them in stacks of 5 and the procedure seems to work without getting stuck.
Let's suppose that the server responds too slowly or not all, how can I cancel all the requests so that the separate thread is free from this load? is
B4X:
CancelScheduledService(HttpUtils2Service)
correct?
 
Last edited:

padvou

Active Member
Licensed User
Longtime User
Http requests should not have a significant affect on the main thread performance. Stopping the service will not stop the requests.

How do I stop/cancel the requests? I mean like pressing X on a browser.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
It is not simple. You can close the output stream that you pass to Response.GetAsyncshronously.

A simpler solution will be to send the requests one by one (send the next one when the previous completes) and then you can always stop submitting the next request.

Are you sure that the requests are the cause for the problem you encounter? Maybe the server limits the connections.
 

padvou

Active Member
Licensed User
Longtime User
It is not simple. You can close the output stream that you pass to Response.GetAsyncshronously.

A simpler solution will be to send the requests one by one (send the next one when the previous completes) and then you can always stop submitting the next request.

Are you sure that the requests are the cause for the problem you encounter? Maybe the server limits the connections.

You are probably right about the server probably limiting the connections.
About sending the requests one by one, I have not yet figured out away,since the jobrequests are generated by a select query against an sqlite db.
So for now, if there is no other workaround for sending them one by one, I just send batches of 5 requests.
 

GuyBooth

Active Member
Licensed User
Longtime User
Is there a way to determine whether any of the jobs started in an activity are still running? Currently my activity pauses and the jobs continue to run, which is what I want, but when the activity resumes I need to know whether any of the jobs are still running, or if they have all finished.
 

netchicken

Active Member
Licensed User
Longtime User
I want to save data coming down from a net DB as a list.

Solved it.

Two stupid errors
1 the cell phone wasn't connecting through the wifi, wifi had crashed.
2. I wasn't calling the sub that loaded the data to the listivew. sigh .......

Final code left in for anyone


I am updating the program from the HTTP library and this works as my old code
B4X:
Sub HC_ResponseSuccess (Response As HttpResponse, TaskId As Int)

Response.GetAsynchronously("Response", File.OpenOutput(File.DirInternalCache, "temp.txt", False), True, TaskId)
End Sub

Sub Response_StreamFinish (Success As Boolean, TaskId As Int)
   If Success Then
   'open it from the temp file
   reader.Initialize(File.OpenInput(File.DirInternalCache, "temp.txt"))
 lvoutput.Clear ' clear the listview reay for the new data
'readlist returns data as a list, so i pass it to a list and then extract the data out in a loop   
   Dim List1 As List 'make a list, and pass the data to it
    List1 = reader.ReadList
   reader.Close 'close the reader


How do I replicate that in HTTPUtils2?

Looking back through the posts here I get this however jobdone success comes back as false and it times out with connection timeout exception

B4X:
Sub btncallDB_Click
Dim getall As String

getall = "http://dsed.visioncollege.ac.nz/Gary_netdb.php?action=getall"
   
NetDBdownload.Download(getall)
   
ProgressDialogShow("Fetching all data...")
End Sub
'success data comes back stick it in a temp file and pull it out below

Sub JobDone (job As HttpJob)
'this runs when your job has been done, the data all comes back through this common sub. 
   Log("JobName = " & job.JobName & ", Success = " & job.Success)
   If job.Success = True Then 'If the job comes down
      
     Select job.JobName 'get the name of the job AND choose it from the Select statement below
            
         Case "DBGetall"
'pass the data To the Sub below

ProgressDialogShow("Now downloading ...")   
Dim out As OutputStream
out = File.OpenOutput(File.DirInternal,"getall.txt",False )
File.Copy2(job.GetInputStream, out)
out.Close
      End Select
   Else
      Log("Error: " & job.ErrorMessage)
      ToastMessageShow("Error: " & job.ErrorMessage, True)
      ProgressDialogHide
      End If
   job.Release
End Sub
 
Last edited:

MMORETTI964

Member
Licensed User
Longtime User
HttpUtils2 & InitializeAcceptAll -> I haven't found a way to accept SSL certificate home-made with HttpUtils2, the only way was to change source of library to make InitializeAcceptAll in the Service_Create like this:
Sub Service_Create
TempFolder = File.DirInternalCache
hc.InitializeAcceptAll("hc")
TaskIdToJob.Initialize
End Sub

It's possibile to have another parameter to inizialize HttpJob to accept all SSL certificate?
How do you think?
 

imgsimonebiliato

Well-Known Member
Licensed User
Longtime User
Hi Erel,
is HttpUtils2 included in the new versions of B4A or I have to add the 2 modules every time? I am currently using the version 2.52.

Thanks
 

mjtaryan

Active Member
Licensed User
Longtime User
it works next question: How to save file ?

when i download a file wit

jonb1.dowload(filurl)

how to save

this is done with httputil the old one

File.Copy2(httputil.GetInputStream(FileUrl),File.OpenOutput(File.DirDefaultExternal,"Test.ini",False))


how to do that with httpjob.

greets

Doomer


I wrote the following as a test and it works fine -- all the files are read from the URL and saved to the specified file where "PathN" holds the directory "FName" holds the filename. Both PathN and FName are global declared as String.

B4X:
Sub JobDone (Job As HttpJob)
    Dim TempStr As String
    Dim TempImg As Bitmap
    Dim Out As OutputStream
    TempImg.InitializeMutable(200, 200)
    If Job.Success = True Then
        Select Job.JobName
            Case "summary"
                'Save file to DirDefaultExternal
                File.WriteString(PathN, "summary.txt", Job.GetString)
            Case "0", "1", "2", "3"
                TempImg = Job.GetBitmap
                Out = File.OpenOutput(PathN, FName, False)
                TempImg.WriteToStream(Out, 100, "JPEG")
                Out.Close
        End Select
    Else
        ToastMessageShow("Error: " & Job.ErrorMessage, True)
    End If
    Job.Release
End Sub
 

mjtaryan

Active Member
Licensed User
Longtime User
Erel, I've used HttpUtils2 to download and save both plain text files (*.txt) and image files. However, I need to download an html file as well. I tried reading it with Job.GetString but it either it doesn't download or doesn't get written (File.WriteString) to the directory. How do I download this type of file? And what is the best method to use to download any file regardless of type? Thanks.
 

jgbozza

Member
Licensed User
Longtime User
Hello again!

I have a local database inside android with more than 1000 rows. Im using httputils2 to send these registers to a remote server but I'm trying to figure out the best practice to get this done without losing any data.
Im calling the job.poststring several times inside a for..next loop wich is very fast, making no time for the server to respond or might be getting it truncated.
Would be possible to create an array of jobs and release each one correctly only when they have successfully posted the fields to server and have taken the response ? (Or it should be self-destroyed after the timeout, in my case is 30000)
Every job sends a field named "cod" (ie. chk.asp?cod=1&data1=abc&data2=123) and the ASP page returns this cod in order to be sure that the file was captured by the server. The tablet reads the response from job.getstring and delete the local register where cod = job.getstring so every time a post is successful it might be deleted locally.


Any clue?
 
Top