github twitter linkedin email rss
OkHttp 3.X on Android 4.4.4
Feb 27, 2017
2 minutes read

This morning I was greeted at work by an unexpectedly-large number of crashes from a new Android release. As it happens, OkHttp 3.X has issues on Android 4.4.4 and 4.4.2 - it cannot reliably load the system’s default TrustManagers without looping and eventually crashing with an OutOfMemoryError. The fix was simple - we can reliably load it ourselves, and provide it to new OkHttpClient instances. For posterity, the solution we hit on follows below:

TrustManagerFactory tmf;
try {
  String defaultAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
  tmf = TrustManagerFactory.getInstance(defaultAlgorithm);
} catch (NoSuchAlgorithmException e) {
  // The system *just* gave us this algo name :(
  throw new AssertionError(e); // no helping this one.
}

try {
  tmf.init((KeyStore) null); // null == system default keystore
} catch (KeyStoreException e) {
  throw new AssertionError(e); // again, no helping this one.
}

X509TrustManager trustManager = null;
for (TrustManager tm : tmf.getTrustManagers()) {
  if (tm instanceof X509TrustManager) {
    trustManager = (X509TrustManager) tm;
    break;
  }
}

if (trustManager == null) {
  throw new AssertionError("The system is not capable of handling X509 certificates - lol");
}

SSLSocketFactory ssf = (SSLSocketFactory) SSLSocketFactory.getDefault()

// Finally!  With the SSL socket factory and the X509 trust manager,
// we can safely build our HTTP client instance.
OkHttpClient client = new OkHttpClient.Builder()
    .sslSocketFactory(ssf, trustManager) 
    .build();

Of course, you won’t want to do this more than once, but ideally you’re already using a singleton client instance and are reaping the benefits of connection-pooling, a smaller memory footprint, etc.

Hopefully this helps someone - even me, a year from now.


Back to posts