Download a file with android

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).

This is an example code:

// 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(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"); 

The AsyncTask will look like this:

// usually, subclasses of AsyncTask are declared inside the activity class. // that way, you can easily modify the UI thread from here 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;     } 

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();         mProgressDialog.show();     }     @Override     protected void onProgressUpdate(Integer... progress) {         super.onProgressUpdate(progress);         mProgressDialog.setProgress(progress[0]);     } } 

You will also want to override the onPostExecute method if you want to execute some code once the file has been downloaded completely (for instance mProgressDialog.dismiss()).

2. Download from Service

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).

Download service can look like this:

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(url.openStream());             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"/> 

And the activity will look like this:

// 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); 

Here is were ResultReceiver comes to play:

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();             }         }     } } 

3. Use DownloadManager class (GingerBread and newer only)

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.

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) {     try {         if (Build.VERSION.SDK_INT < Build.VERSION_CODES.GINGERBREAD) {             return false;         }         Intent intent = new Intent(Intent.ACTION_MAIN);         intent.addCategory(Intent.CATEGORY_LAUNCHER);         intent.setClassName("com.android.providers.downloads.ui", "com.android.providers.downloads.ui.DownloadList");         List<ResolveInfo> list = context.getPackageManager().queryIntentActivities(intent,                 PackageManager.MATCH_DEFAULT_ONLY);         return list.size() > 0;     } catch (Exception e) {         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.

Final thoughts

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 to app to be robust. Here is a brief list:

  • You must check whether user has an internet connection available
  • Make sure you have the right permissions (INTERNET and WRITE_EXTERNAL_STORAGE); alsoACCESS_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.
  • Users will be grateful if you allow them to interrupt the download.

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

 

 

 

****An other example:

 

 

Android Download File With Progress Bar
Our output is something like this

DownloadFile.java

package com.example.downloadfile;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

import android.app.Activity;
import android.app.Dialog;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.widget.TextView;

public class DownloadFile extends Activity {

public static final String LOG_TAG = « Android Downloader by The CodeOf A Ninja »;

//initialize our progress dialog/bar
private ProgressDialog mProgressDialog;
public static final int DIALOG_DOWNLOAD_PROGRESS = 0;

//initialize root directory
File rootDir = Environment.getExternalStorageDirectory();

//defining file name and url
public String fileName = « codeofaninja.jpg »;
public String fileURL = « https://lh4.googleusercontent.com/-HiJOyupc-tQ/TgnDx1_HDzI/AAAAAAAAAWo/DEeOtnRimak/s800/DSC04158.JPG &raquo;;

@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
//setting some display
setContentView(R.layout.main);
TextView tv = new TextView(this);
tv.setText(« Android Download File With Progress Bar »);

//making sure the download directory exists
checkAndCreateDirectory(« /my_downloads »);

//executing the asynctask
new DownloadFileAsync().execute(fileURL);
}

//this is our download file asynctask
class DownloadFileAsync extends AsyncTask<String, String, String> {

@Override
protected void onPreExecute() {
super.onPreExecute();
showDialog(DIALOG_DOWNLOAD_PROGRESS);
}

@Override
protected String doInBackground(String… aurl) {

try {
//connecting to url
URL u = new URL(fileURL);
HttpURLConnection c = (HttpURLConnection)u.openConnection();
c.setRequestMethod(« GET »);
c.setDoOutput(true);
c.connect();

//lenghtOfFile is used for calculating download progress
int lenghtOfFile = c.getContentLength();

//this is where the file will be seen after the download
FileOutputStream f = new FileOutputStream(newFile(rootDir + « /my_downloads/ », fileName));
//file input is from the url
InputStream in = c.getInputStream();

//here’s the download code
byte[] buffer = new byte[1024];
int len1 = 0;
long total = 0;

while ((len1 = in.read(buffer)) > 0) {
total += len1; //total = total + len1
publishProgress(«  » +(int)((total*100)/lenghtOfFile));
f.write(buffer, 0, len1);
}
f.close();

} catch (Exception e) {
Log.d(LOG_TAG, e.getMessage());
}

return null;
}

protected void onProgressUpdate(String… progress) {
Log.d(LOG_TAG,progress[0]);
mProgressDialog.setProgress(Integer.parseInt(progress[0]));
}

@Override
protected void onPostExecute(String unused) {
//dismiss the dialog after the file was downloaded
dismissDialog(DIALOG_DOWNLOAD_PROGRESS);
}
}

//function to verify if directory exists
public void checkAndCreateDirectory(String dirName){
File new_dir = new File( rootDir + dirName );
if( !new_dir.exists() ){
new_dir.mkdirs();
}
}

//our progress bar settings
@Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case DIALOG_DOWNLOAD_PROGRESS: //we set this to 0
mProgressDialog = new ProgressDialog(this);
mProgressDialog.setMessage(« Downloading file… »);
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);
mProgressDialog.show();
return mProgressDialog;
default:
return null;
}
}
}

And for the AndroidManifest.xml, include the INTERNET and WRITE_EXTERNAL_STORAGE permissions.

<?xml version= »1.0″ encoding= »utf-8″?>
<manifest xmlns:android= »http://schemas.android.com/apk/res/android &raquo;
package= »com.example.downloadfile »
android:versionCode= »1″
android:versionName= »1.0″>

<uses-permission android:name= »android.permission.INTERNET » />
<uses-permissionandroid:name= »android.permission.WRITE_EXTERNAL_STORAGE » />

<uses-sdk android:minSdkVersion= »4″ />

<application android:icon= »@drawable/icon »android:label= »@string/app_name »>
<activity android:name= ».DownloadFile »
android:label= »@string/app_name »>
<intent-filter>
<action android:name= »android.intent.action.MAIN » />
<category android:name= »android.intent.category.LAUNCHER »/>
</intent-filter>
</activity>

</application>
</manifest>

 

 

http://www.codeofaninja.com/2011/10/android-download-file-with-progress-bar.html

About these ads

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s