When sending a file, I try to update the progress bar in the status bar via the callback of the Volley Plus and OkHTTP libraries, but when I update the system UI it hangs. I understand that these libraries use the main UI stream, but how can I update the progress bar in the service? If you do the same thing, but in the activity, then it works fine and there are no problems (the main thread). Unfortunately I can not use the Apache Http Client. Can there be alternative libraries with support for SSL and MultipartEntity?

OkHTTP

mUBuilder.setContentTitle("Upload image") .setContentText("") .setAutoCancel(false) .setContentIntent(PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT)) .setSmallIcon(R.drawable.ic_launcher); try { final File file = new File(IMAGE_PATH); final long totalSize = file.length(); RequestBody requestBody = new MultipartBody.Builder() .addPart(Headers.of("Content-Disposition", "form-data; name=\"image\"; filename=\"" + file.getName() + "\""), new CountingFileRequestBody(file, "image/*", new CountingFileRequestBody.ProgressListener() { @Override public void transferred(long num) { final float progress = (num / (float) totalSize) * 100; Log.d(TAG, "OUT THREAD: " + progress); //see in logs new Thread( new Runnable() { @Override public void run() { Log.d(TAG, "IN THREAD: " + progress); //not visible in the logs mUBuilder.setProgress(100,(int) progress, false); mNotifyManager.notify(AppSettings.SEND_DATA_NOTIF, mUBuilder.build()); } } ); } })) .build(); Request request = new Request.Builder() .url("http://posttestserver.com/post.php?dir=123") .post(requestBody) .build(); client.newCall(request).enqueue(new Callback() { @Override public void onFailure(Call call, IOException e) { e.printStackTrace(); } @Override public void onResponse(Call call, Response response) throws IOException { if (!response.isSuccessful()) throw new IOException("Unexpected code " + response); Headers responseHeaders = response.headers(); for (int i = 0, size = responseHeaders.size(); i < size; i++) { System.out.println(responseHeaders.name(i) + ": " + responseHeaders.value(i)); } mUBuilder.setContentTitle("Upload complete!"); mNotifyManager.notify(AppSettings.SEND_DATA_NOTIF, mUBuilder.build()); System.out.println(response.body().string()); } }); }catch(Exception e){ e.printStackTrace(); } 

CountingFileRequestBody.java from here https://stackoverflow.com/a/26376724/2127124

Volley Plus

 mNotifyManager = (NotificationManager) getApplicationContext().getSystemService(Context.NOTIFICATION_SERVICE); notificationIntent = new Intent(getApplicationContext(), NMainActivity.class); final NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext()); mBuilder.setContentTitle("Upload image") .setContentText("") .setAutoCancel(false) .setContentIntent(PendingIntent.getActivity(getApplicationContext(), 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT)) .setSmallIcon(R.drawable.ic_launcher); SimpleMultiPartRequest jsonRequest = new SimpleMultiPartRequest(Request.Method.POST, "http://posttestserver.com/post.php?dir=123", new Response.Listener<String>() { @Override public void onResponse(String response) { Log.i(getClass().getName(), response); mBuilder.setContentText("Upload image complete!"); mNotifyManager.notify(AppSettings.SEND_DATA_NOTIF, mBuilder.build()); } }, new Response.ErrorListener() { @Override public void onErrorResponse(VolleyError error) { Log.e(getClass().getName(), error.toString()); } }) { @Override protected Map<String, String> getParams() throws AuthFailureError { return mParams; } }; jsonRequest.addFile("images", (IMAGE_PATH); jsonRequest.setFixedStreamingMode(true); jsonRequest.setShouldCache(false); jsonRequest.setShouldRetryServerErrors(true); jsonRequest.setOnProgressListener(new Response.ProgressListener() { @Override public void onProgress(long transferredBytes, long totalSize) { final int percentage = (int) ((transferredBytes / ((float) totalSize)) * 100); mBuilder.setProgress(100, percentage, false); mNotifyManager.notify(AppSettings.SEND_DATA_NOTIF, mBuilder.build()); //freeze system UI } }); mRequestQueue = Volley.newRequestQueue(getApplicationContext()); mRequestQueue.add(jsonRequest); mRequestQueue.start(); 

    1 answer 1

    Found a simple solution to this problem!

    The original is from here https://stackoverflow.com/a/23107289/2127124

    A little fix code for OkHTTP:

     @Override public void transferred(final int progress) { handler.post(new Runnable() { @Override public void run() { mUBuilder.setProgress(100, progress, true); mNotifyManager.notify(AppSettings.SEND_DATA_NOTIF, mUBuilder.build()); } }); } 

    CountingFileRequestBody.java

     public class CountingFileRequestBody extends RequestBody { ... int latestPercentDone, percentDone; ... @Override public void writeTo(BufferedSink sink) throws IOException { ... while ((read = source.read(sink.buffer(), SEGMENT_SIZE)) != -1) { total += read; sink.flush(); latestPercentDone = (int) ((total / (float) file.length()) * 100); if (percentDone != latestPercentDone) { percentDone = latestPercentDone; this.listener.transferred(percentDone); } } } public interface ProgressListener { void transferred(int num); } } 

    Code for Volley Plus:

     jsonRequest.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; mUBuilder.setProgress(100, percentDone, false); mNotifyManager.notify(AppSettings.SEND_DATA_NOTIF, mUBuilder.build()); } } }); 

    You can also use this code:

     final File file = new File(event.getPath().getPath()); final long totalSize = file.length(); new AsyncTask<Void, Integer, String>() { @Override protected void onProgressUpdate(Integer... values) { mUBuilder.setProgress(100, values[0], false); mNotifyManager.notify(AppSettings.SEND_DATA_NOTIF, mUBuilder.build()); } @Override protected String doInBackground(Void... voids) { try{ final File file = new File(event.getPath().getPath()); final long totalSize = file.length(); HttpClient client = new DefaultHttpClient(); HttpPost post = new HttpPost("http://posttestserver.com/post.php?dir=123"); MultipartEntityBuilder builder = MultipartEntityBuilder.create(); builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); FileBody fb = new FileBody(file); builder.addPart("file", fb); final HttpEntity yourEntity = builder.build(); class ProgressiveEntity implements HttpEntity { @Override public void consumeContent() throws IOException { yourEntity.consumeContent(); } @Override public InputStream getContent() throws IOException, IllegalStateException { return yourEntity.getContent(); } @Override public Header getContentEncoding() { return yourEntity.getContentEncoding(); } @Override public long getContentLength() { return yourEntity.getContentLength(); } @Override public Header getContentType() { return yourEntity.getContentType(); } @Override public boolean isChunked() { return yourEntity.isChunked(); } @Override public boolean isRepeatable() { return yourEntity.isRepeatable(); } @Override public boolean isStreaming() { return yourEntity.isStreaming(); } @Override public void writeTo(OutputStream outstream) throws IOException { class ProxyOutputStream extends FilterOutputStream { public ProxyOutputStream(OutputStream proxy) { super(proxy); } public void write(int idx) throws IOException { out.write(idx); } public void write(byte[] bts) throws IOException { out.write(bts); } public void write(byte[] bts, int st, int end) throws IOException { out.write(bts, st, end); } public void flush() throws IOException { out.flush(); } public void close() throws IOException { out.close(); } } class ProgressiveOutputStream extends ProxyOutputStream { long totalSent; int latestPercentDone, percentDone; public ProgressiveOutputStream(OutputStream proxy) { super(proxy); totalSent = 0; } public void write(byte[] bts, int st, int end) throws IOException { totalSent += end; latestPercentDone = (int) ((totalSent / (float) totalSize) * 100); if (percentDone != latestPercentDone) { percentDone = latestPercentDone; publishProgress(percentDone); } out.write(bts, st, end); } } yourEntity.writeTo(new ProgressiveOutputStream(outstream)); } } ProgressiveEntity myEntity = new ProgressiveEntity(); post.setEntity(myEntity); HttpResponse response = client.execute(post); Log.d(TAG, response.toString()); }catch(Exception e){ e.printStackTrace(); } return null; } }.execute(); 

    Do not forget to add dependencies if you will use the last example:

     android { useLibrary 'org.apache.http.legacy' } dependencies { ... compile('org.apache.httpcomponents:httpcore:+') { exclude module: "httpclient" } compile('org.apache.httpcomponents:httpmime:4.3.6') { exclude module: "httpclient" } ... } 

    Tested on Android 6.0.1.