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

miguelm

New Member
Licensed User
Longtime User
Hi Erel and Everybody.

How may I to accessing from B4A to a web service method that resides in a web server?

Example: I am executing in my PC a web service (myService.asmx), and I need to access a particular method of myService.asmx from another application in B4A.

Something like ... CallSub("myService", "myServiceMethod")

Thank you.

Please forgive my english.
 
Last edited:

aminoacid

Active Member
Licensed User
Longtime User
The code you posted is wrong. It doesn't close the output stream so the file might not be complete.
Something like:
B4X:
Dim out As OutputStream
out = File.OpenOutput(File.DirDefaultExternal,"Test.ini",False )
File.Copy2(job.GetInputStream, out)
out.Close
The code you posted is wrong. It doesn't close the output stream so the file might not be complete.
Something like:
B4X:
Dim out As OutputStream
out = File.OpenOutput(File.DirDefaultExternal,"Test.ini",False )
File.Copy2(job.GetInputStream, out)
out.Close

how do you specify the URL
 

boten

Active Member
Licensed User
Longtime User
Trying to do all download HttpJob in a code module

This works: (JobDone sub in Main)
B4X:
Dim Job As HttpJob
Job.Initialize("jobname","main")
Job.Download(url)

But trying to process the result inside the code module does NOT work (JobDone sub in code module)
B4X:
Dim Job As HttpJob
Job.Initialize("jobname","<code-modle-name>")
Job.Download(url)

Is there a way to process the JobDone inside the code module?

unfiltered log is:
B4X:
** Service (httputils2service) Create **
** Service (httputils2service) Start **
GC_FOR_MALLOC freed 3418 objects / 199504 bytes in 43ms
Default buffer size used in BufferedOutputStream constructor. It would be better to be explicit if an 8k buffer is required.
Shutting down VM
threadid=1: thread exiting with uncaught exception (group=0x4001d800)
java.lang.RuntimeException: java.lang.NoSuchFieldException: processBA
   at anywheresoftware.b4a.keywords.Common$5.run(Common.java:960)
   at android.os.Handler.handleCallback(Handler.java:587)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:123)
   at android.app.ActivityThread.main(ActivityThread.java:4627)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:521)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
   at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NoSuchFieldException: processBA
   at java.lang.ClassCache.findFieldByName(ClassCache.java:510)
   at java.lang.Class.getField(Class.java:881)
   at anywheresoftware.b4a.keywords.Common.getComponentBA(Common.java:997)
   at anywheresoftware.b4a.keywords.Common.access$0(Common.java:986)
   at anywheresoftware.b4a.keywords.Common$5.run(Common.java:905)
   ... 9 more
FATAL EXCEPTION: main
java.lang.RuntimeException: java.lang.NoSuchFieldException: processBA
   at anywheresoftware.b4a.keywords.Common$5.run(Common.java:960)
   at android.os.Handler.handleCallback(Handler.java:587)
   at android.os.Handler.dispatchMessage(Handler.java:92)
   at android.os.Looper.loop(Looper.java:123)
   at android.app.ActivityThread.main(ActivityThread.java:4627)
   at java.lang.reflect.Method.invokeNative(Native Method)
   at java.lang.reflect.Method.invoke(Method.java:521)
   at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:868)
   at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:626)
   at dalvik.system.NativeStart.main(Native Method)
Caused by: java.lang.NoSuchFieldException: processBA
   at java.lang.ClassCache.findFieldByName(ClassCache.java:510)
   at java.lang.Class.getField(Class.java:881)
   at anywheresoftware.b4a.keywords.Common.getComponentBA(Common.java:997)
   at anywheresoftware.b4a.keywords.Common.access$0(Common.java:986)
   at anywheresoftware.b4a.keywords.Common$5.run(Common.java:905)
   ... 9 more
  Force finishing activity ...............
 

boten

Active Member
Licensed User
Longtime User
... You have to process JobDone in the same activity that you initialize the Job in.
The code snippets I posted above ARE from the code module. In effect the "working" code calls JobDone in Main. My question still stands
 

boten

Active Member
Licensed User
Longtime User
I'm not making any assumption. I'm stating the facts:
this code :
B4X:
Dim Job As HttpJob
Job.Initialize("jobname","main")
Job.Download(url)

is in the code module

the JobDone sub is in Main

This "combination" works OK

obviously the initialize/download is in one module (code) and the JobDone is in another module (Main).
Still, I'd like to know why the JobDone can not be in code module too?
 

boten

Active Member
Licensed User
Longtime User
I think I got it (Erel can verify this):
Since JobDone is the HttpJob's event and code modules can NOT handle events - hence the problem. :rolleyes:
 

Ramanathan Subbiah

New Member
Licensed User
Longtime User
Hi Erel,
Can you post a sample code which would demonstrate how to connect to a https server, accept the certificates and retrieve the contents. I'm quite confused with HttpUtils, HttpUtils2, Httpjob etc. Is there a sequential way to learn about https and http connections.
 

Ramanathan Subbiah

New Member
Licensed User
Longtime User
HttpUtils is the old version. It is not relevant any more.

Certificates are handled automatically. You don't need to do anything special. Just follow the tutorial in the first post.

Thanks for the reply but, I'm trying to connect to my localhost with an untrusted certificate. I get this error:
Error: javax.net.ssl.SSLPeerUnverifiedException: No peer certificate
I used the steps as in your first post.
 

Erel

B4X founder
Staff member
Licensed User
Longtime User
The correct behavior is to reject unknown certificates unless you (the developer) explicitly configure it to accept all certificates.

Follow these steps:
- Uncheck HttpUtils2 library
- Add HttpUtils2 modules (from the first post)
- Check StringUtils and Http libraries
- Change hc.Initialize in HttpUtils2Service to hc.InitializeAcceptAll
 

Douglas Farias

Expert
Licensed User
Longtime User
erel its possible send a image to host with this lib?
 

Douglas Farias

Expert
Licensed User
Longtime User
can you show me a simple exemple?
to send a image to vps?

to get file your code works fine
B4X:
  'Send a GET request
  job3.Initialize("Job3", Me)
  job3.Download("http://www.b4x.com/forum/images/categories/android.png")

but to send how can i ?

can you show me a simple code to send ?
 
Top