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,188
  • HttpUtils2.zip
    8.5 KB · Views: 11,523
Last edited:

Derek Jee

Active Member
Licensed User
Longtime User
Hi there

I am sending multiple PostStrings at once and would like to know when they are all finished and their success status. Is there a way of doing this other than checking as I want to move on to a new activity once they are all successfully completed. Apologies if I need to ask this in a new thread but I think it is ok :)

Kind regards,

Derek.
 

fbritop

Active Member
Licensed User
Longtime User
You should identify each post with a unique "TAG" and add them to a list, depending on the result, Success either true or false, you should release each request identify by the TAG from the list.

Also you can have a timer to periodically inform you of the number of requests still on the queue.

Cheers
Felipe
 

Derek Jee

Active Member
Licensed User
Longtime User
Hi Felipe

Thank you, I guessed as much, so I will have to do as you suggest :)

Best regards,


Derek.
 

Jaime Ramirez

Member
Licensed User
Longtime User
Hi Guys:

I am using this WCF Webservice: (Got this info using fiddler)


POST http://siosnet/PI_TTP/PI_TTP_WCF.svc HTTP/1.1
Content-Type: text/xml; charset=utf-8
SOAPAction: "http://tempuri.org/IPI_TTP_WCF/Get_Tag"
Host: siosnet
Content-Length: 162
Expect: 100-continue
Accept-Encoding: gzip, deflate
Connection: Keep-Alive

<s:Envelope xmlns:s="http://schemas.xmlsoap.org/soap/envelope/"><s:Body><Get_Tag xmlns="http://tempuri.org/"><Tag>SDK_Test_A</Tag></Get_Tag></s:Body></s:Envelope>

With the http library V1.36 All I had to do was this and worked VERY nice:

Sub Cmd_Get_Tag_Click
Dim Url1 As String
Dim requestSoapXML As String

Url1 = "http://xxx.xxx.xxx.xxx/PI_TTP/PI_TTP_WCF.svc"
requestSoapXML = ""
requestSoapXML = requestSoapXML & "<?xml version='1.0' encoding='utf-8'?>"
requestSoapXML= requestSoapXML &"<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'><s:Body><Get_Tag xmlns='http://tempuri.org/'><Tag>C0000000.TTP_SIOS.WT</Tag></Get_Tag></s:Body></s:Envelope>"
requestSoapXML = requestSoapXML.Replace("'", Chr(34))
Weight_WCF_Request.InitializePost2(Url1, requestSoapXML.GetBytes("UTF8"))
Weight_WCF_Request.SetHeader("Content-Type", "text/xml; charset=utf-8")
Weight_WCF_Request.SetHeader("SOAPAction", "http://tempuri.org/IPI_TTP_WCF/Get_Tag")
Weight_WCF_Request.Timeout = 10000
webClient.Initialize("webClient")
If webClient.Execute(Weight_WCF_Request, 1) = False Then Return
End Sub

Sub webClient_ResponseSuccess (Response As HttpResponse, TaskId As Int)
Dim resultSoapXML As String

resultSoapXML = Response.GetString("UTF8")
Lbl_Weight_Data.Text = xmlGetTagContent(resultSoapXML,"Get_TagResult") & " Kgs"

End Sub


However with the Httputils2 v2.01 I just can not figure out how to set the header and all those parameters and my app keeps getting me a utf format error or something, Any Ideas?

Jaime
 

Jaime Ramirez

Member
Licensed User
Longtime User
Erel:

Thank you for you prompt reply. You were right, if I do what is described in that post the webservice request works just fine, however the old way was more logical:

First you set all required parameter then you webClient.Execute.

Now is not that clear when the WCF is really requested:

Dim htJob As HttpJob
Dim Url1 As String
Dim requestSoapXML As String

Url1 = "http://xxx.xxx.xxx.xxx/PI_TTP/PI_TTP_WCF.svc"
requestSoapXML = ""
requestSoapXML= requestSoapXML &"<s:Envelope xmlns:s='http://schemas.xmlsoap.org/soap/envelope/'><s:Body><Get_Tag xmlns='http://tempuri.org/'><Tag>C0000000.TTP_SIOS.WT</Tag></Get_Tag></s:Body></s:Envelope>"
requestSoapXML = requestSoapXML.Replace("'", Chr(34))
Log(requestSoapXML)
htJob.Initialize("htJob", Me)
htJob.PostString(Url1, requestSoapXML)
'Added this line below
htJob.GetRequest.SetHeader("SOAPAction", "http://tempuri.org/IPI_TTP_WCF/Get_Tag")
htJob.GetRequest.SetContentType("text/xml; charset=utf-8")

Thanks

Jaime
 

svk123

Member
Licensed User
Longtime User
This is a great library. Should i manually stop or worry about httputils2service which keeps running after Job.Release or is it a property of httputils2service to run continuously. Will it affect the performance of the phone if it keeps running?
 

winjiadh

Active Member
Licensed User
Longtime User
erel,I download you sample
I want use it to login in a web
like "http://new.28lottery.com"
B4X:
Sub Globals
    'These global variables will be redeclared each time the activity is created.
    'These variables can only be accessed from this module.
    Dim WebView1 As WebView
    Dim txtusername,txtpassword As EditText
    Dim job3 As HttpJob
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("1")
    WebView1.LoadUrl("http://new.28lottery.com")
   
   

End Sub

Sub Activity_Resume

End Sub

Sub Activity_Pause (UserClosed As Boolean)

End Sub



Sub Button1_Click
    job3.Initialize("Job3", Me)
    job3.Username =txtusername.Text
    job3.Password =txtpassword.Text
    job3.Download("http://new.28lottery.com/admin/login")
'    job3.PostString("http://new.28lottery.com/admin/login","username="&txtusername.Text&"password="&txtpassword.Text )
   
End Sub

Sub JobDone (Job As HttpJob)
    If Job.Success =True Then
    WebView1.LoadUrl("http://new.28lottery.com/page/agree")
    'WebView1.LoadUrl("http://new.28lottery.com/lottery/index")
    WebView1.Visible =True
    End If

End Sub
but the poststring and the download can't work,I add the zip file,need you help
 

Attachments

  • weblogin.zip
    10.1 KB · Views: 457

winjiadh

Active Member
Licensed User
Longtime User
I cannot read anything on this site but i see a Captcha. How are you knowing the captchavalue to give this value in the loginrequest too?
if you use the mobile open the site,you can only use the name and password
I need a app , and weblogin
thanks
 

Martin Larsen

Active Member
Licensed User
Longtime User
What is the best way to download a large number of urls in turn?

I load a series of urls with a JSON request. Each of these urls (can be hundreds) will download some JSON data to be parsed as the are fetched. Since I don't know the number of jobs beforehand I can't just declare that many jobs. So how do I handle all these dynamically generated jobs so they are not mixed up?

Also, is there a way to see if a job is finished or still running without maintaning a flag?
 
Last edited:

Erel

B4X founder
Staff member
Licensed User
Longtime User
Downloading hundreds of urls will be slow. Consider a different approach.

You don't need to know the number of jobs beforehand.
You can use a process global Map to track all the jobs:
B4X:
For i = 0 to 1000
 'read data to find job information
 Dim j As HttpJob
 j.Initialize(Me, "job" & i)
j.Tag = ... 'you can use to store additional information
 MapOfRunningJobs.Put(j, "")
 j.Download(...)
Next

Later in JobDone:
B4X:
MapOfJobs.Remove(job)
 

Martin Larsen

Active Member
Licensed User
Longtime User
Downloading hundreds of urls will be slow. Consider a different approach.
I know, but it is only on first run of the app. It's a TV Guide app and I dont have control of the JSON data. Only other option would be to make a webservice myself that aggregates the data from the 124 requests (one for each channel) and send it as one big JSON object. This is something I consider, but my initial tests show that my current setup will work ok.

Later on it is only the user's selected channels that will be fetched, probably 10-15 or so.

You don't need to know the number of jobs beforehand.
You can use a process global Map to track all the jobs:

The jobs should run sequentially and if I understand your code correctly, I don't have control of the other the downloads are done.

you can use a "queue" to handle one job after another instead of starting hundrets of them the same time.

I actually ended up with something myself, similar to your example. At the end of JobDone I start the next download etc. This seems to work ok.
 

kalmen

Member
Licensed User
Longtime User
Hi ,

Where can i download the source for B4A HttpUtil2 , i downloaded B4J, and compiled it ,
i need to make hc.Initialize("hc") to hc.InitializeAcceptAll("hc") at the initialize , or else
my project at B4A , will run but hit error , where i am accessing https.

Since we all need a common testing lib , will that be possible for httpUtil2 lib to add
the InitializeAcceptAll for accepting all certificate during testing ?

Thanks.
Kalmen
 

Martin Larsen

Active Member
Licensed User
Longtime User
A few questions:

1.
Is there a way to download just a small snippet from a webserver, return the string and then continue?

I am looking for something like file_get_contents($url) in PHP. It's about 20-30 bytes so it's nothing.

I know I can download the string with this library, but it seems overkill for the purpose.

2.
How can I get the response status code afte returning from a job with httputils2 (200, 301, 404 etc) ?

3.
Are cookies maintained between jobs? I need to login to a site with Job.PostString and later get some data using Job.Download, but it doesn't seem to work as a get the error message "forbidden" for the download. So I wonder if cookies are maintained.
 
Last edited:

DonManfred

Expert
Licensed User
Longtime User
I am looking for something like file_get_contents($url) in PHP. It's about 20-30 bytes so it's nothing.
filegetcontents does get the COMPLETE htmlcode from this url. Not just a part of it!

2.
How can I get the response status code afte returning from a job with httputils2 (200, 301, 404 etc) ?
you need to use a httpclient and extract the info... httputils does not return it

3.
Are cookies maintained between jobs?
if you get the cookie at first call and set it in the header when doing a next call. Yes. Here you need to use httpclient to to get the cookie
Search forum.. this is handled a lot of times
 
Top