Search code examples
androidhttpsslretrofit

CLEARTEXT communication not supported on Retrofit


I'm trying to connect to https server on android using Retrofit. Here's my OkHttpClient

@Provides
public OkHttpClient provideContactClient(){
  HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor();
  ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.MODERN_TLS)
      .tlsVersions(TlsVersion.TLS_1_2)
      .cipherSuites(CipherSuite.TLS_RSA_WITH_DES_CBC_SHA,
          CipherSuite.TLS_RSA_WITH_AES_128_GCM_SHA256,
          CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256)
      .build();
  interceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
  SSLSocketFactory sslSocketFactory = null;
  try {
    SSLContext sslContext = SSLContext.getInstance("TLS");
    sslContext.init(null, null, null);
    sslSocketFactory = sslContext.getSocketFactory();
  }catch (GeneralSecurityException e){
    e.printStackTrace();
  }
  return new OkHttpClient.Builder()
      .addInterceptor(interceptor)
      .connectionSpecs(Collections.singletonList(spec))
      .sslSocketFactory(sslSocketFactory)
      .authenticator(new Authenticator() {
        @Override
        public Request authenticate(Route route, Response response) throws IOException {
          if(responseCount(response) >= 5){
            return null;
          }
          String credential = Credentials.basic("user", "pass");
          return response.request().newBuilder().header("Authorization", credential).build();
        }
      })
      .build();
}

However I keep getting CLEARTEXT communication not supported: exception

While debugging the RealConnection class I notice route.address() member does not have the sslSocketFactory despite it being assigned in Bulider.


Solution

  • According to Network security configuration

    The guidance in this section applies only to apps that target Android 8.1 (API level 27) or lower. Starting with Android 9 (API level 28), cleartext support is disabled by default.

    Create file res/xml/network_security_config.xml

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <domain-config cleartextTrafficPermitted="true">
            <domain includeSubdomains="true">Your URL(ex: 127.0.0.1)</domain>
        </domain-config>
    </network-security-config>
    

    AndroidManifest.xml

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ...>
        <uses-permission android:name="android.permission.INTERNET" />
        <application
            ...
            android:networkSecurityConfig="@xml/network_security_config"
            ...>
            ...
        </application>
    </manifest>
    

    OR you can directly set in application in manifest like this.

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ...>
        <uses-permission android:name="android.permission.INTERNET" />
        <application
            ...
            android:usesCleartextTraffic="true"
            ...>
            ...
        </application>
    </manifest>