web-dev-qa-db-fra.com

Télécharger un fichier avec Android et montrer la progression dans un ProgressDialog

J'essaie d'écrire une application simple qui est mise à jour. Pour cela, j'ai besoin d'une fonction simple qui peut télécharger un fichier et afficher la progression actuelle dans un ProgressDialog. Je sais comment utiliser la ProgressDialog, mais je ne sais pas comment afficher l'état d'avancement actuel ni comment télécharger le fichier.

1006
Tom Leese

Il existe plusieurs façons de télécharger des fichiers. Après je posterai les moyens les plus communs; c'est à vous de décider quelle méthode convient le mieux à votre application.

1. Utilisez AsyncTask et affichez la progression du téléchargement dans une boîte de dialogue.

Cette méthode vous permettra d'exécuter certains processus en arrière-plan et de mettre à jour l'interface utilisateur en même temps (dans ce cas, nous mettrons à jour une barre de progression).

Ceci est un exemple de 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(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); //cancel the task
    }
});

La AsyncTask ressemblera à ceci:

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

La méthode ci-dessus (doInBackground) est toujours exécutée sur un thread d'arrière-plan. Vous ne devriez pas faire de tâches d'interface utilisateur ici. D'autre part, les variables onProgressUpdate et onPreExecute s'exécutent sur le thread d'interface utilisateur. Vous pouvez donc modifier la barre de progression:

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

Pour que cela fonctionne, vous devez disposer de l'autorisation WAKE_LOCK.

<uses-permission Android:name="Android.permission.WAKE_LOCK" />

2. Télécharger du service

La grande question est la suivante: comment puis-je mettre à jour mon activité à partir d'un service? . Dans l'exemple suivant, nous allons utiliser deux classes que vous ignorez peut-être: ResultReceiver et IntentService. ResultReceiver est celui qui nous permettra de mettre à jour notre thread depuis un service; IntentService est une sous-classe de Service qui génère un thread pour effectuer un travail d'arrière-plan à partir de là (vous devez savoir qu'un Service s'exécute en réalité dans le même thread de votre application; lorsque vous étendez Service, vous devez générer manuellement de nouveaux threads pour exécuter des opérations de blocage du processeur).

Le service de téléchargement peut ressembler à ceci:

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 {

            //create url and connect
            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());

            String path = "/sdcard/BarcodeScanner-debug.apk" ;
            OutputStream output = new FileOutputStream(path);

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

            // close streams 
            output.flush();
            output.close();
            input.close();

        } catch (IOException e) {
            e.printStackTrace();
        }

        Bundle resultData = new Bundle();
        resultData.putInt("progress" ,100);

        receiver.send(UPDATE_PROGRESS, resultData);
    }
}

Ajoutez le service à votre manifeste:

<service Android:name=".DownloadService"/>

Et l'activité ressemblera à ceci:

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

Voici où ResultReceiver vient de jouer:

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"); //get the progress
            dialog.setProgress(progress);

            if (progress == 100) {
                dialog.dismiss();
            }
        }
    }
}

2.1 Utiliser la bibliothèque Groundy

Groundy est une bibliothèque qui vous aide essentiellement à exécuter des morceaux de code dans un service en arrière-plan. Elle est basée sur le ResultReceiver concept présenté ci-dessus. Cette bibliothèque est obsolète pour le moment. Voici à quoi ressemblerait le code entier :

L'activité dans laquelle vous affichez la boîte de dialogue ...

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

Une implémentation GroundyTask utilisée par Groundy pour télécharger le fichier et afficher la progression:

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

Et ajoutez simplement ceci au manifeste:

<service Android:name="com.codeslap.groundy.GroundyService"/>

Cela ne pourrait pas être plus facile je pense. Il suffit de saisir le dernier pot de Github et vous êtes prêt à partir. Gardez à l’esprit que Groundy a pour objectif principal d’appeler des appels externes REST dans un service en arrière-plan et de publier les résultats sur le serveur. UI avec facilement. Si vous faites quelque chose comme ça dans votre application, cela pourrait être vraiment utile.

2.2 Utilisez https://github.com/koush/ion

3. Utilisez DownloadManager class (Gingerbread et plus récent uniquement)

Gingerbread a apporté une nouvelle fonctionnalité, DownloadManager, qui vous permet de télécharger facilement des fichiers et de déléguer le travail difficile de gestion des threads, des flux, etc. au système.

Voyons tout d'abord une méthode utilitaire:

/**
 * @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;
}

Le nom de la méthode explique tout. Une fois que vous êtes sûr que DownloadManager est disponible, vous pouvez faire quelque chose comme ceci:

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

La progression du téléchargement sera affichée dans la barre de notification.

Dernières pensées

Les première et deuxième méthodes ne sont que la pointe de l'iceberg. Il y a beaucoup de choses que vous devez garder à l'esprit si vous voulez que votre application soit robuste. Voici une brève liste:

  • Vous devez vérifier si l'utilisateur dispose d'une connexion Internet disponible
  • Assurez-vous de disposer des autorisations adéquates (INTERNET et WRITE_EXTERNAL_STORAGE); aussi ACCESS_NETWORK_STATE si vous voulez vérifier la disponibilité d'Internet.
  • Assurez-vous que le répertoire dans lequel vous allez télécharger les fichiers existe et dispose des droits en écriture.
  • Si le téléchargement est trop volumineux, vous pouvez mettre en œuvre un moyen de le reprendre si les tentatives précédentes échouaient.
  • Les utilisateurs seront reconnaissants si vous leur permettez d'interrompre le téléchargement.

Sauf si vous avez besoin d'un contrôle détaillé du processus de téléchargement, envisagez d'utiliser DownloadManager (3) car il gère déjà la plupart des éléments répertoriés ci-dessus.

Mais considérez également que vos besoins peuvent changer. Par exemple, DownloadManagerne met pas en cache la réponse . Il téléchargera aveuglément le même gros fichier plusieurs fois. Il n'y a pas de moyen facile de régler le problème après coup. Où si vous commencez avec un HttpURLConnection de base (1, 2), il vous suffit d’ajouter un HttpResponseCache. L’effort initial d’apprentissage des outils de base standard peut donc être un bon investissement.

Cette classe était obsolète dans l'API de niveau 26. ProgressDialog est une boîte de dialogue modale qui empêche l'utilisateur d'interagir avec l'application. Au lieu d'utiliser cette classe, vous devez utiliser un indicateur de progression, tel que ProgressBar, qui peut être intégré à l'interface utilisateur de votre application. Vous pouvez également utiliser une notification pour informer l'utilisateur de l'avancement de la tâche. Pour plus de détails Lien

1823
Cristian

N'oubliez pas d'ajouter des autorisations à votre fichier manifeste si vous téléchargez des fichiers à partir d'Internet!

<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
    package="com.example.helloandroid"
    Android:versionCode="1"
    Android:versionName="1.0">

        <uses-sdk Android:minSdkVersion="10" />

        <uses-permission Android:name="Android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
        <uses-permission Android:name="Android.permission.INTERNET"></uses-permission>
        <uses-permission Android:name="Android.permission.ACCESS_NETWORK_STATE"></uses-permission>
        <uses-permission Android:name="Android.permission.READ_PHONE_STATE"></uses-permission>

        <application 
            Android:icon="@drawable/icon" 
            Android:label="@string/app_name" 
            Android:debuggable="true">

        </application>

</manifest>
105
Mnightmare

Oui, le code ci-dessus fonctionnera. Mais si vous mettez à jour votre progressbar dans onProgressUpdate sur Asynctask et que vous appuyez sur le bouton Précédent ou terminez votre activité AsyncTask perd sa trace avec votre interface utilisateur Et lorsque vous revenez à votre activité, même si le téléchargement s’exécute en arrière-plan, vous ne verrez aucune mise à jour dans Progressbar. Ainsi, sur OnResume(), essayez de lancer un thread tel que runOnUIThread avec une tâche de minuteur qui met à jour ur progressbar avec les valeurs mises à jour à partir de l'arrière-plan AsyncTask.

private void updateProgressBar(){
    Runnable runnable = new updateProgress();
    background = new Thread(runnable);
    background.start();
}

public class updateProgress implements Runnable {
    public void run() {
        while(Thread.currentThread()==background)
            //while (!Thread.currentThread().isInterrupted()) {
            try {
                Thread.sleep(1000); 
                Message msg = new Message();
                progress = getProgressPercentage();        
                handler.sendMessage(msg);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } catch (Exception e) {
        }
    }
}

private Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        progress.setProgress(msg.what);
    }
};

N'oubliez pas de détruire le fil lorsque votre activité n'est pas visible.

private void destroyRunningThreads() {
    if (background != null) {
        background.interrupt();
        background=null;
    }
}
31
sheetal

Je vous recommande d'utiliser mon projet Netroid , basé sur Volley . J'y ai ajouté des fonctionnalités telles que le rappel multi-événements, la gestion du téléchargement de fichiers. Cela pourrait être utile.

17
VinceStyling

J'ai modifié la classe AsyncTask pour gérer la création de progressDialog dans le même contexte. Je pense que le code suivant sera plus réutilisable. (il peut être appelé depuis n'importe quelle activité, il suffit de passer le contexte, le fichier cible, le message de dialogue)

public static class DownloadTask extends AsyncTask<String, Integer, String> {
    private ProgressDialog mPDialog;
    private Context mContext;
    private PowerManager.WakeLock mWakeLock;
    private File mTargetFile;
    //Constructor parameters :
    // @context (current Activity)
    // @targetFile (File object to write,it will be overwritten if exist)
    // @dialogMessage (message of the ProgresDialog)
    public DownloadTask(Context context,File targetFile,String dialogMessage) {
        this.mContext = context;
        this.mTargetFile = targetFile;
        mPDialog = new ProgressDialog(context);

        mPDialog.setMessage(dialogMessage);
        mPDialog.setIndeterminate(true);
        mPDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
        mPDialog.setCancelable(true);
        // reference to instance to use inside listener
        final DownloadTask me = this;
        mPDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
            @Override
            public void onCancel(DialogInterface dialog) {
                me.cancel(true);
            }
        });
        Log.i("DownloadTask","Constructor done");
    }

    @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();
            }
            Log.i("DownloadTask","Response " + connection.getResponseCode());

            // 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(mTargetFile,false);

            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    Log.i("DownloadTask","Cancelled");
                    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;
    }
    @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) mContext.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
                getClass().getName());
        mWakeLock.acquire();

        mPDialog.show();

    }

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

    }

    @Override
    protected void onPostExecute(String result) {
        Log.i("DownloadTask", "Work Done! PostExecute");
        mWakeLock.release();
        mPDialog.dismiss();
        if (result != null)
            Toast.makeText(mContext,"Download error: "+result, Toast.LENGTH_LONG).show();
        else
            Toast.makeText(mContext,"File Downloaded", Toast.LENGTH_SHORT).show();
    }
}
14
The Syrian

J'ai trouvé this blog très utile, Son utilisation de loopJ pour télécharger le fichier, il n'a qu'une fonction simple, sera utile à certains nouveaux Android gars.

8
chintan adatiya

N'oubliez pas de remplacer "/ sdcard ..." par nouveau fichier ("/ mnt/sdcard/... ") sinon vous obtiendrez un FileNotFoundException

8
ENSATE

Alors que je commençais à apprendre le développement de Android, j’avais appris que ProgressDialog était la voie à suivre. Il existe la méthode setProgress de ProgressDialog qui peut être appelée pour mettre à jour le niveau de progression au fur et à mesure que le fichier est téléchargé.

Le meilleur que j'ai vu dans de nombreuses applications est qu'elles personnalisent les attributs de cette boîte de dialogue de progression afin de leur donner une meilleure apparence que la version d'origine. Il est bon de garder l'utilisateur engagé dans une animation de grenouilles, d'éléphants ou de chats/chiots mignons. Toute animation avec dans la boîte de dialogue de progression attire les utilisateurs et ceux-ci ne se sentent pas obligés d'attendre longtemps.

6
Sandeep

Mon conseil personnel est d'utiliser dialogue de progression et de le construire avant l'exécution, ou de l'initier à OnPreExecute(), publiez la progression souvent si vous utilisez le style horizontal de la barre de progression du dialogue de progression. La partie restante consiste à optimiser l’algorithme de doInBackground.

5
Raju yourPepe

Utilisez Android Bibliothèque de requêtes, vraiment très cool. Vous pouvez le changer pour utiliser ProgressDialog comme vous le voyez dans d'autres exemples, celui-ci affichera la vue de la progression à partir de votre mise en page et la masquera à la fin.

File target = new File(new File(Environment.getExternalStorageDirectory(), "ApplicationName"), "tmp.pdf");
new AQuery(this).progress(R.id.progress_view).download(_competition.qualificationScoreCardsPdf(), target, new AjaxCallback<File>() {
    public void callback(String url, File file, AjaxStatus status) {
        if (file != null) {
            // do something with file  
        } 
    }
});
5
Renetik

Autorisations

  <uses-permission Android:name="Android.permission.INTERNET" />
  <uses-permission 
   Android:name="Android.permission.WRITE_EXTERNAL_STORAGE" />

Utilisation de HttpURLConnection

import Java.io.File;
import Java.io.FileOutputStream;
import Java.io.IOException;
import Java.io.InputStream;
import Java.net.HttpURLConnection;
import Java.net.MalformedURLException;
import Java.net.URL;

import Android.app.Activity;
import Android.app.Dialog;
import Android.os.Bundle;
import Android.os.Environment;
import Android.view.View;
import Android.view.Window;
import Android.view.View.OnClickListener;
import Android.widget.Button;
import Android.widget.ProgressBar;
import Android.widget.TextView;
import Android.widget.Toast;

public class DownloadFileUseHttpURLConnection extends Activity {

ProgressBar pb;
Dialog dialog;
int downloadedSize = 0;
int totalSize = 0;
TextView cur_val;
String dwnload_file_path =  
"http://coderzheaven.com/sample_folder/sample_file.png";
@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    Button b = (Button) findViewById(R.id.b1);
    b.setOnClickListener(new OnClickListener() {
        @Override
        public void onClick(View v) {
             showProgress(dwnload_file_path);

                new Thread(new Runnable() {
                    public void run() {
                         downloadFile();
                    }
                  }).start();
        }
    });
}

void downloadFile(){

    try {
        URL url = new URL(dwnload_file_path);
        HttpURLConnection urlConnection = (HttpURLConnection)   
 url.openConnection();

        urlConnection.setRequestMethod("GET");
        urlConnection.setDoOutput(true);

        //connect
        urlConnection.connect();

        //set the path where we want to save the file           
        File SDCardRoot = Environment.getExternalStorageDirectory(); 
        //create a new file, to save the downloaded file 
        File file = new File(SDCardRoot,"downloaded_file.png");

        FileOutputStream fileOutput = new FileOutputStream(file);

        //Stream used for reading the data from the internet
        InputStream inputStream = urlConnection.getInputStream();

        //this is the total size of the file which we are downloading
        totalSize = urlConnection.getContentLength();

        runOnUiThread(new Runnable() {
            public void run() {
                pb.setMax(totalSize);
            }               
        });

        //create a buffer...
        byte[] buffer = new byte[1024];
        int bufferLength = 0;

        while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
            fileOutput.write(buffer, 0, bufferLength);
            downloadedSize += bufferLength;
            // update the progressbar //
            runOnUiThread(new Runnable() {
                public void run() {
                    pb.setProgress(downloadedSize);
                    float per = ((float)downloadedSize/totalSize) *     
                    100;
                    cur_val.setText("Downloaded " + downloadedSize +  

                    "KB / " + totalSize + "KB (" + (int)per + "%)" );
                }
            });
        }
        //close the output stream when complete //
        fileOutput.close();
        runOnUiThread(new Runnable() {
            public void run() {
                // pb.dismiss(); // if you want close it..
            }
        });         

    } catch (final MalformedURLException e) {
        showError("Error : MalformedURLException " + e);        
        e.printStackTrace();
    } catch (final IOException e) {
        showError("Error : IOException " + e);          
        e.printStackTrace();
    }
    catch (final Exception e) {
        showError("Error : Please check your internet connection " +  
e);
    }       
}

void showError(final String err){
    runOnUiThread(new Runnable() {
        public void run() {
            Toast.makeText(DownloadFileDemo1.this, err,  
      Toast.LENGTH_LONG).show();
        }
    });
}

void showProgress(String file_path){
    dialog = new Dialog(DownloadFileDemo1.this);
    dialog.requestWindowFeature(Window.FEATURE_NO_TITLE);
    dialog.setContentView(R.layout.myprogressdialog);
    dialog.setTitle("Download Progress");

    TextView text = (TextView) dialog.findViewById(R.id.tv1);
    text.setText("Downloading file from ... " + file_path);
    cur_val = (TextView) dialog.findViewById(R.id.cur_pg_tv);
    cur_val.setText("Starting download...");
    dialog.show();

     pb = (ProgressBar)dialog.findViewById(R.id.progress_bar);
     pb.setProgress(0);
            pb.setProgressDrawable(
      getResources().getDrawable(R.drawable.green_progress));  
  }
}
2
vishnuc156

J'ajoute une autre réponse à une autre solution que j'utilise maintenant parce que Android Query est si gros et si peu entretenu pour rester en bonne santé. Alors je suis passé à ceci https://github.com/amitshekhariitbhu/Fast-Android-Networking .

    AndroidNetworking.download(url,dirPath,fileName).build()
      .setDownloadProgressListener(new DownloadProgressListener() {
        public void onProgress(long bytesDownloaded, long totalBytes) {
            bar.setMax((int) totalBytes);
            bar.setProgress((int) bytesDownloaded);
        }
    }).startDownload(new DownloadListener() {
        public void onDownloadComplete() {
            ...
        }

        public void onError(ANError error) {
            ...
        }
    });
2
Renetik