In my Android application I\'ve got to communicate with a https web service and read the response.
I\'ve informed the server configured SSL with
According to the Android Developer documentation TLS 1.2 is available and enabled on devices with API level 20+ (Android 4.4 Wearable):
http://developer.android.com/reference/javax/net/ssl/SSLEngine.html
I assume non of your test devices uses that API level therefore you got the result that only 5.0 devices can connect.
My personal experience is that some 4.4 devices support TLS 1.2 however it is not enabled. You can try to enable it by calling setEnabledProtocols(new String[]{"TLSv1.2"})
on the used SSLSocket.
An elegant solution doing so is implementing an own SSLSocketFactory using the Proxy pattern:
public class MySSLSocketFactory extends SSLSocketFactory {
SSLSocketFactory sslSocketFactory;
public MySSLSocketFactory(SSLSocketFactory sslSocketFactory) {
super();
this.sslSocketFactory = sslSocketFactory;
}
@Override
public String[] getDefaultCipherSuites() {
return sslSocketFactory.getDefaultCipherSuites();
}
@Override
public String[] getSupportedCipherSuites() {
return sslSocketFactory.getSupportedCipherSuites();
}
@Override
public SSLSocket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(s, host, port, autoClose);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}
@Override
public Socket createSocket(String host, int port) throws IOException, UnknownHostException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(host, port);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}
@Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException,
UnknownHostException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(host, port, localHost, localPort);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}
@Override
public Socket createSocket(InetAddress host, int port) throws IOException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(host, port);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}
@Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
throws IOException {
SSLSocket socket = (SSLSocket) sslSocketFactory.createSocket(address, port, localAddress, localPort);
socket.setEnabledProtocols(new String[] { "TLSv1.2" });
return socket;
}
You can use it this way:
...
urlConnection = (HttpsURLConnection) url.openConnection();
urlConnection.setSSLSocketFactory(new MySSLSocketFactory(urlConnection.getSSLSocketFactory()));
...
Here is a Kotlin version of the answer from Robert, which fixed the problem in my case:
import java.net.InetAddress
import java.net.Socket
import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
class MySSLSocketFactory(socket_factory :SSLSocketFactory):
SSLSocketFactory()
{
val sslSocketFactory :SSLSocketFactory
init
{
this.sslSocketFactory = socket_factory
}
override fun getDefaultCipherSuites(): Array<String>
{
return this.sslSocketFactory.getDefaultCipherSuites()
}
override fun createSocket(socket: Socket?, host: String?, port: Int, autoclose: Boolean): Socket
{
val socket: SSLSocket = this.sslSocketFactory.createSocket(socket, host, port, autoclose) as SSLSocket
socket.setEnabledProtocols(arrayOf("TLSv1.2"))
return socket
}
override fun createSocket(host: String?, port: Int): Socket
{
val socket: SSLSocket = this.sslSocketFactory.createSocket(host, port) as SSLSocket
socket.setEnabledProtocols(arrayOf("TLSv1.2"))
return socket
}
override fun createSocket(host: String?, port: Int, local_host: InetAddress?, local_port: Int): Socket {
val socket = sslSocketFactory.createSocket(host, port, local_host, local_port) as SSLSocket
socket.enabledProtocols = arrayOf("TLSv1.2")
return socket
}
override fun createSocket(host: InetAddress?, port: Int): Socket
{
val socket = sslSocketFactory.createSocket(host, port) as SSLSocket
socket.enabledProtocols = arrayOf("TLSv1.2")
return socket
}
override fun createSocket(address: InetAddress?, port: Int, local_address: InetAddress?, local_port: Int): Socket
{
val socket = sslSocketFactory.createSocket(address, port, local_address, local_port) as SSLSocket
socket.enabledProtocols = arrayOf("TLSv1.2")
return socket
}
override fun getSupportedCipherSuites(): Array<String>
{
return this.sslSocketFactory.getSupportedCipherSuites()
}
}