androidandroid-volleysslexception

SSL Exception when using Volley


I'm using Volley in Android to perform my app requests. Unfortunately, I'm getting the following error:

com.android.volley.NoConnectionError: javax.net.ssl.SSLHandshakeException: javax.net.ssl.SSLProtocolException: SSL handshake aborted: ssl=0x61e15f78: Failure in SSL library, usually a protocol error
    error:1407743E:SSL routines:SSL23_GET_SERVER_HELLO:tlsv1 alert inappropriate fallback (external/openssl/ssl/s23_clnt.c:744 0x5b647c58:0x00000000)

I'm using two Fragments, inside a ViewPager, which request their content during onResume. The requests url is basically the same but for a query parameter (which set the type of content, e.g. trending vs hot).

The url is in the form https://host/api/content?type={hot/trending}. Authorization is done through the request header.

The weird part about this exception is that only one of the two requests fail and it varies which one from time to time. After I added a delay between them, the exception stopped occurring (oddly pointing to some race condition?). But this seems a bad workaround and I'd like to solve this the right way.

Any thoughts on what could be the cause of it?

EDIT:

The request is created the standard way, using a singleton providing the queue, as follows:

final RequestQueue requestQueue = RequestQueueSingleton.getInstance(getActivity()).getRequestQueue();
final GsonRequestGet<SearchApiWrapper> gsonRequest = new GsonRequestGet<>(clazz, url,successListener, errorListener);
gsonRequest.setRetryPolicy(new DefaultRetryPolicy(3000, 3, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));
gsonRequest.setTag(mTag);
requestQueue.add(gsonRequest);

And here is the singleton class:

public class RequestQueueSingleton {

    private static RequestQueueSingleton mInstance;
    private RequestQueue mRequestQueue;
    private Context mContext;

    public RequestQueueSingleton(Context context) {
        mContext = context;
        mRequestQueue = getRequestQueue();
    }

    /**
     * Returns a instance of this singleton
     */
    public static synchronized RequestQueueSingleton getInstance(Context context) {
        if (mInstance == null) {
            mInstance = new RequestQueueSingleton(context);
        }
        return mInstance;
    }

    /**
     * Returns instance of the request queue
     */
    public RequestQueue getRequestQueue() {
        if (mRequestQueue == null) {
            mRequestQueue = Volley.newRequestQueue(mContext.getApplicationContext());
        }
        return mRequestQueue;
    }
}

Solution

  • After our comments maybe this can help you:

    Your requestQueue:

    static {
        requestQueue = Volley.newRequestQueue(Application.getContext(), new HurlStack(null, ClientSSLSocketFactory.getSocketFactory()));
    }
    

    The ClientSSLSocketFactory:

    public class ClientSSLSocketFactory extends SSLCertificateSocketFactory {
        private SSLContext sslContext;
    
        public static SSLSocketFactory getSocketFactory(){
            try
            {
                X509TrustManager tm = new X509TrustManager() {
                    public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
    
                    public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {}
    
                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }
                };
                sslContext = SSLContext.getInstance("TLS");
                sslContext.init(null, new TrustManager[] { tm }, null);
    
                SSLSocketFactory ssf = ClientSSLSocketFactory.getDefault(10000, new SSLSessionCache(Application.getInstance()));
    
                return ssf;
            } catch (Exception ex) {
                return null;
            }
        }
    
        @Override
        public Socket createSocket(Socket socket, String host, int port, boolean autoClose) throws IOException, UnknownHostException {
            return sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
        }
    
        @Override
        public Socket createSocket() throws IOException {
            return sslContext.getSocketFactory().createSocket();
        }
    }