web-dev-qa-db-fra.com

Comment télécharger un fichier pdf sous Android?

Je souhaite télécharger un fichier pdf à partir d'une URL . Pour visualiser le fichier pdf, j'ai utilisé le code ci-dessous.

File file = new File("/sdcard/example.pdf");

if (file.exists()) {
    Uri path = Uri.fromFile(file);
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(path, "application/pdf");
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    try {
        startActivity(intent);
    } 
    catch (ActivityNotFoundException e) {
        Toast.makeText(OpenPdf.this, "No Application Available to View PDF",
            Toast.LENGTH_SHORT).show();
    }
}

Cela fonctionne, mais comment puis-je obtenir le fichier pdf à partir d'une URL (par exemple http://.../example.pdf). Je veux télécharger le fichier pdf à partir de cette URL. Aidez-moi, s'il vous plaît. Merci d'avance.

18
Ramakrishna

Le téléchargement d'un PDF fonctionne de la même manière que le téléchargement de tout autre fichier binaire. 

  1. Ouvrir une HttpUrlConnection
  2. Utilisez la méthode getInputStream() de la connexion pour lire le fichier.
  3. Créez une FileOutputStream et écrivez le flux d'entrée.

Vérifiez cet article par exemple le code source.

8
THelper

Télécharger un pdf:

 startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("www.education.gov.yk.ca/pdf/pdf-test.pdf")));

Comme je viens de le découvrir, cela dépend de l'appareil.

scénarios

  1. Il téléchargera le pdf sur votre navigateur/téléchargé/dossier

  2. Vous avez un compte Google Documents - Il vous sera demandé de vous connecter puis de visualiser le pdf dans le navigateur.

  3. Vous avez un lecteur de pdf installé - L'application dépendante peut attraper il ne peut pas

Dans tous les scénarios, l'utilisateur a accès au PDF avec une seule ligne de code :-)

20
Blundell

Il existe plusieurs façons de télécharger des fichiers. Après je vais poster 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);
    }
});

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 en arrière-plan. Vous ne devriez pas faire de tâches d'interface utilisateur ici. D'autre part, les 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é depuis 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 en arrière-plan à partir de là (vous devez savoir qu'une Service s'exécute réellement dans le même thread de votre application; lorsque vous étendez Service, vous devez générer manuellement de nouveaux threads pour exécuter les 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 {
            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);
    }
}

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 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");
            mProgressDialog.setProgress(progress);
            if (progress == 100) {
                mProgressDialog.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 concept ResultReceiver présenté ci-dessus. Cette bibliothèque est deprecated pour le moment. Voici à quoi ressemble le code entier:

L'activité dans laquelle vous affichez le 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 sa 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. N'oubliez pas que le but principal de Groundy est de faire des appels à des apis externes REST dans un service en arrière-plan et d'afficher facilement les résultats dans l'interface utilisateur. 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 la classe DownloadManager (Gingerbread et les plus récents 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 la réponse en cache . 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 une HttpURLConnection de base (1, 2), il vous suffit d’ajouter une HttpResponseCache. L’effort initial d’apprentissage des outils de base standard peut donc être un bon investissement.

9
Arpit Patel

Il n'est pas nécessaire de mettre un long code pour ouvrir et télécharger le pdf dans Android. Vous pouvez simplement utiliser le code ci-dessous pour ouvrir et télécharger le pdf.

String URL ="http://worldhappiness.report/wp-content/uploads/sites/2/2016/03/HR-V1_web.pdf"

 startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse(URL)));
1
DEEP ADHIYA
public static class Downloader {

 public static void DownloadFile(String fileURL, File directory) {
    try {
         FileOutputStream file = new FileOutputStream(directory);
         URL url = new URL(fileURL);
        HttpURLConnection connection = (HttpURLConnection) url .openConnection();
         connection .setRequestMethod("GET");
         connection .setDoOutput(true);
         connection .connect();
         InputStream input = connection .getInputStream();
         byte[] buffer = new byte[1024];
         int len = 0;
          while ((len = input .read(buffer)) > 0) {
           file .write(buffer, 0, len );
         }
        file .close();
  } catch (Exception e) {
          e.printStackTrace();
   }
}

Pour plus d'informations, cliquez ici http://androiddhina.blogspot.in/2015/09/how-to-download-pdf-from-url-in-Android.html

0
Dhina k