I have an android application (4.4.4+) that uses the following libraries:
compile 'com.squareup.okhttp3:okhttp:3.2.0'
compile 'com.squareup.okhttp3:okhttp-urlconnection:3.2.0'
compile 'com.squareup.okio:okio:1.7.0'
I have nginx (version 1.9.14) compiled with OpenSSL (version 1.0.2g source compiled) usage of openSSL confirmed with nginx -V on centOS 7. Configuration of nginx http2 enabled for the reverse proxy:
server {
listen 443 ssl http2;
ssl on;
server_name mobile.site.com;
ssl_certificate /etc/pki/tls/certs/start_cert.pem;
ssl_certificate_key /etc/pki/tls/certs/start_cert.key;
proxy_cache one;
underscores_in_headers on;
access_log /var/log/nginx/ssl.log ssl_custom;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $remote_addr;
proxy_set_header Host $host;
proxy_cache_bypass $cookie_nocache $arg_nocache $arg_comment;
proxy_pass https://10.10.1.31:443;
}
}
Running command on server:
echo | openssl s_client -alpn h2 -connect
Returns:
No client certificate CA names sent
Peer signing digest: SHA512
Server Temp Key: ECDH, P-256, 256 bits
---
SSL handshake has read 3718 bytes and written 442 bytes
---
New, TLSv1/SSLv3, Cipher is ECDHE-RSA-AES256-GCM-SHA384
Server public key is 4096 bit
Secure Renegotiation IS supported
Compression: NONE
Expansion: NONE
ALPN protocol: h2
Browsing an API URL from any modern browser results an HTTP/2 connection showing in the SSL logs and the HTTP/2 chrome add-in. Assuming HTTP/2 configured correctly in nginx / OpenSSL.
Android OKHttp clients refuse to HTTP/2:
ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
.tlsVersions(TlsVersion.TLS_1_2)
.build();
okHttpClient = new OkHttpClient.Builder()
.followSslRedirects(true)
.protocols(Arrays.asList(Protocol.HTTP_2, Protocol.HTTP_1_1))
.connectionSpecs(Collections.singletonList(spec))
.sslSocketFactory(new TLSSocketFactory((SSLSocketFactory) TLSSocketFactory.getDefault()))
.retryOnConnectionFailure(true)
.connectTimeout(25, TimeUnit.SECONDS)
.connectionPool(new ConnectionPool(30, 120, TimeUnit.SECONDS))
.addInterceptor(new AddCookiesInterceptor())
.addInterceptor(new ReceivedCookiesInterceptor())
.build();
I have written a custom TLS Socket Factory to enable usage of TLS 1.2 on <= Android 4.4.4.
TLSv1.2 does actually work on 4.4.4+ with this custom socket factory, but I have also tried running on 5.0+ with and without the custom socket factory, no HTTP/2 luck.
HTTP/2 fails on kit-kat, lollipop and marshmallow, but works on "N" developer preview (a.k.a. New York Cheesecake). No errors are thrown, just only ever connects as HTTP/1.1. I am having trouble finding any articles that relate to OKhttp and HTTP/2, most help questions / posts just say use ALPN, but with no resources to elaborate on the usage. OkHTTP documentation is not clear on HTTP/2 usages and deployment practices, but the main page says it supports it. Any help or expert guidance would be greatly appreciated, even just a nudge in the right direction would be a huge help. Please let me know if I have missed anything that may help in the process, thanks in advance!
Update 1: I found one of the SO questions that relate to this, with a very vague answer: [SO link] How to use http/2 with Okhttp on Android devices? with a comment that makes a suggestion to use jetty, but only in regards to desktop usage, not Android usage.
Update 2: This article shows that ALPN is enabled with Android 4.4: https://github.com/http2/http2-spec/wiki/ALPN-Status
Update 3: Was able to connect HTTP/2 using +5.0, but not 4.4.4. I don't need to go any lower than 4.4.4, as the in-house target devices are the concern for http/2 and they run 4.4.4. I was able to update the app to use the Google Play Services security protocol as the OKHttp Socket Connection, but the 4.4.4 devices we are using are not Google enabled, so I can't use PlayServices security sockets on these.