The application quite often sends and receives requests from the server. I used to do everything with the help of DefaultHttpClient and it worked fine, but I decided to switch to Volley and there is a big problem. After about 30 requests ceases to send and receive them altogether. LogCat is empty. Made singleton for RequestQueue. Used by VolleyPlus.
Initialization of singleton in Application
public void onCreate() { super.onCreate(); //Init Volley requests StringRequest.getInstance(this); ... } Class itself
public class StringRequest { private final String TAG = this.getClass().getSimpleName(); private static StringRequest mInstance; private RequestQueue mRequestQueue; private ProgressListener mProgress; private ResponseListener mResponse; private ErrorListener mError; private List<String> files; private StringRequest(Context context){ mRequestQueue = getRequestQueue(context.getApplicationContext()); } public static synchronized StringRequest getInstance(Context context) { if (null == mInstance) mInstance = new StringRequest(context); return mInstance; } public static synchronized StringRequest getInstance() { if (null == mInstance) { throw new IllegalStateException(StringRequest.class.getSimpleName() + " is not initialized, call getInstance(...) first"); } return mInstance; } public RequestQueue getRequestQueue(Context context) { if (mRequestQueue == null) { mRequestQueue = Volley.newRequestQueue(context, getStack()); } return mRequestQueue; } private HurlStack getStack(){ return new HurlStack() { @Override protected HttpURLConnection createConnection(URL url) throws IOException { HttpsURLConnection httpsURLConnection = (HttpsURLConnection) super.createConnection(url); try { httpsURLConnection.setSSLSocketFactory(getSSLSocketFactory()); httpsURLConnection.setHostnameVerifier(getHostnameVerifier()); } catch (CertificateException | KeyStoreException | KeyManagementException | NoSuchAlgorithmException e) { Log.e(TAG, "getHurlStack ", e); } return httpsURLConnection; } }; } public void createRequest(String tag, String url, Map<String, String> params){ final SimpleMultiPartRequest request = new SimpleMultiPartRequest(Request.Method.POST, url, new Response.Listener<String>() { @Override public void onResponse(String response) { //Log.d(TAG, response); if(mResponse != null) mResponse.onResponse(response); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { //Log.d(TAG, error.getMessage()); if(mError != null) mError.onError(error); } }) { @Override public Map<String, String> getHeaders() throws AuthFailureError { SharedPreferences app_preferences = PreferenceManager.getDefaultSharedPreferences(Application.getInstance()); HashMap<String, String> params = new HashMap<>(); params.put("PARAM1", app_preferences.getString("user", "")); params.put("PARAM2", app_preferences.getString("password", "")); return params; } }; if(getFiles()!=null && getFiles().size()>0) { for(int i=0; i<getFiles().size(); i++) { request.addFile("images", getFiles().get(i)); } } request.setFixedStreamingMode(true); request.setTag(tag); /*request.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 0, DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));*/ request.setRetryPolicy(new DefaultRetryPolicy(20 * 1000, 1, 1.0f)); request.setShouldCache(false); if(params!=null && params.size()>0){ for (Map.Entry<String, String> entry : params.entrySet()) { request.addStringParam(entry.getKey(), entry.getValue()); } } request.setOnProgressListener(new Response.ProgressListener() { int latestPercentDone, percentDone; @Override public void onProgress(long transferredBytes, long totalSize) { latestPercentDone = (int) ((transferredBytes / (float) totalSize) * 100); if (percentDone != latestPercentDone) { percentDone = latestPercentDone; if(mProgress != null) mProgress.onProgress(percentDone); } } }); mRequestQueue.add(request); } private HostnameVerifier getHostnameVerifier() { return new HostnameVerifier() { @Override public boolean verify(String hostname, SSLSession session) { HostnameVerifier hv = HttpsURLConnection.getDefaultHostnameVerifier(); return hv.verify("mysite.com", session); } }; } private TrustManager[] getWrappedTrustManagers(TrustManager[] trustManagers) { final X509TrustManager originalTrustManager = (X509TrustManager) trustManagers[0]; return new TrustManager[]{ new X509TrustManager() { public X509Certificate[] getAcceptedIssuers() { return originalTrustManager.getAcceptedIssuers(); } public void checkClientTrusted(X509Certificate[] certs, String authType) { try { if (certs != null && certs.length > 0){ certs[0].checkValidity(); } else { originalTrustManager.checkClientTrusted(certs, authType); } } catch (CertificateException e) { Log.w(TAG, e.toString()); } } public void checkServerTrusted(X509Certificate[] certs, String authType) { try { if (certs != null && certs.length > 0){ certs[0].checkValidity(); } else { originalTrustManager.checkServerTrusted(certs, authType); } } catch (CertificateException e) { Log.w(TAG, e.toString()); } } } }; } private SSLSocketFactory getSSLSocketFactory() throws CertificateException, KeyStoreException, IOException, NoSuchAlgorithmException, KeyManagementException { CertificateFactory cf = CertificateFactory.getInstance("X.509"); InputStream caInput = this.getClass().getClassLoader().getResourceAsStream("res/raw/cert.bks"); //Certificate ca = cf.generateCertificate(caInput); KeyStore keyStore = KeyStore.getInstance("BKS"); keyStore.load(caInput, "password".toCharArray()); //keyStore.setCertificateEntry("ca", ca); caInput.close(); String tmfAlgorithm = TrustManagerFactory.getDefaultAlgorithm(); TrustManagerFactory tmf = TrustManagerFactory.getInstance(tmfAlgorithm); tmf.init(keyStore); TrustManager[] wrappedTrustManagers = getWrappedTrustManagers(tmf.getTrustManagers()); SSLContext sslContext = SSLContext.getInstance("TLS"); sslContext.init(null, wrappedTrustManagers, null); return sslContext.getSocketFactory(); } public List<String> getFiles() { return files; } public void setFiles(List<String> files) { this.files = files; } public void setProgressListener(ProgressListener mProgress) { this.mProgress = mProgress; } public void setResponseListener(ResponseListener mResponse) { this.mResponse = mResponse; } public void setErrorListener(ErrorListener mError) { this.mError = mError; } public interface ResponseListener{ void onResponse(String response); } public interface ErrorListener{ void onError(VolleyError error); } public interface ProgressListener{ void onProgress(int percent); } }
And then I use it, for example in Activity:
try{ Map<String, String> mParams = new HashMap<>(); mParams.put("lat", String.valueOf(params[0])); mParams.put("lon", String.valueOf(params[1])); final CountDownLatch countDownLatch = new CountDownLatch(1); final Object[] responseHolder = new Object[1]; StringRequest request = StringRequest.getInstance(); request.setResponseListener(new StringRequest.ResponseListener() { @Override public void onResponse(String response) { responseHolder[0] = response; countDownLatch.countDown(); } }); request.setErrorListener(new StringRequest.ErrorListener() { @Override public void onError(VolleyError error) { responseHolder[0] = error; countDownLatch.countDown(); } }); request.createRequest(TAG, URL, mParams); try { countDownLatch.await(); }catch (InterruptedException e){ throw new RuntimeException(e); } if(responseHolder[0] instanceof VolleyError){ VolleyError volleyError = (VolleyError)responseHolder[0]; Log.e(getClass().getName(), volleyError.toString()); }else{ String response = (String)responseHolder[0]; try { JSONObject mJson = new JSONObject(response); try { if (mJson.getString("status").equals("OK")) { try { User user = AppSettings.getmUser(); user.setHomeLat(Double.parseDouble(String.valueOf(params[0]))); user.setHomeLon(Double.parseDouble(String.valueOf(params[1]))); AppSettings.setmUser(user); Log.i(getClass().getName(), "Get location: " + String.valueOf(params[0]) + ":" + String.valueOf(params[1])); return true; }catch(Exception ex){ Log.e(this.getClass().getSimpleName(), "Double convert Exception", e); } } else if (mJson.getString("status").equals("BAD")) { Log.i(getClass().getName(), "Error " + mJson.getInt("statusCode") + " " + mJson.getString("message")); } } catch (JSONException e) { Log.e(getClass().getName(), "JSON Exception1", e); throw e; } } catch (JSONException e) { e.printStackTrace(); } } }catch(Exception e){ this.e = e; } If you stop using singleton, it works fine, but Volley keeps all requests in memory https://stackoverflow.com/questions/25868608/volley-framewok-request-keeps-objects-in-memory and the application hangs after about half a day of intensive work .