Question

I'm developing an app that allows to users to upload mediafiles(such as images, photos, videos) to server and I've got a little bit problem with large files - is too long to wait and view a progress bar in activity while its uploading and another problem - if app dies upload dies too so I need to transfer my uploading code to service. So here my troubles begins - if I'll transfer my upload code to server how can I send progress updates(%) to activity?

here's my upload method's code:

public static void uploadMovie(final HashMap<String, String> dataSource, final OnResponseListener finishedListener, final ProgressListener progressListener) {
    if (finishedListener != null) {
        new Thread(new Runnable() {
            public void run() {
                try {

                    //Prepare data-->

                    String boundary = getMD5(dataSource.size() + String.valueOf(System.currentTimeMillis()));
                    MultipartEntityBuilder multipartEntity = MultipartEntityBuilder.create();
                    multipartEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
                    multipartEntity.setCharset(Charset.forName("UTF-8"));
                    for (String key : dataSource.keySet()) {
                        if (key.equals(MoviesFragmentAdd.USERFILE)) {
                            FileBody userFile = new FileBody(new File(dataSource.get(key)));
                            multipartEntity.addPart(key, userFile);
                            continue;
                        }
                        multipartEntity.addPart(key, new StringBody(dataSource.get(key), ContentType.APPLICATION_JSON));
                    }
                    HttpEntity entity = multipartEntity.build();
                    //<--

                    //Prepare Connection-->

                    trustAllHosts();
                    HttpsURLConnection conn = (HttpsURLConnection) new URL(SAKH_URL_API + "/video/addForm/").openConnection();
                    conn.setUseCaches(false);
                    conn.setDoOutput(true);
                    conn.setDoInput(true);
                    conn.setRequestMethod("POST");
                    conn.setRequestProperty("Accept-Charset", "UTF-8");
                    conn.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);
                    conn.setRequestProperty("Content-length", entity.getContentLength() + "");
                    conn.setRequestProperty(entity.getContentType().getName(), entity.getContentType().getValue());
                    conn.connect();


                    //<--
                    // Upload-->


                    OutputStream os = conn.getOutputStream();
                    ByteArrayOutputStream baos = new ByteArrayOutputStream();
                    entity.writeTo(baos);
                    baos.close();
                    byte[] payload = baos.toByteArray();
                    baos = null;
                    int totalSize = payload.length;
                    int bytesTransferred = 0;
                    int chunkSize = 2000;

                    while (bytesTransferred < totalSize) {
                        int nextChunkSize = totalSize - bytesTransferred;
                        if (nextChunkSize > chunkSize) {
                            nextChunkSize = chunkSize;
                        }
                        os.write(payload, bytesTransferred, nextChunkSize);
                        bytesTransferred += nextChunkSize;

                        //Progress update-->
                        if (progressListener != null) {
                            progressListener.onProgressUpdate((100 * bytesTransferred / totalSize));
                        }
                        //<--

                    }

                    os.flush();

                    //<--
                    //Get server response-->
                    int status = conn.getResponseCode();
                    if (conn.getResponseCode() == HttpsURLConnection.HTTP_OK) {

                        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
                        JsonObject request = (JsonObject) gparser.parse(in.readLine());

                        if (!request.get("error").getAsBoolean()) {
                            finishedListener.onLoadFinished(new Object());
                        }
                    } else {
                        throw new IOException("Server returned non-OK status: " + status);
                    }

                    conn.disconnect();
                } catch (Exception e) {
                    e.printStackTrace();
                    finishedListener.onNotConnected();

                }
            }
        }).start();

    }
}   
Was it helpful?

Solution

1-Create a bindable service and implement the necessary Binder

Start your service BEFORE binding to it or in other case if your app is closed the service will also close

2-Expose a public function like StartDownload(url, IUpdateTarget) on your service.

3-Create an interface (IUpdateTarget) with a function like UpdateProgress(somevalues);

4-Implement the IUpdateTarget interface in the View which should receive the update notifications

5-Bind to the service and retrieve the running service's instance

6-Now you have the instance of your service, call to StartDownload passing the URL and the target view for notifications.

7-Whenever you must update the interface from the service call to UpdateProgress from the IUpdateProgress instance passed to the service (the target view).

Beware with cross-threading calls, remember that you must always update interface on main thread.

OTHER TIPS

Use Handler to send process

new Thread(new Runnable() {

    @Override
    public void run() {
        // TODO Auto-generated method stub
        android.os.Message msg = new android.os.Message();
        Bundle bundle = new Bundle();
        bundle.putInt("process", process);
        msg.setData(bundle);
        mHandler.sendMessage(msg);
    }
}).start();

Handler mHandler = new Handler() {
    public void handleMessage(android.os.Message msg) {
        int process = msg.getData().getInt("process");
    };
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top