title: How to solve javax.net.ssl.SSLHandshakeException Error without Google Play Services installed?
body: <p>I am working on radio app using Exoplayer.
  In case of <a href="https://audio.simplecast.com/b07b19ee.mp3" rel="nofollow noreferrer">this</a> podcast the Exoplayer throws SSLHandshakeException.</p>
  
  <p>To fix this I tried:</p>
  
  <p><strong>1. Update security provider with Provider installer by calling</strong> <code>ProviderInstaller.installIfNeededAsync</code>.</p>
  
  <pre><code>    public class MainActivity extends Activity
      implements ProviderInstaller.ProviderInstallListener {
  
      private static final int ERROR_DIALOG_REQUEST_CODE = 1;
  
      private boolean mRetryProviderInstall;
  
      //Update the security provider when the activity is created.
      @Override
      protected void onCreate(Bundle savedInstanceState) {
       super.onCreate(savedInstanceState);
       ProviderInstaller.installIfNeededAsync(this, this);
      }
  
      /**
       * This method is only called if the provider is successfully 
      updated (or is already up-to-date).
       */
      @Override
      protected void onProviderInstalled() {
       // Provider is up-to-date, app can make secure network calls.
      }
  
      /**
      * This method is called if updating fails; the error code indicates
      * whether the error is recoverable.
      */
      @Override
      protected void onProviderInstallFailed(int errorCode, Intent recoveryIntent) {
        GoogleApiAvailability availability = GoogleApiAvailability.getInstance();
      if (availability.isUserRecoverableError(errorCode)) {
        // Recoverable error. Show a dialog prompting the user to
        // install/update/enable Google Play services.
        availability.showErrorDialogFragment(
            this,
            errorCode,
            ERROR_DIALOG_REQUEST_CODE,
            new DialogInterface.OnCancelListener() {
              @Override
              public void onCancel(DialogInterface dialog) {
                // The user chose not to take the recovery action
                onProviderInstallerNotAvailable();
              }
            });
      } else {
        // Google Play services is not available.
        onProviderInstallerNotAvailable();
      }
    }
  
      @Override
      protected void onActivityResult(int requestCode, int resultCode,
        Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (requestCode == ERROR_DIALOG_REQUEST_CODE) {
          // Adding a fragment via GoogleApiAvailability.showErrorDialogFragment
          // before the instance state is restored throws an error. So instead,
          // set a flag here, which will cause the fragment to delay until
          // onPostResume.
          mRetryProviderInstall = true;
        }
      }
  
      /**
       * On resume, check to see if we flagged that we need to reinstall the provider.
       */
      @Override
      protected void onPostResume() {
        super.onPostResume();
         if (mRetryProviderInstall) {
          // We can now safely retry installation.
          ProviderInstaller.installIfNeededAsync(this, this);
        }
        mRetryProviderInstall = false;
      }
  
      private void onProviderInstallerNotAvailable() {
        // This is reached if the provider cannot be updated for some reason.
        // App should consider all HTTP communication to be vulnerable, 
        // and take appropriate action.
      }
    }
  </code></pre>
  
  <p><strong>2. Replace https to http</strong></p>
  
  <p>In this case, Exoplayer throws an Exception with error code 308 (redirection exception).</p>
  
  <p><strong>3. Use NetCipher</strong> instead of HttpUrlConnection by calling <code>HttpsURLConnection connection = NetCipher.getHttpsURLConnection(sourceUrl)</code> like described <a href="https://stackoverflow.com/questions/26649389/how-to-disable-sslv3-in-android-for-httpsurlconnection/32466614#32466614">here</a></p>
  
  <p><strong>4. Use NoSSLv3SocketFactory</strong> like described <a href="https://stackoverflow.com/questions/29916962/javax-net-ssl-sslhandshakeexception-javax-net-ssl-sslprotocolexception-ssl-han/30302235#30302235">here</a></p>
  
  <p><strong>5. Disable SSL certificate Checking</strong> by calling</p>
  
  <pre><code> private static void disableSSLCertificateChecking() {
    TrustManager[] trustAllCerts = new TrustManager[] { new X509TrustManager() {
    public X509Certificate[] getAcceptedIssuers() {
    return null;
   }
  
   @Override
   public void checkClientTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
    // Not implemented
   }
  
   @Override
   public void checkServerTrusted(X509Certificate[] arg0, String arg1) throws CertificateException {
   // Not implemented
   }
   } };
  
    try {
    SSLContext sc = SSLContext.getInstance("TLS");
  
    sc.init(null, trustAllCerts, new java.security.SecureRandom());
  
    HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
    } catch (KeyManagementException e) {
    e.printStackTrace();
    } catch (NoSuchAlgorithmException e) {
    e.printStackTrace();
    }
   }
  </code></pre>
  
  <p><strong>6. Create <a href="https://github.com/square/okhttp/blob/master/samples/guide/src/main/java/okhttp3/recipes/CustomTrust.java" rel="nofollow noreferrer">customTrust</a></strong> </p>
  
  <p>To get certificates I run the open ssl command:</p>
  
  <pre><code>OpenSSL&gt; s_client -connect simplecast.com:443
  </code></pre>
  
  <p><strong>7. Download the .crt file</strong> from <a href="https://crt.sh/?q=simplecast.com" rel="nofollow noreferrer">here</a> and as Google suggests run</p>
  
  <pre><code>    CertificateFactory cf = CertificateFactory.getInstance("X.509");
      InputStream caInput = new BufferedInputStream(new 
      FileInputStream("my_downloaded.crt"));
      Certificate ca;
       try {
         ca = cf.generateCertificate(caInput);
         System.out.println("ca=" + ((X509Certificate) ca).getSubjectDN());
       } finally {
         caInput.close();
      }
  
      String keyStoreType = KeyStore.getDefaultType();
      KeyStore keyStore = KeyStore.getInstance(keyStoreType);
      keyStore.load(null, null);
      keyStore.setCertificateEntry("ca", ca);
  
      String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
      TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm);
      tmf.init(keyStore);
  
      SSLContext context = SSLContext.getInstance("TLS");
      context.init(null, tmf.getTrustManagers(), null);
  
      // Tell the URLConnection to use a SocketFactory from our SSLContext
      HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection();
      urlConnection.setSSLSocketFactory(context.getSocketFactory());
  </code></pre>
  
  <p><strong>8. Enable TLSv1.2 only</strong> using a code from <a href="https://github.com/square/okhttp/issues/2372#issuecomment-244807676" rel="nofollow noreferrer">here</a></p>
  
  <p><em>The device that I use for testing is Samsung SM-t111 Android 4.2.2. It has google play services installed, but I am trying to fix the issue without using Google Play services because the client's device does not have it.</em></p>
  
  <p>Please suggest what should be the working solution?</p>