Rectangle 27 1660

1. Use AsyncTask and show the download progress in a dialog

This method will allow you to execute some background processes and update the UI at the same time (in this case, we'll update a progress bar).

// declare the dialog as a member field of your activity
ProgressDialog mProgressDialog;

// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);

// execute this when the downloader must be fired
final DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");

mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
        downloadTask.cancel(true);
    }
});
AsyncTask
// usually, subclasses of AsyncTask are declared inside the activity class.
// that way, you can easily modify the UI thread from here
private class DownloadTask extends AsyncTask<String, Integer, String> {

    private Context context;
    private PowerManager.WakeLock mWakeLock;

    public DownloadTask(Context context) {
        this.context = context;
    }

    @Override
    protected String doInBackground(String... sUrl) {
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(sUrl[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            // expect HTTP 200 OK, so we don't mistakenly save error report
            // instead of the file
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "Server returned HTTP " + connection.getResponseCode()
                        + " " + connection.getResponseMessage();
            }

            // this will be useful to display download percentage
            // might be -1: server did not report the length
            int fileLength = connection.getContentLength();

            // download the file
            input = connection.getInputStream();
            output = new FileOutputStream("/sdcard/file_name.extension");

            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    input.close();
                    return null;
                }
                total += count;
                // publishing the progress....
                if (fileLength > 0) // only if total length is known
                    publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }
        } catch (Exception e) {
            return e.toString();
        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }

            if (connection != null)
                connection.disconnect();
        }
        return null;
    }

The method above (doInBackground) runs always on a background thread. You shouldn't do any UI tasks there. On the other hand, the onProgressUpdate and onPreExecute run on the UI thread, so there you can change the progress bar:

@Override
    protected void onPreExecute() {
        super.onPreExecute();
        // take CPU lock to prevent CPU from going off if the user 
        // presses the power button during download
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
             getClass().getName());
        mWakeLock.acquire();
        mProgressDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        // if we get here, length is known, now set indeterminate to false
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.setMax(100);
        mProgressDialog.setProgress(progress[0]);
    }

    @Override
    protected void onPostExecute(String result) {
        mWakeLock.release();
        mProgressDialog.dismiss();
        if (result != null)
            Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
        else
            Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
    }
<uses-permission android:name="android.permission.WAKE_LOCK" />

The big question here is: how do I update my activity from a service?. In the next example we are going to use two classes you may not be aware of: ResultReceiver and IntentService. ResultReceiver is the one that will allow us to update our thread from a service; IntentService is a subclass of Service which spawns a thread to do background work from there (you should know that a Service runs actually in the same thread of your app; when you extends Service, you must manually spawn new threads to run CPU blocking operations).

public class DownloadService extends IntentService {
    public static final int UPDATE_PROGRESS = 8344;
    public DownloadService() {
        super("DownloadService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        String urlToDownload = intent.getStringExtra("url");
        ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
        try {
            URL url = new URL(urlToDownload);
            URLConnection connection = url.openConnection();
            connection.connect();
            // this will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(connection.getInputStream());
            OutputStream output = new FileOutputStream("/sdcard/BarcodeScanner-debug.apk");

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                Bundle resultData = new Bundle();
                resultData.putInt("progress" ,(int) (total * 100 / fileLength));
                receiver.send(UPDATE_PROGRESS, resultData);
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Bundle resultData = new Bundle();
        resultData.putInt("progress" ,100);
        receiver.send(UPDATE_PROGRESS, resultData);
    }
}

Add the service to your manifest:

<service android:name=".DownloadService"/>
// initialize the progress dialog like in the first example

// this is how you fire the downloader
mProgressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url", "url of the file to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);
ResultReceiver
private class DownloadReceiver extends ResultReceiver{
    public DownloadReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);
        if (resultCode == DownloadService.UPDATE_PROGRESS) {
            int progress = resultData.getInt("progress");
            mProgressDialog.setProgress(progress);
            if (progress == 100) {
                mProgressDialog.dismiss();
            }
        }
    }
}

Groundy is a library that basically helps you run pieces of code in a background service, and it is based on the ResultReceiver concept shown above. This library is deprecated at the moment. This is how the whole code would look like:

The activity where you are showing the dialog...

public class MainActivity extends Activity {

    private ProgressDialog mProgressDialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        findViewById(R.id.btn_download).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                String url = ((EditText) findViewById(R.id.edit_url)).getText().toString().trim();
                Bundle extras = new Bundler().add(DownloadTask.PARAM_URL, url).build();
                Groundy.create(DownloadExample.this, DownloadTask.class)
                        .receiver(mReceiver)
                        .params(extras)
                        .queue();

                mProgressDialog = new ProgressDialog(MainActivity.this);
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                mProgressDialog.setCancelable(false);
                mProgressDialog.show();
            }
        });
    }

    private ResultReceiver mReceiver = new ResultReceiver(new Handler()) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            super.onReceiveResult(resultCode, resultData);
            switch (resultCode) {
                case Groundy.STATUS_PROGRESS:
                    mProgressDialog.setProgress(resultData.getInt(Groundy.KEY_PROGRESS));
                    break;
                case Groundy.STATUS_FINISHED:
                    Toast.makeText(DownloadExample.this, R.string.file_downloaded, Toast.LENGTH_LONG);
                    mProgressDialog.dismiss();
                    break;
                case Groundy.STATUS_ERROR:
                    Toast.makeText(DownloadExample.this, resultData.getString(Groundy.KEY_ERROR), Toast.LENGTH_LONG).show();
                    mProgressDialog.dismiss();
                    break;
            }
        }
    };
}

A GroundyTask implementation used by Groundy to download the file and show the progress:

public class DownloadTask extends GroundyTask {    
    public static final String PARAM_URL = "com.groundy.sample.param.url";

    @Override
    protected boolean doInBackground() {
        try {
            String url = getParameters().getString(PARAM_URL);
            File dest = new File(getContext().getFilesDir(), new File(url).getName());
            DownloadUtils.downloadFile(getContext(), url, dest, DownloadUtils.getDownloadListenerForTask(this));
            return true;
        } catch (Exception pokemon) {
            return false;
        }
    }
}
<service android:name="com.codeslap.groundy.GroundyService"/>

It couldn't be easier I think. Just grab the latest jar from Github and you are ready to go. Keep in mind that Groundy's main purpose is to make calls to external REST apis in a background service and post results to the UI with easily. If you are doing something like that in your app, it could be really useful.

GingerBread brought a new feature, DownloadManager, which allows you to download files easily and delegate the hard work of handling threads, streams, etc. to the system.

First, let's see a utility method:

/**
 * @param context used to check the device version and DownloadManager information
 * @return true if the download manager is available
 */
public static boolean isDownloadManagerAvailable(Context context) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        return true;
    }
    return false;
}

Method's name explains it all. Once you are sure DownloadManager is available, you can do something like this:

String url = "url you want to download";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");
request.setTitle("Some title");
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext");

// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);

Download progress will be showing in the notification bar.

First and second methods are just the tip of the iceberg. There are lots of things you have to keep in mind if you want your app to be robust. Here is a brief list:

  • Make sure you have the right permissions (INTERNET and WRITE_EXTERNAL_STORAGE); also ACCESS_NETWORK_STATE if you want to check internet availability.
  • Make sure the directory were you are going to download files exist and has write permissions.
  • If download is too big you may want to implement a way to resume the download if previous attempts failed.

Unless you need detailed control of the download process, then consider using DownloadManager (3) because it already handles most of the items listed above.

But also consider that your needs may change. For example, DownloadManager does no response caching. It will blindly download the same big file multiple times. There's no easy way to fix it after the fact. Where if you start with a basic HttpURLConnection (1, 2), then all you need is to add an HttpResponseCache. So the initial effort of learning the basic, standard tools can be a good investment.

DownloadManager is part of the OS, which means it will always be available in GB+ and cannot be uninstalled.

There is a problem in Cristian's answer. Because code at "1. Use AsyncTask and show the download progress in a dialog" does connection.connect(); then InputStream input = new BufferedInputStream(url.openStream()); code makes 2 connections to the server. I have managed to change this behavior by updating the code as follows InputStream input = new BufferedInputStream(connection.getInputStream());

i wish android documentation was this concise.

Suggested to close() the streams (input and output) in finally instead of try, otherwise if any exception is thrown before close(), you have unclosed streams hanging around.

sdcard/
Environment.getExternalStorageDirectory()

java - Download a file with Android, and showing the progress in a Pro...

java android download android-asynctask
Rectangle 27 1647

1. Use AsyncTask and show the download progress in a dialog

This method will allow you to execute some background processes and update the UI at the same time (in this case, we'll update a progress bar).

// declare the dialog as a member field of your activity
ProgressDialog mProgressDialog;

// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);

// execute this when the downloader must be fired
final DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");

mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
        downloadTask.cancel(true);
    }
});
AsyncTask
// usually, subclasses of AsyncTask are declared inside the activity class.
// that way, you can easily modify the UI thread from here
private class DownloadTask extends AsyncTask<String, Integer, String> {

    private Context context;
    private PowerManager.WakeLock mWakeLock;

    public DownloadTask(Context context) {
        this.context = context;
    }

    @Override
    protected String doInBackground(String... sUrl) {
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(sUrl[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            // expect HTTP 200 OK, so we don't mistakenly save error report
            // instead of the file
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "Server returned HTTP " + connection.getResponseCode()
                        + " " + connection.getResponseMessage();
            }

            // this will be useful to display download percentage
            // might be -1: server did not report the length
            int fileLength = connection.getContentLength();

            // download the file
            input = connection.getInputStream();
            output = new FileOutputStream("/sdcard/file_name.extension");

            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    input.close();
                    return null;
                }
                total += count;
                // publishing the progress....
                if (fileLength > 0) // only if total length is known
                    publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }
        } catch (Exception e) {
            return e.toString();
        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }

            if (connection != null)
                connection.disconnect();
        }
        return null;
    }

The method above (doInBackground) runs always on a background thread. You shouldn't do any UI tasks there. On the other hand, the onProgressUpdate and onPreExecute run on the UI thread, so there you can change the progress bar:

@Override
    protected void onPreExecute() {
        super.onPreExecute();
        // take CPU lock to prevent CPU from going off if the user 
        // presses the power button during download
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
             getClass().getName());
        mWakeLock.acquire();
        mProgressDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        // if we get here, length is known, now set indeterminate to false
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.setMax(100);
        mProgressDialog.setProgress(progress[0]);
    }

    @Override
    protected void onPostExecute(String result) {
        mWakeLock.release();
        mProgressDialog.dismiss();
        if (result != null)
            Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
        else
            Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
    }
<uses-permission android:name="android.permission.WAKE_LOCK" />

The big question here is: how do I update my activity from a service?. In the next example we are going to use two classes you may not be aware of: ResultReceiver and IntentService. ResultReceiver is the one that will allow us to update our thread from a service; IntentService is a subclass of Service which spawns a thread to do background work from there (you should know that a Service runs actually in the same thread of your app; when you extends Service, you must manually spawn new threads to run CPU blocking operations).

public class DownloadService extends IntentService {
    public static final int UPDATE_PROGRESS = 8344;
    public DownloadService() {
        super("DownloadService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        String urlToDownload = intent.getStringExtra("url");
        ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
        try {
            URL url = new URL(urlToDownload);
            URLConnection connection = url.openConnection();
            connection.connect();
            // this will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(connection.getInputStream());
            OutputStream output = new FileOutputStream("/sdcard/BarcodeScanner-debug.apk");

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                Bundle resultData = new Bundle();
                resultData.putInt("progress" ,(int) (total * 100 / fileLength));
                receiver.send(UPDATE_PROGRESS, resultData);
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Bundle resultData = new Bundle();
        resultData.putInt("progress" ,100);
        receiver.send(UPDATE_PROGRESS, resultData);
    }
}

Add the service to your manifest:

<service android:name=".DownloadService"/>
// initialize the progress dialog like in the first example

// this is how you fire the downloader
mProgressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url", "url of the file to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);
ResultReceiver
private class DownloadReceiver extends ResultReceiver{
    public DownloadReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);
        if (resultCode == DownloadService.UPDATE_PROGRESS) {
            int progress = resultData.getInt("progress");
            mProgressDialog.setProgress(progress);
            if (progress == 100) {
                mProgressDialog.dismiss();
            }
        }
    }
}

Groundy is a library that basically helps you run pieces of code in a background service, and it is based on the ResultReceiver concept shown above. This library is deprecated at the moment. This is how the whole code would look like:

Groundy is a library a friend and I wrote time ago. It basically helps you run pieces of code in a background service, and it is based on the ResultReceiver concept shown above. This is how the whole code would look like...

The activity where you are showing the dialog...

public class MainActivity extends Activity {

    private ProgressDialog mProgressDialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        findViewById(R.id.btn_download).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                String url = ((EditText) findViewById(R.id.edit_url)).getText().toString().trim();
                Bundle extras = new Bundler().add(DownloadTask.PARAM_URL, url).build();
                Groundy.create(DownloadExample.this, DownloadTask.class)
                        .receiver(mReceiver)
                        .params(extras)
                        .queue();

                mProgressDialog = new ProgressDialog(MainActivity.this);
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                mProgressDialog.setCancelable(false);
                mProgressDialog.show();
            }
        });
    }

    private ResultReceiver mReceiver = new ResultReceiver(new Handler()) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            super.onReceiveResult(resultCode, resultData);
            switch (resultCode) {
                case Groundy.STATUS_PROGRESS:
                    mProgressDialog.setProgress(resultData.getInt(Groundy.KEY_PROGRESS));
                    break;
                case Groundy.STATUS_FINISHED:
                    Toast.makeText(DownloadExample.this, R.string.file_downloaded, Toast.LENGTH_LONG);
                    mProgressDialog.dismiss();
                    break;
                case Groundy.STATUS_ERROR:
                    Toast.makeText(DownloadExample.this, resultData.getString(Groundy.KEY_ERROR), Toast.LENGTH_LONG).show();
                    mProgressDialog.dismiss();
                    break;
            }
        }
    };
}

A GroundyTask implementation used by Groundy to download the file and show the progress:

public class DownloadTask extends GroundyTask {    
    public static final String PARAM_URL = "com.groundy.sample.param.url";

    @Override
    protected boolean doInBackground() {
        try {
            String url = getParameters().getString(PARAM_URL);
            File dest = new File(getContext().getFilesDir(), new File(url).getName());
            DownloadUtils.downloadFile(getContext(), url, dest, DownloadUtils.getDownloadListenerForTask(this));
            return true;
        } catch (Exception pokemon) {
            return false;
        }
    }
}
<service android:name="com.codeslap.groundy.GroundyService"/>

It couldn't be easier I think. Just grab the latest jar from Github and you are ready to go. Keep in mind that Groundy's main purpose is to make calls to external REST apis in a background service and post results to the UI with easily. If you are doing something like that in your app, it could be really useful.

This method is awesome, you do not have to worry about downloading the file manually, handle threads, streams, etc. GingerBread brought a new feature: DownloadManager which allows you to download files easily and delegate the hard work to the system.

GingerBread brought a new feature, DownloadManager, which allows you to download files easily and delegate the hard work of handling threads, streams, etc. to the system.

First, let's see a utility method:

/**
 * @param context used to check the device version and DownloadManager information
 * @return true if the download manager is available
 */
public static boolean isDownloadManagerAvailable(Context context) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        return true;
    }
    return false;
}

Method's name explains it all. Once you are sure DownloadManager is available, you can do something like this:

String url = "url you want to download";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");
request.setTitle("Some title");
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext");

// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);

Download progress will be showing in the notification bar.

First and second methods are just the tip of the iceberg. There are lots of things you have to keep in mind if you want your app to be robust. Here is a brief list:

  • Make sure you have the right permissions (INTERNET and WRITE_EXTERNAL_STORAGE); also ACCESS_NETWORK_STATE if you want to check internet availability.
  • Make sure the directory were you are going to download files exist and has write permissions.
  • If download is too big you may want to implement a way to resume the download if previous attempts failed.

Unless you need detailed control of the download process, then consider using DownloadManager (3) because it already handles most of the items listed above.

Unless you want to have full control over the download process, I highly recommend using DownloadManager which already handles most of the items listed above.

But also consider that your needs may change. For example, DownloadManager does no response caching. It will blindly download the same big file multiple times. There's no easy way to fix it after the fact. Where if you start with a basic HttpURLConnection (1, 2), then all you need is to add an HttpResponseCache. So the initial effort of learning the basic, standard tools can be a good investment.

DownloadManager is part of the OS, which means it will always be available in GB+ and cannot be uninstalled.

There is a problem in Cristian's answer. Because code at "1. Use AsyncTask and show the download progress in a dialog" does connection.connect(); then InputStream input = new BufferedInputStream(url.openStream()); code makes 2 connections to the server. I have managed to change this behavior by updating the code as follows InputStream input = new BufferedInputStream(connection.getInputStream());

i wish android documentation was this concise.

Suggested to close() the streams (input and output) in finally instead of try, otherwise if any exception is thrown before close(), you have unclosed streams hanging around.

sdcard/
Environment.getExternalStorageDirectory()

java - Download a file with Android, and showing the progress in a Pro...

java android download android-asynctask
Rectangle 27 1645

1. Use AsyncTask and show the download progress in a dialog

This method will allow you to execute some background processes and update the UI at the same time (in this case, we'll update a progress bar).

// declare the dialog as a member field of your activity
ProgressDialog mProgressDialog;

// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);

// execute this when the downloader must be fired
final DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");

mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
        downloadTask.cancel(true);
    }
});
AsyncTask
// usually, subclasses of AsyncTask are declared inside the activity class.
// that way, you can easily modify the UI thread from here
private class DownloadTask extends AsyncTask<String, Integer, String> {

    private Context context;
    private PowerManager.WakeLock mWakeLock;

    public DownloadTask(Context context) {
        this.context = context;
    }

    @Override
    protected String doInBackground(String... sUrl) {
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(sUrl[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            // expect HTTP 200 OK, so we don't mistakenly save error report
            // instead of the file
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "Server returned HTTP " + connection.getResponseCode()
                        + " " + connection.getResponseMessage();
            }

            // this will be useful to display download percentage
            // might be -1: server did not report the length
            int fileLength = connection.getContentLength();

            // download the file
            input = connection.getInputStream();
            output = new FileOutputStream("/sdcard/file_name.extension");

            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    input.close();
                    return null;
                }
                total += count;
                // publishing the progress....
                if (fileLength > 0) // only if total length is known
                    publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }
        } catch (Exception e) {
            return e.toString();
        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }

            if (connection != null)
                connection.disconnect();
        }
        return null;
    }

The method above (doInBackground) runs always on a background thread. You shouldn't do any UI tasks there. On the other hand, the onProgressUpdate and onPreExecute run on the UI thread, so there you can change the progress bar:

@Override
    protected void onPreExecute() {
        super.onPreExecute();
        // take CPU lock to prevent CPU from going off if the user 
        // presses the power button during download
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
             getClass().getName());
        mWakeLock.acquire();
        mProgressDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        // if we get here, length is known, now set indeterminate to false
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.setMax(100);
        mProgressDialog.setProgress(progress[0]);
    }

    @Override
    protected void onPostExecute(String result) {
        mWakeLock.release();
        mProgressDialog.dismiss();
        if (result != null)
            Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
        else
            Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
    }
<uses-permission android:name="android.permission.WAKE_LOCK" />

The big question here is: how do I update my activity from a service?. In the next example we are going to use two classes you may not be aware of: ResultReceiver and IntentService. ResultReceiver is the one that will allow us to update our thread from a service; IntentService is a subclass of Service which spawns a thread to do background work from there (you should know that a Service runs actually in the same thread of your app; when you extends Service, you must manually spawn new threads to run CPU blocking operations).

public class DownloadService extends IntentService {
    public static final int UPDATE_PROGRESS = 8344;
    public DownloadService() {
        super("DownloadService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        String urlToDownload = intent.getStringExtra("url");
        ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
        try {
            URL url = new URL(urlToDownload);
            URLConnection connection = url.openConnection();
            connection.connect();
            // this will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(connection.getInputStream());
            OutputStream output = new FileOutputStream("/sdcard/BarcodeScanner-debug.apk");

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                Bundle resultData = new Bundle();
                resultData.putInt("progress" ,(int) (total * 100 / fileLength));
                receiver.send(UPDATE_PROGRESS, resultData);
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Bundle resultData = new Bundle();
        resultData.putInt("progress" ,100);
        receiver.send(UPDATE_PROGRESS, resultData);
    }
}

Add the service to your manifest:

<service android:name=".DownloadService"/>
// initialize the progress dialog like in the first example

// this is how you fire the downloader
mProgressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url", "url of the file to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);
ResultReceiver
private class DownloadReceiver extends ResultReceiver{
    public DownloadReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);
        if (resultCode == DownloadService.UPDATE_PROGRESS) {
            int progress = resultData.getInt("progress");
            mProgressDialog.setProgress(progress);
            if (progress == 100) {
                mProgressDialog.dismiss();
            }
        }
    }
}

Groundy is a library that basically helps you run pieces of code in a background service, and it is based on the ResultReceiver concept shown above. This library is deprecated at the moment. This is how the whole code would look like:

The activity where you are showing the dialog...

public class MainActivity extends Activity {

    private ProgressDialog mProgressDialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        findViewById(R.id.btn_download).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                String url = ((EditText) findViewById(R.id.edit_url)).getText().toString().trim();
                Bundle extras = new Bundler().add(DownloadTask.PARAM_URL, url).build();
                Groundy.create(DownloadExample.this, DownloadTask.class)
                        .receiver(mReceiver)
                        .params(extras)
                        .queue();

                mProgressDialog = new ProgressDialog(MainActivity.this);
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                mProgressDialog.setCancelable(false);
                mProgressDialog.show();
            }
        });
    }

    private ResultReceiver mReceiver = new ResultReceiver(new Handler()) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            super.onReceiveResult(resultCode, resultData);
            switch (resultCode) {
                case Groundy.STATUS_PROGRESS:
                    mProgressDialog.setProgress(resultData.getInt(Groundy.KEY_PROGRESS));
                    break;
                case Groundy.STATUS_FINISHED:
                    Toast.makeText(DownloadExample.this, R.string.file_downloaded, Toast.LENGTH_LONG);
                    mProgressDialog.dismiss();
                    break;
                case Groundy.STATUS_ERROR:
                    Toast.makeText(DownloadExample.this, resultData.getString(Groundy.KEY_ERROR), Toast.LENGTH_LONG).show();
                    mProgressDialog.dismiss();
                    break;
            }
        }
    };
}

A GroundyTask implementation used by Groundy to download the file and show the progress:

public class DownloadTask extends GroundyTask {    
    public static final String PARAM_URL = "com.groundy.sample.param.url";

    @Override
    protected boolean doInBackground() {
        try {
            String url = getParameters().getString(PARAM_URL);
            File dest = new File(getContext().getFilesDir(), new File(url).getName());
            DownloadUtils.downloadFile(getContext(), url, dest, DownloadUtils.getDownloadListenerForTask(this));
            return true;
        } catch (Exception pokemon) {
            return false;
        }
    }
}
<service android:name="com.codeslap.groundy.GroundyService"/>

It couldn't be easier I think. Just grab the latest jar from Github and you are ready to go. Keep in mind that Groundy's main purpose is to make calls to external REST apis in a background service and post results to the UI with easily. If you are doing something like that in your app, it could be really useful.

GingerBread brought a new feature, DownloadManager, which allows you to download files easily and delegate the hard work of handling threads, streams, etc. to the system.

First, let's see a utility method:

/**
 * @param context used to check the device version and DownloadManager information
 * @return true if the download manager is available
 */
public static boolean isDownloadManagerAvailable(Context context) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        return true;
    }
    return false;
}

Method's name explains it all. Once you are sure DownloadManager is available, you can do something like this:

String url = "url you want to download";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");
request.setTitle("Some title");
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext");

// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);

Download progress will be showing in the notification bar.

First and second methods are just the tip of the iceberg. There are lots of things you have to keep in mind if you want your app to be robust. Here is a brief list:

  • Make sure you have the right permissions (INTERNET and WRITE_EXTERNAL_STORAGE); also ACCESS_NETWORK_STATE if you want to check internet availability.
  • Make sure the directory were you are going to download files exist and has write permissions.
  • If download is too big you may want to implement a way to resume the download if previous attempts failed.

Unless you need detailed control of the download process, then consider using DownloadManager (3) because it already handles most of the items listed above.

But also consider that your needs may change. For example, DownloadManager does no response caching. It will blindly download the same big file multiple times. There's no easy way to fix it after the fact. Where if you start with a basic HttpURLConnection (1, 2), then all you need is to add an HttpResponseCache. So the initial effort of learning the basic, standard tools can be a good investment.

DownloadManager is part of the OS, which means it will always be available in GB+ and cannot be uninstalled.

There is a problem in Cristian's answer. Because code at "1. Use AsyncTask and show the download progress in a dialog" does connection.connect(); then InputStream input = new BufferedInputStream(url.openStream()); code makes 2 connections to the server. I have managed to change this behavior by updating the code as follows InputStream input = new BufferedInputStream(connection.getInputStream());

i wish android documentation was this concise.

Suggested to close() the streams (input and output) in finally instead of try, otherwise if any exception is thrown before close(), you have unclosed streams hanging around.

sdcard/
Environment.getExternalStorageDirectory()

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

java - Download a file with Android, and showing the progress in a Pro...

java android download android-asynctask
Rectangle 27 5

What you are looking at is a Seekbar rather than a plain Progressbar. The circle indicator is called a thumb and you can add any image you like (as well as a custom progress bar also).

<SeekBar ...
    android:thumb="@drawable/your_thumb"
    android:progressDrawable="@drawable/progress_bar_layers"
 />

android - How to make custom progress bar with indicator image, like w...

android android-progressbar whatsapp
Rectangle 27 13

This is happening because when screen orientation rotates the Activity gets re-started. In this case you can add configChanges attribute in your tag in the AndroidManifest file to stop the re-creation of the Activity.

<activity android:name=".Activity_name"
          android:configChanges="orientation|keyboardHidden">

By, this your orientation can change will the progress bar is working and also it won't stop though the orientation changes.

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
            setContentView(R.layout.login_landscape);
        }
        else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            setContentView(R.layout.login);         
        }
    }

If i have 2 diff layout for potrait and landscape mode,how can i set the appropriate layout when orientation changes.Because when we make the activity as android:configChanges="orientation|keyboardHidden",it won't automatically change the layout on orientation change.

you can put that landscape xml file in res/layout-land folder and then it will automatically set that file when orientation changes, no need to write any code for that to detect the orientation in your activity file..

In normal scenario it will automatically set the file when orientation changes,but when we make it as android:configChanges="orientation|keyboardHidden", it doent change automatically.

Yep,But i cannot fix a particular orientation.It should support both potrait and landscape.

@androidGuy Please come to casual chat room so that we can discuss further on your issue...I am trying something else for your issue.

How to stop changing the orientation when a progress bar is spinning i...

android progress-bar screen-orientation orientation-changes
Rectangle 27 13

This is happening because when screen orientation rotates the Activity gets re-started. In this case you can add configChanges attribute in your tag in the AndroidManifest file to stop the re-creation of the Activity.

<activity android:name=".Activity_name"
          android:configChanges="orientation|keyboardHidden">

By, this your orientation can change will the progress bar is working and also it won't stop though the orientation changes.

@Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        if(newConfig.orientation == Configuration.ORIENTATION_LANDSCAPE){
            setContentView(R.layout.login_landscape);
        }
        else if (newConfig.orientation == Configuration.ORIENTATION_PORTRAIT) {
            setContentView(R.layout.login);         
        }
    }

If i have 2 diff layout for potrait and landscape mode,how can i set the appropriate layout when orientation changes.Because when we make the activity as android:configChanges="orientation|keyboardHidden",it won't automatically change the layout on orientation change.

you can put that landscape xml file in res/layout-land folder and then it will automatically set that file when orientation changes, no need to write any code for that to detect the orientation in your activity file..

In normal scenario it will automatically set the file when orientation changes,but when we make it as android:configChanges="orientation|keyboardHidden", it doent change automatically.

Yep,But i cannot fix a particular orientation.It should support both potrait and landscape.

@androidGuy Please come to casual chat room so that we can discuss further on your issue...I am trying something else for your issue.

How to stop changing the orientation when a progress bar is spinning i...

android progress-bar screen-orientation orientation-changes
Rectangle 27 9

and then

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

Don't think that it's broken when testing on the emulator, the ctrl+F11 shortcut ALWAYS change the screen orientation, without emulating sensors moves.

So you need not to stop the rotation for this solution. You should handle the progress bar. Here are some tutorials, which are useful for this purpose ..

And some time you looses data when orientation changes. So you can try these tutorials

How to stop changing the orientation when a progress bar is spinning i...

android progress-bar screen-orientation orientation-changes
Rectangle 27 9

and then

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);

Don't think that it's broken when testing on the emulator, the ctrl+F11 shortcut ALWAYS change the screen orientation, without emulating sensors moves.

So you need not to stop the rotation for this solution. You should handle the progress bar. Here are some tutorials, which are useful for this purpose ..

And some time you looses data when orientation changes. So you can try these tutorials

How to stop changing the orientation when a progress bar is spinning i...

android progress-bar screen-orientation orientation-changes
Rectangle 27 2

I added a ProgressDialog using the video time

final int msec = MediaPlayer.create(this, Uri.fromFile(new File(path))).getDuration();

 final ProgressDialog dialog = new ProgressDialog(this);
        dialog.setMax(msec);
        dialog.setMessage("Progress");
        dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        dialog.setProgress(0);
OnStart
ExecuteBinaryResponseHandler
dialog.show()
onProgress(String message)
@Override
public void onProgress(String message) {
    int start = message.indexOf("time=");
        int end = message.indexOf(" bitrate");
        if (start != -1 && end != -1) {
            String duration = message.substring(start + 5, end);
            if (duration != "") {
                try {
                    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
                    sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
                    dialog.setProgress((int)sdf.parse("1970-01-01 " + duration).getTime());                        
                }catch (ParseException e)
                {
                    e.printStackTrace();
                }
            }
    }
}

dismiss the dialog in the OnFinish() method

@Override
public void onFinish() {
    String s = System.currentTimeMillis() - MainActivity.this.startTime + "";
    dialog.dismiss();
}

How to add progress bar to FFMPEG android - Stack Overflow

android ffmpeg progress-bar
Rectangle 27 2

android:theme="@android:style/Theme.NoTitleBar.Fullscreen"

and if you want to do it through coding in Activity then you can use following code, in OnCreate() method of Activity.

requestWindowFeature(Window.FEATURE_NO_TITLE); 
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

Thanks Lucifer for your reply. But doing this will hide my progress bar from showing on my title bar. Do you have other options that will show the progress bar and hides the title bar after the webview finishes loading?

Android hiding the title bar after progress bar finishes loading - Sta...

android progress-bar titlebar android-titlebar
Rectangle 27 2

ProgressDialog mProgressDialog;
// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

// execute this when the downloader must be fired
DownloadFile downloadFile = new DownloadFile();
downloadFile.execute("the url to the file you want to download");
private class DownloadFile extends AsyncTask<String, Integer, String> {
@Override
protected String doInBackground(String... sUrl) {
    try {
        URL url = new URL(sUrl[0]);
        URLConnection connection = url.openConnection();
        connection.connect();
        // this will be useful so that you can show a typical 0-100% progress bar
        int fileLength = connection.getContentLength();

        // download the file
        InputStream input = new BufferedInputStream(url.openStream());
        OutputStream output = new FileOutputStream("/sdcard/file_name.extension");

        byte data[] = new byte[1024];
        long total = 0;
        int count;
        while ((count = input.read(data)) != -1) {
            total += count;
            // publishing the progress....
            publishProgress((int) (total * 100 / fileLength));
            output.write(data, 0, count);
        }

        output.flush();
        output.close();
        input.close();
    } catch (Exception e) {
    }
    return null;
}

This can be done using Download from Service as well as Download Manager class. Refer this question for details.

The percentage completed is what you actually publish in the progress dialog. If you want to display the percentage, you may use this (total * 100 / fileLength).

int percentage =  (total * 100 / fileLength);
TextView tv = (TextView)findViewById(R.id.textview);
tv.setText("" + percentage);

Use this code to display the percentage in the desired textview.

hi, there is only a progress dialog which is displayed. The progress is not displayed. I did the same thing like how you said.

this will give u the percentage (total * 100 / fileLength). you may accept the answer if it helped.

service - Progress Bar % completed (download) Display in Android - Sta...

android service android-asynctask progress-bar
Rectangle 27 41

Maybe too late, but I guess somebody might find it useful.

public class MainActivity extends Activity implements View.OnClickListener {

    String myLog = "myLog";

    AlphaAnimation inAnimation;
    AlphaAnimation outAnimation;

    FrameLayout progressBarHolder;
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.button);
        progressBarHolder = (FrameLayout) findViewById(R.id.progressBarHolder);

        button.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                new MyTask().execute();
                break;
        }

    }

    private class MyTask extends AsyncTask <Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            button.setEnabled(false);
            inAnimation = new AlphaAnimation(0f, 1f);
            inAnimation.setDuration(200);
            progressBarHolder.setAnimation(inAnimation);
            progressBarHolder.setVisibility(View.VISIBLE);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            outAnimation = new AlphaAnimation(1f, 0f);
            outAnimation.setDuration(200);
            progressBarHolder.setAnimation(outAnimation);
            progressBarHolder.setVisibility(View.GONE);
            button.setEnabled(true);
        }

        @Override
        protected Void doInBackground(Void... params) {
            try {
                for (int i = 0; i < 5; i++) {
                    Log.d(myLog, "Emulating some task.. Step " + i);
                    TimeUnit.SECONDS.sleep(1);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start doing stuff"
        android:id="@+id/button"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Do Some Stuff"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <FrameLayout
        android:id="@+id/progressBarHolder"
        android:animateLayoutChanges="true"
        android:visibility="gone"
        android:alpha="0.4"
        android:background="#000000"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminate="true"
            android:layout_gravity="center" />
    </FrameLayout>
</RelativeLayout>

This should be selected as the answer imo. The selected answer suggests about ProgressDialog which isn't commonly used anymore and provides no code.

progress bar - Display a loading overlay on Android screen - Stack Ove...

android progress-bar overlay
Rectangle 27 41

Maybe too late, but I guess somebody might find it useful.

public class MainActivity extends Activity implements View.OnClickListener {

    String myLog = "myLog";

    AlphaAnimation inAnimation;
    AlphaAnimation outAnimation;

    FrameLayout progressBarHolder;
    Button button;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        button = (Button) findViewById(R.id.button);
        progressBarHolder = (FrameLayout) findViewById(R.id.progressBarHolder);

        button.setOnClickListener(this);

    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
            case R.id.button:
                new MyTask().execute();
                break;
        }

    }

    private class MyTask extends AsyncTask <Void, Void, Void> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            button.setEnabled(false);
            inAnimation = new AlphaAnimation(0f, 1f);
            inAnimation.setDuration(200);
            progressBarHolder.setAnimation(inAnimation);
            progressBarHolder.setVisibility(View.VISIBLE);
        }

        @Override
        protected void onPostExecute(Void aVoid) {
            super.onPostExecute(aVoid);
            outAnimation = new AlphaAnimation(1f, 0f);
            outAnimation.setDuration(200);
            progressBarHolder.setAnimation(outAnimation);
            progressBarHolder.setVisibility(View.GONE);
            button.setEnabled(true);
        }

        @Override
        protected Void doInBackground(Void... params) {
            try {
                for (int i = 0; i < 5; i++) {
                    Log.d(myLog, "Emulating some task.. Step " + i);
                    TimeUnit.SECONDS.sleep(1);
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return null;
        }
    }

}
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Start doing stuff"
        android:id="@+id/button"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Do Some Stuff"
        android:id="@+id/textView"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true" />

    <FrameLayout
        android:id="@+id/progressBarHolder"
        android:animateLayoutChanges="true"
        android:visibility="gone"
        android:alpha="0.4"
        android:background="#000000"
        android:layout_width="match_parent"
        android:layout_height="match_parent">

        <ProgressBar
            style="?android:attr/progressBarStyleLarge"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:indeterminate="true"
            android:layout_gravity="center" />
    </FrameLayout>
</RelativeLayout>

This should be selected as the answer imo. The selected answer suggests about ProgressDialog which isn't commonly used anymore and provides no code.

progress bar - Display a loading overlay on Android screen - Stack Ove...

android progress-bar overlay
Rectangle 27 1

You download your data in AsyncTask right? Put this code

private class DownloadData extends AsyncTask<Void, Void, Void>{
    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgress.setVisibility(View.VISIBLE); 
    }
    @Override
    protected Void doInBackground(Void... params) {
        // download your data here
        return null;
    }

    @Override
    protected void onPostExecute(Void result) {
        super.onPostExecute(result);
        mProgress.setVisibility(View.GONE); 
    }
}

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).

Android Progress Bar appear and hide - Stack Overflow

android progress-bar
Rectangle 27 1

The best way implement it by using an AsyncTask

class MyTask extends AsyncTask<Void, Void, Void> {
    ProgressDialog dialog;
    Context context;
    MyTask(Context context){
        this.context=context;
    }
    @Override
    protected void onPreExecute() {
        dialog=new ProgressDialog(context);
        dialog.setMessage("Please wait...");
        dialog.setIndeterminate(true);
        dialog.setCancelable(false);
        dialog.show();
    }
    @Override
    protected Void doInBackground(Void... params) {
        //do your task here
    }
    @Override
    protected void onPostExecute(Void result) {
        if(dialog.isShowing()){
            dialog.dismiss();
        }
    }
}

You can start the task like this:

public void buttonClick(View v){
    new MyTask(YourActivity.this).execute();
}

You can modify the AsyncTask accordingly to retrieve the result.

Android Progress Bar appear and hide - Stack Overflow

android progress-bar
Rectangle 27 2

if (player != null)
        {
            player.seekTo(length);
            player.start();
        }
        else
        {
            player = MediaPlayer.create(context, Uri.fromFile(new File(url)));

            seek_bar.setMax(player.getDuration());

            seek_bar.setProgress(player.getCurrentPosition());

            player.setOnCompletionListener(new OnCompletionListener()
            {
                @Override
                public void onCompletion(MediaPlayer mp)
                {
                    player.reset();
                    player.release();
                    player = null;
                    seekHandler.removeCallbacks(run);
                    seek_bar.setProgress(0);
                    if (recieveOrSend.equals("send"))
                    {

                        holder.iv_audio_pause_send.setVisibility(View.INVISIBLE);
                        holder.iv_audio_play_send.setVisibility(View.VISIBLE);
                    }
                    else
                    {
                        holder.iv_audio_pause_recieve.setVisibility(View.INVISIBLE);
                        holder.iv_audio_play_recieve.setVisibility(View.VISIBLE);
                    }
                }
            });

            //          player.prepare();
            player.start();

        }
        seekUpdation();
Runnable run = new Runnable()
{
    @Override
    public void run()
    {

        seekUpdation();
    }
};

public void seekUpdation()
{
    seek_bar.setProgress(player.getCurrentPosition());
    seekHandler.postDelayed(run, 1000);
}

private void pausePlayer()
{

    try
    {
        if (player != null)
        {
            player.pause();
            length = player.getCurrentPosition();
            seekHandler.removeCallbacks(run);
        }
    }
    catch (Exception e)
    {
        e.printStackTrace();
    }
}

Android media player progress bar rest to "0" when stop music - Stack ...

android progress-bar media-player
Rectangle 27 29

Building on that, here's a couple of ideas to make the same overlay easily reusable across your app:

Consider putting the overlay FrameLayout in a separate layout file, e.g. res/layout/include_progress_overlay:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/progress_overlay"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:alpha="0.4"
    android:animateLayoutChanges="true"
    android:background="@android:color/black"
    android:clickable="true"
    android:visibility="gone">

    <ProgressBar
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:indeterminate="true"/>

</FrameLayout>

(One thing I added in the overlay FrameLayout is android:clickable="true". So while the overlay is shown, it prevents clicks going through to UI elements underneath it. At least in my typical use cases this is what I want.)

<!-- Progress bar overlay; shown while login is in progress -->
<include layout="@layout/include_progress_overlay"/>

And in code:

View progressOverlay;
[...]

progressOverlay = findViewById(R.id.progress_overlay);
[...]

// Show progress overlay (with animation): 
AndroidUtils.animateView(progressOverlay, View.VISIBLE, 0.4f, 200);
[...]

// Hide it (with animation): 
AndroidUtils.animateView(progressOverlay, View.GONE, 0, 200);
/**
 * @param view         View to animate
 * @param toVisibility Visibility at the end of animation
 * @param toAlpha      Alpha at the end of animation
 * @param duration     Animation duration in ms
 */
public static void animateView(final View view, final int toVisibility, float toAlpha, int duration) {
    boolean show = toVisibility == View.VISIBLE;
    if (show) {
        view.setAlpha(0);
    }
    view.setVisibility(View.VISIBLE);
    view.animate()
            .setDuration(duration)
            .alpha(show ? toAlpha : 0)
            .setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            view.setVisibility(toVisibility);
        }
    });
}
view.animate()
AlphaAnimation

I'm using a ConstraintLayout and had to use progressOverlay.bringToFront() to prevent interaction with other UI elements. Otherwise, neat answer Jonik and Kostya.

progress bar - Display a loading overlay on Android screen - Stack Ove...

android progress-bar overlay
Rectangle 27 29

Building on that, here's a couple of ideas to make the same overlay easily reusable across your app:

Consider putting the overlay FrameLayout in a separate layout file, e.g. res/layout/include_progress_overlay:

<FrameLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/progress_overlay"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:alpha="0.4"
    android:animateLayoutChanges="true"
    android:background="@android:color/black"
    android:clickable="true"
    android:visibility="gone">

    <ProgressBar
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:indeterminate="true"/>

</FrameLayout>

(One thing I added in the overlay FrameLayout is android:clickable="true". So while the overlay is shown, it prevents clicks going through to UI elements underneath it. At least in my typical use cases this is what I want.)

<!-- Progress bar overlay; shown while login is in progress -->
<include layout="@layout/include_progress_overlay"/>

And in code:

View progressOverlay;
[...]

progressOverlay = findViewById(R.id.progress_overlay);
[...]

// Show progress overlay (with animation): 
AndroidUtils.animateView(progressOverlay, View.VISIBLE, 0.4f, 200);
[...]

// Hide it (with animation): 
AndroidUtils.animateView(progressOverlay, View.GONE, 0, 200);
/**
 * @param view         View to animate
 * @param toVisibility Visibility at the end of animation
 * @param toAlpha      Alpha at the end of animation
 * @param duration     Animation duration in ms
 */
public static void animateView(final View view, final int toVisibility, float toAlpha, int duration) {
    boolean show = toVisibility == View.VISIBLE;
    if (show) {
        view.setAlpha(0);
    }
    view.setVisibility(View.VISIBLE);
    view.animate()
            .setDuration(duration)
            .alpha(show ? toAlpha : 0)
            .setListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            view.setVisibility(toVisibility);
        }
    });
}
view.animate()
AlphaAnimation

I'm using a ConstraintLayout and had to use progressOverlay.bringToFront() to prevent interaction with other UI elements. Otherwise, neat answer Jonik and Kostya.

progress bar - Display a loading overlay on Android screen - Stack Ove...

android progress-bar overlay
Rectangle 27 2

use setRequestOrientation method in Activity class. Inherit ProgressDialog class, and override methods. Example code is below.

class myDialog extends ProgressDialog
{
    Activity mActivity;
    public myDialog(Activity context) {
        super(context);
        this.mActivity = context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
    }

    @Override
    public void dismiss() {            
        super.dismiss();
        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
    }
}

How to stop changing the orientation when a progress bar is spinning i...

android progress-bar screen-orientation orientation-changes
Rectangle 27 2

use setRequestOrientation method in Activity class. Inherit ProgressDialog class, and override methods. Example code is below.

class myDialog extends ProgressDialog
{
    Activity mActivity;
    public myDialog(Activity context) {
        super(context);
        this.mActivity = context;
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR);
    }

    @Override
    public void dismiss() {            
        super.dismiss();
        mActivity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR);
    }
}

How to stop changing the orientation when a progress bar is spinning i...

android progress-bar screen-orientation orientation-changes