There is a very good library that handles all that plus has resume capability for cases when the network goes offline for some unknown reason.
The android library is called PRDownloader and is available on Github here:
https://github.com/MindorksOpenSource/PRDownloader
first you need to add it to your gradle file, like this (the current version os 0.6.0)
implementation 'com.mindorks.android:prdownloader:0.6.0'
After that, one can use it as shown below in a class I've implemented f the apps i developed. It uses a progress dialog and shows the percentage downloaded and, as a said above, has the ability to pickup the download later for cases when the network goes offline or the user quits the app.
One can adjust it according to specific needs, bellow is the code:
public class DownloadManager {
private MainActivity activity;
private ProgressDialog progressDialog;
private int downloadStatus;
private String filename="";
private static String dirPath;
private String URL = "https://someurl.com/dummyfile.pdf";
public DownloadManager(MainActivity _activity){
this.activity=_activity;
dirPath = Utils.getRootDirPath(activity);
downloadStatus=0;
}
public void setDownloadUrl(String url){
this.URL=url;
}
public String getFileNameDirPath(){
return dirPath+"/"+filename;
};
public void setFilename(String filename){
this.filename=filename;
}
public String getFilename(){
return this.filename;
}
public String getDirectoryPath(){
return this.filename;
}
public void startFileDownload(){
if (Status.RUNNING == PRDownloader.getStatus(downloadStatus)) {
PRDownloader.pause(downloadStatus);
return;
}
this.progressDialog = new ProgressDialog(this.activity);
this.progressDialog.setIndeterminate(true);
this.progressDialog.setTitle("Title");
this.progressDialog.setMessage("Downloading file...");
this.progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
this.progressDialog.setCancelable(false);
this.progressDialog.setMax(100);
this.progressDialog.show();
if (Status.PAUSED == PRDownloader.getStatus(downloadStatus)) {
PRDownloader.resume(downloadStatus);
return;
}
downloadStatus = PRDownloader.download(URL, dirPath, this.filename)
.build()
.setOnStartOrResumeListener(new OnStartOrResumeListener() {
@Override
public void onStartOrResume() {
progressDialog.setIndeterminate(false);
}
})
.setOnPauseListener(new OnPauseListener() {
@Override
public void onPause() {
}
})
.setOnCancelListener(new OnCancelListener() {
@Override
public void onCancel() {
progressDialog.setProgress(0);
downloadStatus = 0;
progressDialog.setIndeterminate(false);
progressDialog.dismiss();
}
})
.setOnProgressListener(new OnProgressListener() {
@Override
public void onProgress(Progress progress) {
long progressPercent = progress.currentBytes * 100 / progress.totalBytes;
progressDialog.setProgress((int) progressPercent);
progressDialog.setIndeterminate(false);
}
})
.start(new OnDownloadListener() {
@Override
public void onDownloadComplete() {
progressDialog.dismiss();
activity.fragmentManagement.setCurrentFragment("MapFragment");
}
@Override
public void onError(Error error) {
Toast.makeText(activity, "Error downloading file", Toast.LENGTH_SHORT).show();
progressDialog.setProgress(0);
downloadStatus = 0;
progressDialog.setIndeterminate(false);
progressDialog.dismiss();
}
});
}
public static final class Utils {
private Utils() {
// no instance
}
public static String getRootDirPath(Context context) {
if (Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) {
File file = ContextCompat.getExternalFilesDirs(context.getApplicationContext(),
null)[0];
return file.getAbsolutePath();
} else {
return context.getApplicationContext().getFilesDir().getAbsolutePath();
}
}
public static String getProgressDisplayLine(long currentBytes, long totalBytes) {
return getBytesToMBString(currentBytes) + "/" + getBytesToMBString(totalBytes);
}
private static String getBytesToMBString(long bytes){
return String.format(Locale.ENGLISH, "%.2fMb", bytes / (1024.00 * 1024.00));
}
}
}