I’m getting the following error while trying to run on devices below android lollipop and it is working really well for version above lollipop.
javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x943e670: Failure in SSL library, usually a protocol error error:14077410:SSL routines:SSL23_GET_SERVER_HELLO:sslv3 alert handshake failure (external/openssl/ssl/s23_clnt.c:658 0xb750d3a1:0x00000000)
this is my method to register the user:
String tag_string_req = "register"; StringRequest strReq = new StringRequest(Request.Method.POST, AppConfig.URL_REGISTER, new Response.Listener<String>() { @Override public void onResponse(String response) { Log.d(TAG, "Register Response: " + response.toString()); hideDialog(); try { JSONObject jObj = new JSONObject(response); boolean error = jObj.getBoolean("error"); if (!error) { String id = jObj.getString("id"); finish(); } else { String errorMsg = jObj.getString("error_msg"); Toast.makeText(getApplicationContext(), errorMsg, Toast.LENGTH_LONG).show(); } } catch (JSONException e) { e.printStackTrace(); } } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(TAG, "Registration Error: " + error.getMessage()); Toast.makeText(getApplicationContext(), error.getMessage(), Toast.LENGTH_LONG).show(); hideDialog(); } }) { @Override protected Map<String, String> getParams() { Map<String, String> params = new HashMap<String, String>(); params.put("user_name", txtSEditName.getText().toString().trim()); params.put("password", txtSEditPhone.getText().toString().trim()); return params; } }; AppController.getInstance().addToRequestQueue(strReq, tag_string_req);
My volley singleton looks like this:
public class AppController extends Application { public static final String TAG = AppController.class.getSimpleName(); private RequestQueue mRequestQueue; private static AppController mInstance; @Override public void onCreate() { super.onCreate(); mInstance = this; } public static synchronized AppController getInstance() { return mInstance; } public RequestQueue getRequestQueue() { if (mRequestQueue == null) { mRequestQueue = Volley.newRequestQueue(getApplicationContext()); } return mRequestQueue; } public <T> void addToRequestQueue(Request<T> req, String tag) { req.setTag(TextUtils.isEmpty(tag) ? TAG : tag); getRequestQueue().add(req); } public <T> void addToRequestQueue(Request<T> req) { req.setTag(TAG); getRequestQueue().add(req); } public void cancelPendingRequests(Object tag) { if (mRequestQueue != null) { mRequestQueue.cancelAll(tag); } } }
and my app config file looks like this:
public static String URL_REGISTER = "http://192.168.56.1/MyApp/register.php";
Can anyone help me solve this issue?
Error: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted:
Advertisement
Answer
I have tried to sort out the error and this has worked for me. What I have understood was that for devices below that of lollipop the protocols TLSv1.1 and TLSv1.2 are not enabled by default. Inorder to enable them for devices such using jellybean or kitkat we will have to use a SSLSocketFactory.
So now I have made the following change to the getRequestQueue() method of Volley singleton:
public RequestQueue getRequestQueue() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && Build.VERSION.SDK_INT <= Build.VERSION_CODES.KITKAT) { Log.d("msg", "HI, I m a kitkat phone"); try { ProviderInstaller.installIfNeeded(getApplicationContext()); } catch (GooglePlayServicesRepairableException e) { // Indicates that Google Play services is out of date, disabled, etc. // Prompt the user to install/update/enable Google Play services. GooglePlayServicesUtil.showErrorNotification(e.getConnectionStatusCode(), getApplicationContext()); e.printStackTrace(); } catch (GooglePlayServicesNotAvailableException e) { // Indicates a non-recoverable error; the ProviderInstaller is not able // to install an up-to-date Provider. e.printStackTrace(); } HttpStack stack = null; try { stack = new HurlStack(null, new TLSSocketFactory()); } catch (KeyManagementException e) { e.printStackTrace(); Log.d("Your Wrapper Class", "Could not create new stack for TLS v1.2"); stack = new HurlStack(); } catch (NoSuchAlgorithmException e) { e.printStackTrace(); Log.d("Your Wrapper Class", "Could not create new stack for TLS v1.2"); stack = new HurlStack(); } mRequestQueue = Volley.newRequestQueue(getApplicationContext(), stack); } else { mRequestQueue = Volley.newRequestQueue(getApplicationContext()); } return mRequestQueue; }
And create a class named TLSSocketFactory.java and add the following code:
public class TLSSocketFactory extends SSLSocketFactory {
private SSLSocketFactory internalSSLSocketFactory; public TLSSocketFactory() throws KeyManagementException, NoSuchAlgorithmException { SSLContext context = SSLContext.getInstance("TLS"); context.init(null, null, null); internalSSLSocketFactory = context.getSocketFactory(); } @Override public String[] getDefaultCipherSuites() { return internalSSLSocketFactory.getDefaultCipherSuites(); } @Override public String[] getSupportedCipherSuites() { return internalSSLSocketFactory.getSupportedCipherSuites(); } @Override public Socket createSocket() throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket()); } @Override public Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(s, host, port, autoClose)); } @Override public Socket createSocket(String host, int port) throws IOException, UnknownHostException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override public Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException, UnknownHostException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port, localHost, localPort)); } @Override public Socket createSocket(InetAddress host, int port) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(host, port)); } @Override public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return enableTLSOnSocket(internalSSLSocketFactory.createSocket(address, port, localAddress, localPort)); } private Socket enableTLSOnSocket(Socket socket) { if(socket != null && (socket instanceof SSLSocket)) { ((SSLSocket)socket).setEnabledProtocols(new String[] {"TLSv1.1", "TLSv1.2"}); } return socket; }
}
One more step is to add the following implementation in your dependencies of gradle file:
implementation 'com.google.android.gms:play-services-base:11.0.0'
I hope this might help you to resolve this issue.