Several days ago, I wrote an Android wallpaper app example. In that example, I am using AsyncTask to download the wallpaper and using a Progress Dialog to track the download progress. But some friends have problem reading the source code because there are two many other functions inside. Therefore, I decide to write a new Android Progress Dialog example separately. In this android example, I will put a button on the stage. So users click the button and it will show Android progress dialog to download an image. After download complete, the progress dialog positive button will appear. Users can click the button to dismiss the progress dialog and show the downloaded image on the stage.
Try Example Android App
You can click the following link to download and install this android example app on your phone and tablet. Or you can scan the following QR code.
Download and Run This Example on Your Android Phone
Layout XML Source Code
First of all, let’s see the layout xml first. I am going to put a button on the top and a ImageView below the button. After the image is downloaded in local, I will show the image in this ImageView.
<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" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity" > <Button android:id="@+id/downloadButton" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:paddingBottom="5dp" android:paddingLeft="10dp" android:paddingRight="10dp" android:paddingTop="5dp" android:text="@string/download_image" /> <ImageView android:id="@+id/imageView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/downloadButton" android:layout_centerHorizontal="true" android:layout_marginTop="24dp"/> </RelativeLayout>
Create a ProgressDialog and Set Button Onclick Listener
In the main activity class, I will create the progress dialog and add a button inside. In progress dialog, there are 3 buttons predefined. From the left to right, there are BUTTON_NEGATIVE, BUTTON_NEUTRAL, and BUTTON_POSITIVE. If you want to show one button, you can choose anyone of them. Here, I add a click listener on BUTTON_NEGATIVE.
protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); imageView = (ImageView)this.findViewById(R.id.imageView1); progressDialog = new ProgressDialog(this); progressDialog.setTitle("Download Image"); progressDialog.setMessage("Downloading in progress..."); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.setProgress(0); progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, "Show Image", dialogInterfaceOnClickListener); Button downloadButton = (Button) findViewById(R.id.downloadButton); downloadButton.setOnClickListener(downloadButtonOnClickListener); }
Download Button Onclick Listener
The following source code example is download button onclick listener. When users click on the button, it will show the progress dialog and start to download the image by AsyncTask. Meanwhile, I will hide the BUTTON_NEGATIVE at the beginning.
private OnClickListener downloadButtonOnClickListener = new OnClickListener() { @Override public void onClick(View v) { // TODO Auto-generated method stub progressDialog.show(); progressDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.INVISIBLE); new DownloadImageTask().execute("http://farm8.staticflickr.com/7315/9046944633_881f24c4fa.jpg"); } };
Progress Dialog DialogInterface Onclick Listener
Next source code is BUTTON_NEGATIVE button onclick listener. I will show BUTTON_NEGATIVE button in progress dialog after the image is downloaded. When users click on it, progress dialog will disappear and the image will appear in ImageView. This listener is different from View OnClickListener. When you create DialogInterface.OnClickListener instance, you’d better to create it with the full package page. In case it may get conflict with View.OnClickListener.
private android.content.DialogInterface.OnClickListener dialogInterfaceOnClickListener = new android.content.DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { // TODO Auto-generated method stub progressDialog.dismiss(); MainActivity.this.imageView.setImageBitmap(bitmap); } };
Using AsyncTask to Download Image
Now, we will talk about the most complicated part. It is the DownloadImageTask class which extends from AsyncTask. There are three function inside.
- protected Bitmap doInBackground(String… params)
- protected void onProgressUpdate(Integer… values)
- protected void onPostExecute(Bitmap result)
In function doInBackground, I will download the image from internet and save in a local temporary file. Every time when I get some data from input stream, I will write it into the temporary file and call publishProgress() to invoke the onProgressUpdate function.
In function onProgressUpdate, I will update the progress dialog progress by the number of data I have downloaded.
In function onPostExecute, I will change the progress dialog progress message to download complete. Meanwhile, I will show the BUTTON_NEGATIVE button in dialog progress. When users click on the BUTTON_NEGATIVE button, the onclick listener will be invoked. The progress dialog will disappear and the image will appear in ImageView. Now let’s see the example source code:
private class DownloadImageTask extends AsyncTask
{
@Override
protected Bitmap doInBackground(String… params) {
// TODO Auto-generated method stub
String cacheFileName = “tempfile.data”;
String fileurlString = params[0];
Bitmap bitmap = null;
try {
URL fileurl = new URL(fileurlString);
URLConnection connection = fileurl.openConnection();
int filesize = connection.getContentLength();
if(filesize < 0) {
progressDialog.setMax(1000000);
} else {
progressDialog.setMax(filesize);
}
InputStream inputStream = new BufferedInputStream(fileurl.openStream(), 10240);
OutputStream outputStream = openFileOutput(cacheFileName, Context.MODE_PRIVATE);
byte[] buffer = new byte[1024];
int dataLength = 0;
int loadedDataLength = 0;
while((dataLength = inputStream.read(buffer)) != -1) {
loadedDataLength += dataLength;
outputStream.write(buffer, 0, dataLength);
publishProgress(loadedDataLength);
}
bitmap = BitmapFactory.decodeStream(openFileInput(cacheFileName));
} catch (MalformedURLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return bitmap;
}
@Override
protected void onProgressUpdate(Integer... values) {
// TODO Auto-generated method stub
super.onProgressUpdate(values);
progressDialog.setProgress(values[0]);
}
@Override
protected void onPostExecute(Bitmap result) {
// TODO Auto-generated method stub
super.onPostExecute(result);
progressDialog.setMessage("Downloading Complete!");
progressDialog.getButton(DialogInterface.BUTTON_NEGATIVE).setVisibility(View.VISIBLE);
bitmap = result;
}
}
[/java]
Get File Size Before Downloading
To trace the downloading progress, we need to know the file size and set the progress dialog max number before we start to download the file. But sometimes connection.getContentLength() returns -1 or a negative value. It’s a server configuration problem. The server which hosts your file doesn’t return a content length in its http header. To solve this problem, there are two options.
- You can change your server configuration to return the content-length http header.
- You can set a approximated value in your progress dialog, which is bigger than the real file size.
Here is normal http header which contains the content-length data.
Get Full Source Code under $2.99
You will get whole source code at $2.99. It is fully functional, and embedded the Google AdMob module by default. With this source code, you can do everything you want:
- Load your own images;
- Monetize the app with your own AdMob publish id;
- Use the source code in your own project;
- Publish the app with your own Google Play account;