B4A Library OkHttp - Replaces the Http library

OkHttpUtils2 source code: [B4X] OkHttpUtils2 / iHttpUtils2 / HttpUtils2 source code
It is included as an internal library.
Usage: [B4X] OkHttpUtils2 with Wait For

The current Http library is based on the Android version of Apache HttpClient. Google has stopped updating this SDK a long time ago and they are removing it from Android M. This means that it is a good time now to switch to a different implementation.

Note that if you are using HttpUtils2 (as you should) it is also based on Http library.

The OkHttp library is based on the OkHttp SDK: http://square.github.io/okhttp/
As this is a newer SDK it supports new features such as SSL SNI, SPDY, Patch requests and better performance.

The OkHttp wrapper API is almost identical to Http library API. The main difference is that the object names start with Ok (OkHttpClient, OkHttpResponse and OkHttpRequest).

This library requires Android 2.3+.

Attached is a modified version of HttpUtils2 library (v2.12) that is based on OkHttp instead of Http.

If you want to use the new HttpUtils2 library you need to copy it to the internal libraries folder.

V1.01 - Compatible with B4J.
V1.00 - Adds support for digest authentication.

OkHttpUtils2 v2.20 is attached. It adds support for multipart requests.

Example:
B4X:
Dim j As HttpJob
j.Initialize("j", Me)
Dim fd As MultipartFileData
fd.Initialize
fd.KeyName = "file"
fd.Dir = File.DirAssets
fd.FileName = "image.png"
fd.ContentType = "image/png"
j.PostMultipart("http://...", CreateMap("param1": "value1"), Array(fd))

OkHttp and OkHttpUtils2 libraries are included in the IDE.
 
Last edited:

Marco Nissen

Active Member
Licensed User
Longtime User
Starting from android 6 the http lib does not work anymore!
Edit If it is http://www.ravelry.com API which you are using.
Ravelry does support digest authentification additional to OAuth 1.
You should be able to use okhttputils using digest authentification to access this api.

Yes, that is correct. Can you please point me to where there's help about using okhttputils to use digest authentication?
I need to sign always every request .. incl. get & post requests
 

DonManfred

Expert
Licensed User
Longtime User
B4X:
    Dim job As HttpJob
    job.Initialize("Job", Me)
    job.Username = "willi"
    job.Password = "mypassword"
    job.xxx(...)
 

Marco Nissen

Active Member
Licensed User
Longtime User
B4X:
    Dim job As HttpJob
    job.Initialize("Job", Me)
    job.Username = "willi"
    job.Password = "mypassword"
    job.xxx(...)

that won't work
oauth does not use password/username, but through the oauth process, you'll get an accesstoken etc.
so I'll need to have something for that

B4X:
Dim myauth As OAuth 
myauth.Initialize(Main.clientID, Main.clientSecret)
myauth.SetTokenWithSecret(Main.AccessToken, Main.AccessSecret)
myauth.sign(job3)

So I don't see any possibility and am now stuck with a situation where okhttp can't be used with the current oauth1.0 implementation
and no, I can't switch to oauth2.0 (it's not supported, and will not be supported anytime soon)
 

DonManfred

Expert
Licensed User
Longtime User
that won't work
you are right. I just found the following in the okhttputils thread
The following features are currently not available:
- Digest authentication.

So my answer above is not correct. Sorry!
(username and password is "basic authentification")

Edit: So the only solution is to use Api 22 or lower to compile your app i guess
 
Last edited:

Marco Nissen

Active Member
Licensed User
Longtime User
I recommend you to use Http for now (assuming that the web service doesn't support OAuth 2).

Note that it will not be supported immediately with the next version of B4A. It will be possible to then integrate the open source project as the relevant field will be exposed.

Question - since v6.80 I can't use "Debug" anymore, because of httputilservices reporting an issue with process_globals

Release works fine.

I would like to switch to okhttp, but since my server endpoint does not understand oauth2, only oauth1, do you have solution that the oauth1 library is not compatible with this okhttp implementation?

Thanks
Marco
 

pxpto

Member
Licensed User
Longtime User
Hi, where can I download this library so I can use it in my B4A 3.50? I would need a JAR+XML file to put in my \Libraries folder, right?
 

FrankBerra

Active Member
Licensed User
Longtime User
I upgraded to B4a v. 7.01 and suddenly i started to have problems in my app related to somethning like "java.lang.Exception: Sub jobdone was not found.".
So i downloaded the httputils2 in the first post that is supposed to be v. 2.20 but the first line of code module "httpjob" says "HttpUtils2 version 2.01" and first line of httputils2service says "'HttpUtils2 version 2.10 (based on OkHttp library)".
I feel confused: is it normal or should i expect some changes in the code of the library to be compatible to the new features offered by b4a v.7?

I need the library for changhing it's code like this for accepting all SSL cerificates:
B4X:
hc.InitializeAcceptAll("hc")
 
Last edited:

ronell

Well-Known Member
Licensed User
Longtime User
I upgraded to B4a v. 7.01 and suddenly i started to have problems in my app related to somethning like "java.lang.Exception: Sub jobdone was not found.".
So i downloaded the httputils2 in the first post that is supposed to be v. 2.20 but the first line of code module "httpjob" says "HttpUtils2 version 2.01" and first line of httputils2service says "'HttpUtils2 version 2.10 (based on OkHttp library)".
I feel confused: is it normal or should i expect some changes in the code of the library to be compatible to the new features offered by b4a v.7?

I need the library for changhing it's code like this for accepting all SSL cerificates:
B4X:
hc.InitializeAcceptAll("hc")
you already post a thread about this in android question.. and also this is not the right section to post technical question
 

hf

Member
Licensed User
The current Http library is based on the Android version of Apache HttpClient. Google has stopped updating this SDK a long time ago and they are removing it from Android M. This means that it is a good time now to switch to a different implementation.

Note that if you are using HttpUtils2 (as you should) it is also based on Http library.

The OkHttp library is based on the OkHttp SDK: http://square.github.io/okhttp/
As this is a newer SDK it supports new features such as SSL SNI, SPDY, Patch requests and better performance.

The OkHttp wrapper API is almost identical to Http library API. The main difference is that the object names start with Ok (OkHttpClient, OkHttpResponse and OkHttpRequest).

This library requires Android 2.3+.

Attached is a modified version of HttpUtils2 library (v2.12) that is based on OkHttp instead of Http.

If you want to use the new HttpUtils2 library you need to copy it to the internal libraries folder.

V1.01 - Compatible with B4J.
V1.00 - Adds support for digest authentication.

OkHttpUtils2 v2.20 is attached. It adds support for multipart requests.

Example:
B4X:
Dim j As HttpJob
j.Initialize("j", Me)
Dim fd As MultipartFileData
fd.Initialize
fd.KeyName = "file"
fd.Dir = File.DirAssets
fd.FileName = "image.png"
fd.ContentType = "image/png"
j.PostMultipart("http://...", CreateMap("param1": "value1"), Array(fd))

OkHttp and OkHttpUtils2 libraries are included in the IDE.
 

Martin Larsen

Active Member
Licensed User
Longtime User
I have spent several hours the last two days trying to make a SAML authentication work. The exacts same code ported to PHP using cUrl worked fine, but not in B4A.

After much debugging and analyzing with mitmproxy I finally realized that OkHttpUtils2 PostString does not automatically encode the POST parameters. Instead, I had to use StringUtils.EncodeUrl:

B4X:
Dim SU As StringUtils
saml = SU.EncodeUrl(saml, "UTF-8")
j.PostString(url, "SAMLResponse=" & saml)

Then it worked.

After I found the cause of the problems, I realized that I could also use PostMultipart which does not need url encoding:

B4X:
Dim m As Map
m.Initialize
m.Put("SAMLResponse", saml)
j.PostMultipart(url, m, Null)

As far as I know, HttpUtils2 does not need encoding of the POST parameters.

Hopefully, this forum post can save others from wasting a few hours :)
 

Vincenzo Fabiano

Member
Licensed User
Longtime User
B4X:
*** Service (httputils2service) Create ***
Class okhttp3.Dispatcher failed lock verification and will run slower.
Class okhttp3.ConnectionPool failed lock verification and will run slower.
Class okhttp3.ConnectionPool$1 failed lock verification and will run slower.
** Service (httputils2service) Start **
Class anywheresoftware.b4a.B4AThreadPool failed lock verification and will run slower.
Class okhttp3.RealCall failed lock verification and will run slower.
Class okhttp3.internal.connection.StreamAllocation failed lock verification and will run slower.
Class okio.SegmentPool failed lock verification and will run slower.
Class okio.AsyncTimeout$Watchdog failed lock verification and will run slower.
javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
    at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:361)
    at okhttp3.internal.connection.RealConnection.connectTls(RealConnection.java:242)
    at okhttp3.internal.connection.RealConnection.establishProtocol(RealConnection.java:200)
    at okhttp3.internal.connection.RealConnection.buildConnection(RealConnection.java:174)
    at okhttp3.internal.connection.RealConnection.connect(RealConnection.java:114)
    at okhttp3.internal.connection.StreamAllocation.findConnection(StreamAllocation.java:196)
    at okhttp3.internal.connection.StreamAllocation.findHealthyConnection(StreamAllocation.java:132)
    at okhttp3.internal.connection.StreamAllocation.newStream(StreamAllocation.java:101)
    at okhttp3.internal.connection.ConnectInterceptor.intercept(ConnectInterceptor.java:42)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
    at okhttp3.internal.cache.CacheInterceptor.intercept(CacheInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
    at okhttp3.internal.http.BridgeInterceptor.intercept(BridgeInterceptor.java:93)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
    at okhttp3.internal.http.RetryAndFollowUpInterceptor.intercept(RetryAndFollowUpInterceptor.java:120)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:92)
    at okhttp3.internal.http.RealInterceptorChain.proceed(RealInterceptorChain.java:67)
    at okhttp3.RealCall.getResponseWithInterceptorChain(RealCall.java:179)
    at okhttp3.RealCall.execute(RealCall.java:63)
    at anywheresoftware.b4h.okhttp.OkHttpClientWrapper.executeWithTimeout(OkHttpClientWrapper.java:156)
    at anywheresoftware.b4h.okhttp.OkHttpClientWrapper.access$0(OkHttpClientWrapper.java:153)
    at anywheresoftware.b4h.okhttp.OkHttpClientWrapper$ExecuteHelper.run(OkHttpClientWrapper.java:201)
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:428)
    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)
    at java.lang.Thread.run(Thread.java:761)
Caused by: java.security.cert.CertificateException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
    at com.android.org.conscrypt.TrustManagerImpl.checkTrustedRecursive(TrustManagerImpl.java:549)
    at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:401)
    at com.android.org.conscrypt.TrustManagerImpl.checkTrusted(TrustManagerImpl.java:375)
    at com.android.org.conscrypt.TrustManagerImpl.getTrustedChainForServer(TrustManagerImpl.java:304)
    at android.security.net.config.NetworkSecurityTrustManager.checkServerTrusted(NetworkSecurityTrustManager.java:94)
    at android.security.net.config.RootTrustManager.checkServerTrusted(RootTrustManager.java:88)
    at com.android.org.conscrypt.Platform.checkServerTrusted(Platform.java:178)
    at com.android.org.conscrypt.OpenSSLSocketImpl.verifyCertificateChain(OpenSSLSocketImpl.java:596)
    at com.android.org.conscrypt.NativeCrypto.SSL_do_handshake(Native Method)
    at com.android.org.conscrypt.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:357)
    ... 28 more
Caused by: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found.
    ... 38 more
ResponseError. Reason: javax.net.ssl.SSLHandshakeException: java.security.cert.CertPathValidatorException: Trust anchor for certification path not found., Response:
Log reader error: java.io.InterruptedIOException: read interrupted
-1 received
writer error
java.lang.InterruptedException
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.reportInterruptAfterWait(AbstractQueuedSynchronizer.java:2010)
    at java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.await(AbstractQueuedSynchronizer.java:2044)
    at java.util.concurrent.ArrayBlockingQueue.take(ArrayBlockingQueue.java:358)
    at anywheresoftware.b4a.remotelogger.Connector$Writer.run(Connector.java:160)
    at java.lang.Thread.run(Thread.java:761)
Ads received


Solution? :/
 

OliverA

Expert
Licensed User
Longtime User
Looks like the server you are trying to connect to is improperly configured. Solution: Have whoever is in charge of the server configure their SSL configuration properly. BTW, this should probably been opened as a new question in the forum instead of here.

Relevant stackoverflow question: https://stackoverflow.com/questions/6825226/trust-anchor-not-found-for-android-ssl-connection
Relevant stackoverflow answer: https://stackoverflow.com/a/16302527

Please note that the same stackoverflow question has answers that show you how to configure the "client" side to circumvent this problem, but I would advise against it. You are then pretty much circumventing the SSL security issue that is causing this problem in the first place instead of fixing it.
 

Vincenzo Fabiano

Member
Licensed User
Longtime User
Looks like the server you are trying to connect to is improperly configured. Solution: Have whoever is in charge of the server configure their SSL configuration properly. BTW, this should probably been opened as a new question in the forum instead of here.

Relevant stackoverflow question: https://stackoverflow.com/questions/6825226/trust-anchor-not-found-for-android-ssl-connection
Relevant stackoverflow answer: https://stackoverflow.com/a/16302527

Please note that the same stackoverflow question has answers that show you how to configure the "client" side to circumvent this problem, but I would advise against it. You are then pretty much circumventing the SSL security issue that is causing this problem in the first place instead of fixing it.


I would like to, but the server is not mine so i can not make any changes regarding the SSL certificate :) .. Is not it just possible to circumvent this error only from the client?
 

luke2012

Well-Known Member
Licensed User
Longtime User
Hi All,
I have to call a web service, pass to it some data filled by the user than the Web Service store all user data within a server DB.
Note: web service will be developed not by me.

I'm not familiar with web services but I think (in my case) that I have to implement a code like (see belove...).
Than to check if the user data was stored successfully I have to check the web service response using Job.GetString. I'm right ?

B4X:
Sub Activity_Create(FirstTime As Boolean)
       dim job as HttpJob = job.Initialize("Job", Me)
       job.PostString("http://www.targetsite.org/webservice.php", "firstname=John&lastname=Doe")
End Sub

Sub JobDone (Job As HttpJob)
   
    If Job.Success = True Then
        Select Job.JobName
            Case "Job"
                Log(Job.GetString)
        End Select
    Else
        Log("Error: " & Job.ErrorMessage)
    End If
    Job.Release
   
End Sub
 
Top