Example of using a Conscrypt-based OkHttpClient
with Cobrowse SDK
Copy dependencies {
...
implementation 'org.conscrypt:conscrypt-android:2.5.3'
}
Copy /**
* Builder of custom {@link OkHttpClient} which supports TLS v1.2 and TLS v1.3 on older platforms.
*/
public class ModernTlsOkHttpClient {
private static final String TAG = "ModernTlsOkHttpClient";
private static class ReusableSingleton {
private static final OkHttpClient INSTANCE = create();
private static final Provider CONSCRYPT = Conscrypt.newProvider();
}
private ModernTlsOkHttpClient() {
}
/**
* Returns an app-wide reusable {@link OkHttpClient} instance.
*/
public static OkHttpClient reuse() {
return ReusableSingleton.INSTANCE;
}
/**
* Returns an app-wide reusable {@link Provider} instance from Conscrypt.
*/
public static Provider conscrypt() {
return ReusableSingleton.CONSCRYPT;
}
/**
* Creates a new {@link OkHttpClient} instance.
*/
public static OkHttpClient create() {
OkHttpClient.Builder builder = new OkHttpClient.Builder()
.pingInterval(60, TimeUnit.SECONDS)
.connectTimeout(2000, TimeUnit.MILLISECONDS);
return enableModernTls(builder).build();
}
@NonNull
private static OkHttpClient.Builder enableModernTls(@NonNull OkHttpClient.Builder client) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
// No modifications on Android 10+
return client;
}
try {
X509TrustManager tm = Conscrypt.getDefaultX509TrustManager();
SSLContext sslContext = SSLContext.getInstance("TLS", conscrypt());
sslContext.init(null, new TrustManager[] { tm }, null);
client.sslSocketFactory(new ModernTlsSocketFactory(sslContext.getSocketFactory()), tm);
} catch (Exception e) {
Log.e(TAG, "Error while setting TLS", e);
}
return client;
}
}
Copy /**
* Enables TLS v1.2 and TLS v1.3 when creating SSLSockets.
* <p/>
* Android supports TLS v1.2 from API {@link Build.VERSION_CODES#JELLY_BEAN}, but enables it
* by default only from API {@link Build.VERSION_CODES#LOLLIPOP}.TLS v1.3 is enabled only
* from API {@link Build.VERSION_CODES#Q}.
*
* @link https://developer.android.com/reference/javax/net/ssl/SSLSocket.html
* @see SSLSocketFactory
*/
public final class ModernTlsSocketFactory extends SSLSocketFactory {
private static final String[] TLS_12_AND_13_ONLY = new String[] {"TLSv1.2", "TLSv1.3"};
private final SSLSocketFactory delegate;
public ModernTlsSocketFactory(SSLSocketFactory sslSocketFactory) {
delegate = sslSocketFactory;
}
@Override
public String[] getDefaultCipherSuites() {
return delegate.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return delegate.getSupportedCipherSuites();
}
@Override
public Socket createSocket() throws IOException {
return enableTLSOnSocket(delegate.createSocket());
}
@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose)
throws IOException {
return enableTLSOnSocket(delegate.createSocket(s, host, port, autoClose));
}
@Override
public Socket createSocket(String host, int port) throws IOException {
return enableTLSOnSocket(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
throws IOException {
return enableTLSOnSocket(delegate.createSocket(host, port, localHost, localPort));
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
return enableTLSOnSocket(delegate.createSocket(host, port));
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
throws IOException {
return enableTLSOnSocket(delegate.createSocket(address, port, localAddress, localPort));
}
private Socket enableTLSOnSocket(Socket socket) {
if (socket instanceof SSLSocket) {
((SSLSocket) socket).setEnabledProtocols(TLS_12_AND_13_ONLY);
}
return socket;
}
}
Copy @Override
public void onCreate() {
super.onCreate();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) {
Security.insertProviderAt(ModernTlsOkHttpClient.conscrypt(), 1);
}
...
}
Copy CobrowseIO.instance().okHttpClient(ModernTlsOkHttpClient.reuse());
CobrowseIO.instance().start();