studio programacion para herramientas fundamentos desarrollo con avanzado aplicaciones android okhttp okio

android - programacion - Seguimiento del progreso de la carga de archivos de varias partes mediante OKHTTP



manual android studio avanzado (3)

Estoy tratando de implementar una barra de progreso para indicar el progreso de una carga de archivos de varias partes.

He leído de un comentario sobre esta respuesta - https://stackoverflow.com/a/24285633/1022454 que tengo que envolver el receptor pasado a RequestBody y proporcionar una devolución de llamada que rastrea los bytes movidos.

Creé un RequestBody personalizado y envolví el receptor con una clase CustomSink; sin embargo, a través de la depuración puedo ver que RealBufferedSink ln 44 escribe los bytes y el método de escritura del receptor personalizado solo se ejecuta una vez, lo que no me permite rastrear los bytes movidos .

private class CustomRequestBody extends RequestBody { MediaType contentType; byte[] content; private CustomRequestBody(final MediaType contentType, final byte[] content) { this.contentType = contentType; this.content = content; } @Override public MediaType contentType() { return contentType; } @Override public long contentLength() { return content.length; } @Override public void writeTo(BufferedSink sink) throws IOException { CustomSink customSink = new CustomSink(sink); customSink.write(content); } } private class CustomSink implements BufferedSink { private static final String TAG = "CUSTOM_SINK"; BufferedSink bufferedSink; private CustomSink(BufferedSink bufferedSink) { this.bufferedSink = bufferedSink; } @Override public void write(Buffer source, long byteCount) throws IOException { Log.d(TAG, "source size: " + source.size() + " bytecount" + byteCount); bufferedSink.write(source, byteCount); } @Override public void flush() throws IOException { bufferedSink.flush(); } @Override public Timeout timeout() { return bufferedSink.timeout(); } @Override public void close() throws IOException { bufferedSink.close(); } @Override public Buffer buffer() { return bufferedSink.buffer(); } @Override public BufferedSink write(ByteString byteString) throws IOException { return bufferedSink.write(byteString); } @Override public BufferedSink write(byte[] source) throws IOException { return bufferedSink.write(source); } @Override public BufferedSink write(byte[] source, int offset, int byteCount) throws IOException { return bufferedSink.write(source, offset, byteCount); } @Override public long writeAll(Source source) throws IOException { return bufferedSink.writeAll(source); } @Override public BufferedSink writeUtf8(String string) throws IOException { return bufferedSink.writeUtf8(string); } @Override public BufferedSink writeString(String string, Charset charset) throws IOException { return bufferedSink.writeString(string, charset); } @Override public BufferedSink writeByte(int b) throws IOException { return bufferedSink.writeByte(b); } @Override public BufferedSink writeShort(int s) throws IOException { return bufferedSink.writeShort(s); } @Override public BufferedSink writeShortLe(int s) throws IOException { return bufferedSink.writeShortLe(s); } @Override public BufferedSink writeInt(int i) throws IOException { return bufferedSink.writeInt(i); } @Override public BufferedSink writeIntLe(int i) throws IOException { return bufferedSink.writeIntLe(i); } @Override public BufferedSink writeLong(long v) throws IOException { return bufferedSink.writeLong(v); } @Override public BufferedSink writeLongLe(long v) throws IOException { return bufferedSink.writeLongLe(v); } @Override public BufferedSink emitCompleteSegments() throws IOException { return bufferedSink.emitCompleteSegments(); } @Override public OutputStream outputStream() { return bufferedSink.outputStream(); } }

¿Alguien tiene un ejemplo de cómo voy a hacer esto?


¡Esto funciona genial!

Gradle

dependencies { compile ''io.github.lizhangqu:coreprogress:1.0.2'' } //wrap your original request body with progress RequestBody requestBody = ProgressHelper.withProgress(body, new ProgressUIListener()....}

El código de ejemplo completo aquí https://github.com/lizhangqu/CoreProgress


Tienes que crear un RequestBody personalizado y anular el método writeTo, y allí tienes que enviar tus archivos por el fregadero en segmentos. Es muy importante que descargue el fregadero después de cada segmento, de lo contrario, su barra de progreso se llenará rápidamente sin que el archivo se envíe realmente a través de la red, porque el contenido permanecerá en el fregadero (que actúa como un búfer).

public class CountingFileRequestBody extends RequestBody { private static final int SEGMENT_SIZE = 2048; // okio.Segment.SIZE private final File file; private final ProgressListener listener; private final String contentType; public CountingFileRequestBody(File file, String contentType, ProgressListener listener) { this.file = file; this.contentType = contentType; this.listener = listener; } @Override public long contentLength() { return file.length(); } @Override public MediaType contentType() { return MediaType.parse(contentType); } @Override public void writeTo(BufferedSink sink) throws IOException { Source source = null; try { source = Okio.source(file); long total = 0; long read; while ((read = source.read(sink.buffer(), SEGMENT_SIZE)) != -1) { total += read; sink.flush(); this.listener.transferred(total); } } finally { Util.closeQuietly(source); } } public interface ProgressListener { void transferred(long num); } }

Puede encontrar una implementación completa que admita la visualización del progreso en un AdapterView y también la cancelación de cargas en mi esencia: https://gist.github.com/eduardb/dd2dc530afd37108e1ac


  • Solo tenemos que crear un RequestBody personalizado, no es necesario implementar un BufferedSink personalizado. Podemos asignar el búfer Okio para leer desde el archivo de imagen y conectar este búfer al receptor.

Para ver un ejemplo, consulte la siguiente función createCustomRequestBody

public static RequestBody createCustomRequestBody(final MediaType contentType, final File file) { return new RequestBody() { @Override public MediaType contentType() { return contentType; } @Override public long contentLength() { return file.length(); } @Override public void writeTo(BufferedSink sink) throws IOException { Source source = null; try { source = Okio.source(file); //sink.writeAll(source); Buffer buf = new Buffer(); Long remaining = contentLength(); for (long readCount; (readCount = source.read(buf, 2048)) != -1; ) { sink.write(buf, readCount); Log.d(TAG, "source size: " + contentLength() + " remaining bytes: " + (remaining -= readCount)); } } catch (Exception e) { e.printStackTrace(); } } }; }

  • usar -

    .addPart( Headers.of("Content-Disposition", "form-data; name=/"image/""), createCustomRequestBody(MediaType.parse("image/png"), new File("test.jpg"))) .build()