@Streaming
@GET
Call<ResponseBody> downloadSong(@Url String url);
Above code is used to download file asynchronously using retrofit. I want get the progress of download, if there any possibility of pause/ resume please answer that too
The interface for Retrofit REST service, in this case, the GET, the @Streaming enables the downloading for large file. public interface RetrofitInterface { @Streaming @GET Call<ResponseBody> downloadFileByUrl(@Url String fileUrl); }
Retrofit is a type-safe HTTP networking library used for Android and Java. Retrofit was even better since it was super fast, offered better functionality, and even simpler syntax. Most developers since then have switched to using Retrofit to make API requests.
Retrofit is a type-safe REST client for Android, Java and Kotlin developed by Square. The library provides a powerful framework for authenticating and interacting with APIs and sending network requests with OkHttp.
At last I got my answer.
For that we need to use rxjava along with retrofit.
DownloadProgressListener.java
public interface DownloadProgressListener {
void update(long bytesRead, long contentLength, boolean done);
}
DownloadProgressResponseBody.java
public class DownloadProgressResponseBody extends ResponseBody {
private ResponseBody responseBody;
private DownloadProgressListener progressListener;
private BufferedSource bufferedSource;
public DownloadProgressResponseBody(ResponseBody responseBody,
DownloadProgressListener progressListener) {
this.responseBody = responseBody;
this.progressListener = progressListener;
}
@Override
public MediaType contentType() {
return responseBody.contentType();
}
@Override
public long contentLength() {
return responseBody.contentLength();
}
@Override
public BufferedSource source() {
if (bufferedSource == null) {
bufferedSource = Okio.buffer(source(responseBody.source()));
}
return bufferedSource;
}
private Source source(Source source) {
return new ForwardingSource(source) {
long totalBytesRead = 0L;
@Override
public long read(Buffer sink, long byteCount) throws IOException {
long bytesRead = super.read(sink, byteCount);
// read() returns the number of bytes read, or -1 if this source is exhausted.
totalBytesRead += bytesRead != -1 ? bytesRead : 0;
if (null != progressListener) {
progressListener.update(totalBytesRead, responseBody.contentLength(), bytesRead == -1);
}
return bytesRead;
}
};
}
}
DownloadProgressInterceptor.java
public class DownloadProgressInterceptor implements Interceptor {
private DownloadProgressListener listener;
public DownloadProgressInterceptor(DownloadProgressListener listener) {
this.listener = listener;
}
@Override
public Response intercept(Chain chain) throws IOException {
Response originalResponse = chain.proceed(chain.request());
return originalResponse.newBuilder()
.body(new DownloadProgressResponseBody(originalResponse.body(), listener))
.build();
}
}
Download.java
public class Download implements Parcelable {
private int progress;
private long currentFileSize;
private long totalFileSize;
public int getProgress() {
return progress;
}
public void setProgress(int progress) {
this.progress = progress;
}
public long getCurrentFileSize() {
return currentFileSize;
}
public void setCurrentFileSize(long currentFileSize) {
this.currentFileSize = currentFileSize;
}
public long getTotalFileSize() {
return totalFileSize;
}
public void setTotalFileSize(long totalFileSize) {
this.totalFileSize = totalFileSize;
}
@Override
public int describeContents() {
return 0;
}
@Override
public void writeToParcel(Parcel dest, int flags) {
dest.writeInt(this.progress);
dest.writeLong(this.currentFileSize);
dest.writeLong(this.totalFileSize);
}
public Download() {
}
protected Download(Parcel in) {
this.progress = in.readInt();
this.currentFileSize = in.readLong();
this.totalFileSize = in.readLong();
}
public static final Parcelable.Creator<Download> CREATOR = new Parcelable.Creator<Download>() {
@Override
public Download createFromParcel(Parcel source) {
return new Download(source);
}
@Override
public Download[] newArray(int size) {
return new Download[size];
}
};
}
DownloadService.java
public interface DownloadService {
@Streaming
@GET
Observable<ResponseBody> download(@Url String url);
}
DownloadAPI.java
public class DownloadAPI {
private static final String TAG = "DownloadAPI";
private static final int DEFAULT_TIMEOUT = 15;
public Retrofit retrofit;
public DownloadAPI(String url, DownloadProgressListener listener) {
DownloadProgressInterceptor interceptor = new DownloadProgressInterceptor(listener);
OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(interceptor)
.retryOnConnectionFailure(true)
.connectTimeout(DEFAULT_TIMEOUT, TimeUnit.SECONDS)
.build();
retrofit = new Retrofit.Builder()
.baseUrl(url)
.client(client)
.addCallAdapterFactory(RxJavaCallAdapterFactory.create())
.build();
}
public void downloadAPK(@NonNull String url, final File file, Subscriber subscriber) {
Log.d(TAG, "downloadAPK: " + url);
retrofit.create(DownloadService.class)
.download(url)
.subscribeOn(Schedulers.io())
.unsubscribeOn(Schedulers.io())
.map(new Func1<ResponseBody, InputStream>() {
@Override
public InputStream call(ResponseBody responseBody) {
return responseBody.byteStream();
}
})
.observeOn(Schedulers.computation())
.doOnNext(new Action1<InputStream>() {
@Override
public void call(InputStream inputStream) {
try {
FileUtils.writeFile(inputStream, file);
} catch (IOException e) {
e.printStackTrace();
throw new CustomizeException(e.getMessage(), e);
}
}
})
.observeOn(AndroidSchedulers.mainThread())
.subscribe(subscriber);
}
}
Usage
DownloadProgressListener listener = new DownloadProgressListener() {
@Override
public void update(long bytesRead, long contentLength, boolean done) {
Download download = new Download();
download.setTotalFileSize(contentLength);
download.setCurrentFileSize(bytesRead);
int progress = (int) ((bytesRead * 100) / contentLength);
download.setProgress(progress);
sendNotification(download);
}
};
File outputFile = new File(Environment.getExternalStoragePublicDirectory
(Environment.DIRECTORY_DOWNLOADS), "file.apk");
String baseUrl = StringUtils.getHostName(apkUrl);
new DownloadAPI(baseUrl, listener).downloadAPK(apkUrl, outputFile, new Subscriber() {
@Override
public void onCompleted() {
downloadCompleted();
}
@Override
public void onError(Throwable e) {
e.printStackTrace();
downloadCompleted();
Log.e(TAG, "onError: " + e.getMessage());
}
@Override
public void onNext(Object o) {
}
});
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With