Can’t grab progress on http POST file upload (Android)

I have tried quite a lot in the last days and I think I have the answer to the initial question:

It’s not possible to grab a progress using HttpURLConnection because there is a bug / unusual behavior in Android:
http://code.google.com/p/android/issues/detail?id=3164#c6

It will be fixed post Froyo, which is not something one can wait for…

So, the only other option I found is to use the Apache HttpClient. The answer linked by papleu is correct, but it refers to general Java. The classes that are used there are not available in Android anymore (HttpClient 3.1 was part of the SDK, once). So, what you can do is add the libraries from HttpClient 4 (specifically apache-mime4j-0.6.jar and httpmime-4.0.1.jar) and use a combination of the first answer (by Tuler) and the last answer (by Hamy):

import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.charset.Charset;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;

public class CountingMultipartEntity extends MultipartEntity {

    private final ProgressListener listener;

    public CountingMultipartEntity(final ProgressListener listener) {
        super();
        this.listener = listener;
    }

    public CountingMultipartEntity(final HttpMultipartMode mode, final ProgressListener listener) {
        super(mode);
        this.listener = listener;
    }

    public CountingMultipartEntity(HttpMultipartMode mode, final String boundary,
            final Charset charset, final ProgressListener listener) {
        super(mode, boundary, charset);
        this.listener = listener;
    }

    @Override
    public void writeTo(final OutputStream outstream) throws IOException {
        super.writeTo(new CountingOutputStream(outstream, this.listener));
    }

    public static interface ProgressListener {
        void transferred(long num);
    }

    public static class CountingOutputStream extends FilterOutputStream {

        private final ProgressListener listener;
        private long transferred;

        public CountingOutputStream(final OutputStream out,
                final ProgressListener listener) {
            super(out);
            this.listener = listener;
            this.transferred = 0;
        }


        public void write(byte[] b, int off, int len) throws IOException {
            out.write(b, off, len);
            this.transferred += len;
            this.listener.transferred(this.transferred);
        }

        public void write(int b) throws IOException {
            out.write(b);
            this.transferred++;
            this.listener.transferred(this.transferred);
        }
    }
}

This works with HttpClient 4, but the downside is that my apk now has a size of 235 kb (it was 90 kb when I used the multipart upload described in my question) and, even worse, an installed app size of 735 kb (about 170 kb before).
That’s really awful. Only to get a progress during upload the app size is now more than 4 times as big as it was before.

Leave a Comment