Javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: Failure in SSL library, usually a protocol error

142,686

Solution 1

I found the solution for it by analyzing the data packets using wireshark. What I found is that while making a secure connection, android was falling back to SSLv3 from TLSv1 . It is a bug in android versions < 4.4 , and it can be solved by removing the SSLv3 protocol from Enabled Protocols list. I made a custom socketFactory class called NoSSLv3SocketFactory.java. Use this to make a socketfactory.

/*Copyright 2015 Bhavit Singh Sengar
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.*/

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetAddress;
import java.net.Socket;
import java.net.SocketAddress;
import java.net.SocketException;
import java.nio.channels.SocketChannel;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSession;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;


public class NoSSLv3SocketFactory extends SSLSocketFactory{
    private final SSLSocketFactory delegate;

public NoSSLv3SocketFactory() {
    this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory();
}

public NoSSLv3SocketFactory(SSLSocketFactory delegate) {
    this.delegate = delegate;
}

@Override
public String[] getDefaultCipherSuites() {
    return delegate.getDefaultCipherSuites();
}

@Override
public String[] getSupportedCipherSuites() {
    return delegate.getSupportedCipherSuites();
}

private Socket makeSocketSafe(Socket socket) {
    if (socket instanceof SSLSocket) {
        socket = new NoSSLv3SSLSocket((SSLSocket) socket);
    }
    return socket;
}

@Override
public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
    return makeSocketSafe(delegate.createSocket(s, host, port, autoClose));
}

@Override
public Socket createSocket(String host, int port) throws IOException {
    return makeSocketSafe(delegate.createSocket(host, port));
}

@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException {
    return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort));
}

@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
    return makeSocketSafe(delegate.createSocket(host, port));
}

@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException {
    return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort));
}

private class NoSSLv3SSLSocket extends DelegateSSLSocket {

    private NoSSLv3SSLSocket(SSLSocket delegate) {
        super(delegate);

    }

    @Override
    public void setEnabledProtocols(String[] protocols) {
        if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) {

            List<String> enabledProtocols = new ArrayList<String>(Arrays.asList(delegate.getEnabledProtocols()));
            if (enabledProtocols.size() > 1) {
                enabledProtocols.remove("SSLv3");
                System.out.println("Removed SSLv3 from enabled protocols");
            } else {
                System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols));
            }
            protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]);
        }

        super.setEnabledProtocols(protocols);
    }
}

public class DelegateSSLSocket extends SSLSocket {

    protected final SSLSocket delegate;

    DelegateSSLSocket(SSLSocket delegate) {
        this.delegate = delegate;
    }

    @Override
    public String[] getSupportedCipherSuites() {
        return delegate.getSupportedCipherSuites();
    }

    @Override
    public String[] getEnabledCipherSuites() {
        return delegate.getEnabledCipherSuites();
    }

    @Override
    public void setEnabledCipherSuites(String[] suites) {
        delegate.setEnabledCipherSuites(suites);
    }

    @Override
    public String[] getSupportedProtocols() {
        return delegate.getSupportedProtocols();
    }

    @Override
    public String[] getEnabledProtocols() {
        return delegate.getEnabledProtocols();
    }

    @Override
    public void setEnabledProtocols(String[] protocols) {
        delegate.setEnabledProtocols(protocols);
    }

    @Override
    public SSLSession getSession() {
        return delegate.getSession();
    }

    @Override
    public void addHandshakeCompletedListener(HandshakeCompletedListener listener) {
        delegate.addHandshakeCompletedListener(listener);
    }

    @Override
    public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) {
        delegate.removeHandshakeCompletedListener(listener);
    }

    @Override
    public void startHandshake() throws IOException {
        delegate.startHandshake();
    }

    @Override
    public void setUseClientMode(boolean mode) {
        delegate.setUseClientMode(mode);
    }

    @Override
    public boolean getUseClientMode() {
        return delegate.getUseClientMode();
    }

    @Override
    public void setNeedClientAuth(boolean need) {
        delegate.setNeedClientAuth(need);
    }

    @Override
    public void setWantClientAuth(boolean want) {
        delegate.setWantClientAuth(want);
    }

    @Override
    public boolean getNeedClientAuth() {
        return delegate.getNeedClientAuth();
    }

    @Override
    public boolean getWantClientAuth() {
        return delegate.getWantClientAuth();
    }

    @Override
    public void setEnableSessionCreation(boolean flag) {
        delegate.setEnableSessionCreation(flag);
    }

    @Override
    public boolean getEnableSessionCreation() {
        return delegate.getEnableSessionCreation();
    }

    @Override
    public void bind(SocketAddress localAddr) throws IOException {
        delegate.bind(localAddr);
    }

    @Override
    public synchronized void close() throws IOException {
        delegate.close();
    }

    @Override
    public void connect(SocketAddress remoteAddr) throws IOException {
        delegate.connect(remoteAddr);
    }

    @Override
    public void connect(SocketAddress remoteAddr, int timeout) throws IOException {
        delegate.connect(remoteAddr, timeout);
    }

    @Override
    public SocketChannel getChannel() {
        return delegate.getChannel();
    }

    @Override
    public InetAddress getInetAddress() {
        return delegate.getInetAddress();
    }

    @Override
    public InputStream getInputStream() throws IOException {
        return delegate.getInputStream();
    }

    @Override
    public boolean getKeepAlive() throws SocketException {
        return delegate.getKeepAlive();
    }

    @Override
    public InetAddress getLocalAddress() {
        return delegate.getLocalAddress();
    }

    @Override
    public int getLocalPort() {
        return delegate.getLocalPort();
    }

    @Override
    public SocketAddress getLocalSocketAddress() {
        return delegate.getLocalSocketAddress();
    }

    @Override
    public boolean getOOBInline() throws SocketException {
        return delegate.getOOBInline();
    }

    @Override
    public OutputStream getOutputStream() throws IOException {
        return delegate.getOutputStream();
    }

    @Override
    public int getPort() {
        return delegate.getPort();
    }

    @Override
    public synchronized int getReceiveBufferSize() throws SocketException {
        return delegate.getReceiveBufferSize();
    }

    @Override
    public SocketAddress getRemoteSocketAddress() {
        return delegate.getRemoteSocketAddress();
    }

    @Override
    public boolean getReuseAddress() throws SocketException {
        return delegate.getReuseAddress();
    }

    @Override
    public synchronized int getSendBufferSize() throws SocketException {
        return delegate.getSendBufferSize();
    }

    @Override
    public int getSoLinger() throws SocketException {
        return delegate.getSoLinger();
    }

    @Override
    public synchronized int getSoTimeout() throws SocketException {
        return delegate.getSoTimeout();
    }

    @Override
    public boolean getTcpNoDelay() throws SocketException {
        return delegate.getTcpNoDelay();
    }

    @Override
    public int getTrafficClass() throws SocketException {
        return delegate.getTrafficClass();
    }

    @Override
    public boolean isBound() {
        return delegate.isBound();
    }

    @Override
    public boolean isClosed() {
        return delegate.isClosed();
    }

    @Override
    public boolean isConnected() {
        return delegate.isConnected();
    }

    @Override
    public boolean isInputShutdown() {
        return delegate.isInputShutdown();
    }

    @Override
    public boolean isOutputShutdown() {
        return delegate.isOutputShutdown();
    }

    @Override
    public void sendUrgentData(int value) throws IOException {
        delegate.sendUrgentData(value);
    }

    @Override
    public void setKeepAlive(boolean keepAlive) throws SocketException {
        delegate.setKeepAlive(keepAlive);
    }

    @Override
    public void setOOBInline(boolean oobinline) throws SocketException {
        delegate.setOOBInline(oobinline);
    }

    @Override
    public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) {
        delegate.setPerformancePreferences(connectionTime, latency, bandwidth);
    }

    @Override
    public synchronized void setReceiveBufferSize(int size) throws SocketException {
        delegate.setReceiveBufferSize(size);
    }

    @Override
    public void setReuseAddress(boolean reuse) throws SocketException {
        delegate.setReuseAddress(reuse);
    }

    @Override
    public synchronized void setSendBufferSize(int size) throws SocketException {
        delegate.setSendBufferSize(size);
    }

    @Override
    public void setSoLinger(boolean on, int timeout) throws SocketException {
        delegate.setSoLinger(on, timeout);
    }

    @Override
    public synchronized void setSoTimeout(int timeout) throws SocketException {
        delegate.setSoTimeout(timeout);
    }

    @Override
    public void setTcpNoDelay(boolean on) throws SocketException {
        delegate.setTcpNoDelay(on);
    }

    @Override
    public void setTrafficClass(int value) throws SocketException {
        delegate.setTrafficClass(value);
    }

    @Override
    public void shutdownInput() throws IOException {
        delegate.shutdownInput();
    }

    @Override
    public void shutdownOutput() throws IOException {
        delegate.shutdownOutput();
    }

    @Override
    public String toString() {
        return delegate.toString();
    }

    @Override
    public boolean equals(Object o) {
        return delegate.equals(o);
    }
}
}

Use this class like this while connecting :

SSLContext sslcontext = SSLContext.getInstance("TLSv1");
sslcontext.init(null, null, null);
SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory());

HttpsURLConnection.setDefaultSSLSocketFactory(NoSSLv3Factory);
l_connection = (HttpsURLConnection) l_url.openConnection();
l_connection.connect();

UPDATE :

Now, correct solution would be to install a newer security provider using Google Play Services:

    ProviderInstaller.installIfNeeded(getApplicationContext());

This effectively gives your app access to a newer version of OpenSSL and Java Security Provider, which includes support for TLSv1.2 in SSLEngine. Once the new provider is installed, you can create an SSLEngine which supports SSLv3, TLSv1, TLSv1.1 and TLSv1.2 the usual way:

    SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
    sslContext.init(null, null, null);
    SSLEngine engine = sslContext.createSSLEngine();

Or you can restrict the enabled protocols using engine.setEnabledProtocols.

Don't forget to add the following dependency (check the latest version here):

implementation 'com.google.android.gms:play-services-auth:17.0.0'

For more info, checkout this link.

Solution 2

Scenario

I was getting SSLHandshake exceptions on devices running versions of Android earlier than Android 5.0. In my use case I also wanted to create a TrustManager to trust my client certificate.

I implemented NoSSLv3SocketFactory and NoSSLv3Factory to remove SSLv3 from my client's list of supported protocols but I could get neither of these solutions to work.

Some things I learned:

  • On devices older than Android 5.0 TLSv1.1 and TLSv1.2 protocols are not enabled by default.
  • SSLv3 protocol is not disabled by default on devices older than Android 5.0.
  • SSLv3 is not a secure protocol and it is therefore desirable to remove it from our client's list of supported protocols before a connection is made.

What worked for me

Allow Android's security Provider to update when starting your app.

The default Provider before 5.0+ does not disable SSLv3. Provided you have access to Google Play services it is relatively straightforward to patch Android's security Provider from your app.

private void updateAndroidSecurityProvider(Activity callingActivity) {
    try {
        ProviderInstaller.installIfNeeded(this);
    } catch (GooglePlayServicesRepairableException e) {
        // Thrown when Google Play Services is not installed, up-to-date, or enabled
        // Show dialog to allow users to install, update, or otherwise enable Google Play services.
        GooglePlayServicesUtil.getErrorDialog(e.getConnectionStatusCode(), callingActivity, 0);
    } catch (GooglePlayServicesNotAvailableException e) {
        Log.e("SecurityException", "Google Play Services not available.");
    }
}

If you now create your OkHttpClient or HttpURLConnection TLSv1.1 and TLSv1.2 should be available as protocols and SSLv3 should be removed. If the client/connection (or more specifically it's SSLContext) was initialised before calling ProviderInstaller.installIfNeeded(...) then it will need to be recreated.

Don't forget to add the following dependency (latest version found here):

compile 'com.google.android.gms:play-services-auth:16.0.1'

Sources:

Aside

I didn't need to explicitly set which cipher algorithms my client should use but I found a SO post recommending those considered most secure at the time of writing: Which Cipher Suites to enable for SSL Socket?

Solution 3

Also you should know that you can force TLS v1.2 for Android 4.0 devices that don't have it enabled by default:

Put this code in onCreate() of your Application file:

try {
        ProviderInstaller.installIfNeeded(getApplicationContext());
        SSLContext sslContext;
        sslContext = SSLContext.getInstance("TLSv1.2");
        sslContext.init(null, null, null);
        sslContext.createSSLEngine();
    } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException
            | NoSuchAlgorithmException | KeyManagementException e) {
        e.printStackTrace();
    }

Solution 4

Previously, I've also solved this problem with custom SSLFactory implementation, but according to OkHttp docs the solution is much easier.

My final solution with needed TLS ciphers for 4.2+ devices looks like this:

public UsersApi provideUsersApi() {

    private ConnectionSpec spec = new ConnectionSpec.Builder(ConnectionSpec.COMPATIBLE_TLS)
        .supportsTlsExtensions(true)
        .tlsVersions(TlsVersion.TLS_1_2, TlsVersion.TLS_1_1, TlsVersion.TLS_1_0)
        .cipherSuites(
                CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
                CipherSuite.TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,
                CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
                CipherSuite.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
                CipherSuite.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
                CipherSuite.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
                CipherSuite.TLS_ECDHE_ECDSA_WITH_RC4_128_SHA,
                CipherSuite.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
                CipherSuite.TLS_DHE_RSA_WITH_AES_128_CBC_SHA,
                CipherSuite.TLS_DHE_DSS_WITH_AES_128_CBC_SHA,
                CipherSuite.TLS_DHE_RSA_WITH_AES_256_CBC_SHA)
        .build();

    OkHttpClient client = new OkHttpClient.Builder()
            .connectionSpecs(Collections.singletonList(spec))
            .build();

    return new Retrofit.Builder()
            .baseUrl(USERS_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .client(client)
            .build()
            .create(UsersApi.class);
}

Note that set of supported protocols depends on configured on your server.

Solution 5

I found the solution here in this link.

You just have to place below code in your Android application class. And that is enough. Don't need to do any changes in your Retrofit settings. It saved my day.

public class MyApplication extends Application {
@Override
public void onCreate() {
    super.onCreate();
    try {
      // Google Play will install latest OpenSSL 
      ProviderInstaller.installIfNeeded(getApplicationContext());
      SSLContext sslContext;
      sslContext = SSLContext.getInstance("TLSv1.2");
      sslContext.init(null, null, null);
      sslContext.createSSLEngine();
    } catch (GooglePlayServicesRepairableException | GooglePlayServicesNotAvailableException
        | NoSuchAlgorithmException | KeyManagementException e) {
        e.printStackTrace();
        }
    }
}

Hope this will be of help. Thank you.

Share:
142,686
Bhavit S. Sengar
Author by

Bhavit S. Sengar

Currently working as an Android and iOS Developer in Oracle Financial Software Services Ltd, Mumbai. I have pursued B.Tech, from Govt.Engineering College Bikaner in Computer Science. Completed my post-graduation diploma in Advanced Computing from Center for Development of Advanced Computing(C-DAC). I have good command on programming in JavaSE, JavaEE, Android and C/C++.

Updated on September 25, 2020

Comments

  • Bhavit S. Sengar
    Bhavit S. Sengar almost 4 years

    I am trying to run the following code in android

    URLConnection l_connection = null;
            // Create connection
            uzip=new UnZipData(mContext);
            l_url = new URL(serverurl);
    
            if ("https".equals(l_url.getProtocol())) {
                System.out.println("<<<<<<<<<<<<< Before TLS >>>>>>>>>>>>");
                sslcontext = SSLContext.getInstance("TLS");
                System.out.println("<<<<<<<<<<<<< After TLS >>>>>>>>>>>>");
                sslcontext.init(null,
                        new TrustManager[] { new CustomTrustManager()},
                        new java.security.SecureRandom());
                HttpsURLConnection
                        .setDefaultHostnameVerifier(new CustomHostnameVerifier());
                HttpsURLConnection.setDefaultSSLSocketFactory(sslcontext
                        .getSocketFactory());
    
                l_connection = (HttpsURLConnection) l_url.openConnection();
                ((HttpsURLConnection) l_connection).setRequestMethod("POST");
            } else {
                l_connection = (HttpURLConnection) l_url.openConnection();
                ((HttpURLConnection) l_connection).setRequestMethod("POST");
            }
            /*System.setProperty("http.agent", "Android_Phone");*/
    
    
            l_connection.setConnectTimeout(10000);
            l_connection.setRequestProperty("Content-Language", "en-US");
            l_connection.setUseCaches(false);
            l_connection.setDoInput(true);
            l_connection.setDoOutput(true);
            System.out.println("<<<<<<<<<<<<< Before Connection >>>>>>>>>>>>");
            l_connection.connect();
    

    On l_connection.connect() , it is giving this SSLhandshakeException. Sometimes it works, but most of the time it gives the exception. It is only happening on Android 4.0 emulator. I tested it on Android 4.4 and 5.0, it works fine. What could be the cause of this ? Please help

    STACKTRACE

        04-28 15:51:13.143: W/System.err(2915): javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error
    04-28 15:51:13.143: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000)
    04-28 15:51:13.143: W/System.err(2915):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:460)
    04-28 15:51:13.143: W/System.err(2915):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:257)
    04-28 15:51:13.143: W/System.err(2915):     at libcore.net.http.HttpConnection.setupSecureSocket(HttpConnection.java:210)
    04-28 15:51:13.143: W/System.err(2915):     at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.makeSslConnection(HttpsURLConnectionImpl.java:477)
    04-28 15:51:13.153: W/System.err(2915):     at libcore.net.http.HttpsURLConnectionImpl$HttpsEngine.connect(HttpsURLConnectionImpl.java:441)
    04-28 15:51:13.153: W/System.err(2915):     at libcore.net.http.HttpEngine.sendSocketRequest(HttpEngine.java:282)
    04-28 15:51:13.153: W/System.err(2915):     at libcore.net.http.HttpEngine.sendRequest(HttpEngine.java:232)
    04-28 15:51:13.153: W/System.err(2915):     at libcore.net.http.HttpURLConnectionImpl.connect(HttpURLConnectionImpl.java:80)
    04-28 15:51:13.153: W/System.err(2915):     at libcore.net.http.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:164)
    04-28 15:51:13.153: W/System.err(2915):     at com.ofss.fcdb.mobile.android.rms.helpers.NetworkConnector.getConnection(NetworkConnector.java:170)
    04-28 15:51:13.153: W/System.err(2915):     at com.ofss.fcdb.mobile.android.rms.util.InitiateRMS$2.run(InitiateRMS.java:221)
    04-28 15:51:13.153: W/System.err(2915):     at java.lang.Thread.run(Thread.java:856)
    04-28 15:51:13.153: W/System.err(2915): Caused by: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x870c918: Failure in SSL library, usually a protocol error
    04-28 15:51:13.153: W/System.err(2915): error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb7c393a1:0x00000000)
    04-28 15:51:13.153: W/System.err(2915):     at org.apache.harmony.xnet.provider.jsse.NativeCrypto.SSL_do_handshake(Native Method)
    04-28 15:51:13.153: W/System.err(2915):     at org.apache.harmony.xnet.provider.jsse.OpenSSLSocketImpl.startHandshake(OpenSSLSocketImpl.java:410)
    04-28 15:51:13.153: W/System.err(2915):     ... 11 more
    04-28 16:42:44.139: W/ResourceType(3140): No package identifier when getting value for resource number 0x00000000
    
  • IgorGanapolsky
    IgorGanapolsky over 8 years
    What if I'm getting this error on a Lollipop device?
  • Skynet
    Skynet over 8 years
    I am getting this on 5.0.1
  • Jaroslav Záruba
    Jaroslav Záruba over 8 years
    This approach seems to be failing when connecting to a virtual host, as it effectively disables SNI by not providing SSLCertificateSocketFactory.setHostname(Socket, String) method. I have been getting 403s where openssl.exe and browser connect w/o troubles. It turns out it is the missing SNI.
  • wkhatch
    wkhatch about 8 years
    not working for me on 5.1; no matter what, the SSLv3 protocol still shows up when inspecting it in debugger.
  • Bhavit S. Sengar
    Bhavit S. Sengar about 8 years
    What exact error is it giving in 5.1 ? Can you share the logs ?
  • uniruddh
    uniruddh almost 8 years
    how can one use this with volley?
  • lordscales91
    lordscales91 over 7 years
    This approach really works. Sadly, this forces my app to use Google Play Services which makes incompatible with some devices. However those are a minority. Isn't it? Is there a way to update the provider manually?
  • Maurice Gavin
    Maurice Gavin over 7 years
    I don't know of any published stats for the number of devices running Google Play Services. The latest figure I could find was Sundar Pichai's IO 2014 talk where he said that 93% of Android devices had the latest version of Play Services. Concerning a manual method, I arrived at this solution when all the manual methods had failed to work for me. If network security isn't vital to your users you could always fall back to HTTP if the user refuses to install Play Services. For our own app we considered the trade-off between compatibility and security. We enforce an update of Play Services.
  • lordscales91
    lordscales91 over 7 years
    @MauriceGavin Thanks for the info. Actually, I'm creating an unofficial "Pin It!" app for Pinterest because the official app seems to fail, or just doesn't find all images in a web page every time I try to create a Pin. So I was using their API and Jsoup to fetch the img tags when I found this issue. TLDR: I just can't choose to disable HTTPS because I can't control every web server on the Internet.
  • 0xAliHn
    0xAliHn over 7 years
    @BhavitS.Sengar It's not working in my case. Can you please help? I am using 4.4.2 device. Same exception.
  • jayeffkay
    jayeffkay over 7 years
    Google Play Services support in China is very limited. Could be good to know depending on your target audience. But well, if you distribute via Google Play, this audience is already missing out.
  • CLIFFORD P Y
    CLIFFORD P Y over 7 years
    @BhavitS.Sengar how can i use this with loopj httpAsync/Ion/SocketIO
  • Rukmal Dias
    Rukmal Dias over 7 years
    i am getting this error in Android API 19 javax.net.ssl.SSLProtocolException: Read error: ssl=0xb83d7120: Failure in SSL library, usually a protocol error
  • Diederik
    Diederik over 7 years
    I have seen this handshake issue on a slow link as well. Increasing timeouts also helped solved this for me. Above solution worked for < 4.4 devices.
  • Pradeep Chakravarti Gudipati
    Pradeep Chakravarti Gudipati over 7 years
    Please add this dependency for the solution to work. compile 'com.google.android.gms:play-services-auth:10.2.0',
  • Kelevandos
    Kelevandos over 6 years
    Adding the ProviderInstaller.installIfNeeded(this); part into Application's onCreate() worked for me! Thanks :-)
  • Burak Karakuş
    Burak Karakuş almost 6 years
    Definitely the most useful answer here. Thanks for such an invaluable help.
  • Gweltaz Niquel
    Gweltaz Niquel almost 6 years
    Worked for me with rxJava OkHttpClient.Builder, thanks a lot.
  • aleksandrbel
    aleksandrbel over 5 years
    @Kelevandos You should use ProviderInstaller.installIfNeededAsync(this, this) instead of .installIfNeeded(). Otherwise it will be running on the UI thread and regarding the documentation "Updating the security provider can take as much as 350 milliseconds (on older devices)."
  • CoolMind
    CoolMind over 5 years
    Works on Android 7.0.
  • CoolMind
    CoolMind over 5 years
    Does your solution support API 14?
  • Fragment
    Fragment over 5 years
    Cannot say for sure, tested this only on 16+ API devices, works fine.
  • CoolMind
    CoolMind over 5 years
    Fragment, a cute nickname :) I agree, couldn't even start API 14 emulator, but your solution works on Android 7.0 (that had the issue) and on API 19.
  • CoolMind
    CoolMind over 5 years
    Thanks, I tested, it worked. Today launched an API 19 emulator again and had to add a solution stackoverflow.com/a/51285550/2914140.
  • android developer
    android developer about 5 years
    Starting from which Android version is it not needed anymore ? 5.1 ?
  • Basant
    Basant almost 5 years
    thanks @mayur gangurde, this is for work me after adding play services auth gradle, implementation 'com.google.android.gms:play-services-auth:16.0.1'
  • Ninad Desai
    Ninad Desai over 4 years
    Worked perfectly. Thank you so much for saving me hours of testing and trying.
  • Caspar Geerlings
    Caspar Geerlings over 4 years
    This is very convenient. Thanks a lot!
  • CoolMind
    CoolMind over 4 years
    How do you use it?
  • CoolMind
    CoolMind over 4 years
    I couldn't make it work on API 16 emulator with Retrofit.
  • CoolMind
    CoolMind over 4 years
    I couldn't make it work on API 16 emulator with Retrofit.
  • ThanosFisherman
    ThanosFisherman over 4 years
    Saved my life in 4.4.2
  • Roman Nazarevych
    Roman Nazarevych almost 4 years
    IMPORTANT updateAndroidSecurityProvider must be invoked before OkHttpClient
  • Shendre Kiran
    Shendre Kiran almost 4 years
    Tested on API 19 and 24. It's working perfectly. Thank you.
  • CoolMind
    CoolMind almost 4 years
  • ToxicAbe
    ToxicAbe over 3 years
    GooglePlayServicesUtil.getErrorDialog(int,Activity,int) is deprecated use GoogleApiAvailability.getInstance().getErrorDialog(callingAc‌​tivity, GoogleApiAvailability.getInstance().isGooglePlayServicesAvai‌​lable(callingActivit‌​y), 0).show() GoogleApiAvailability
  • Md. Yamin Mollah
    Md. Yamin Mollah over 3 years
    Perfectly working and should be the correct answer.
  • Arpan Saini
    Arpan Saini over 3 years
    you can use http instead of https that's a secure connection, that's causing the issue. it resolved mine
  • Sriram Nadiminti
    Sriram Nadiminti about 3 years
    Genius!! This saved my app. Really great
  • kirkadev
    kirkadev about 2 years
    also, you should use override sslSocketFactory(Tls12SocketFactory(sc.socketFactory), trustManager) , because after adding ProviderInstaller.installIfNeeded(context) your app will crash