Utilisation Du Gestionnaire De Téléchargement

 Download Manager est un service conçu pour optimiser la gestion des téléchargements de longue durée en gérant la connexion HTTP, en surveillant les modifications de la connectivité et en réinitialisant le système, afin de garantir la réussite de chaque téléchargement. Les téléchargements gérés par Download Manager sont stockés dans un emplacement accessible dans le monde entier, ce qui le rend inapproprié pour les téléchargements confidentiels. Il est recommandé d’utiliser Download Manager lorsqu’un téléchargement est volumineux - et donc de continuer en arrière-plan entre les sessions utilisateur, lorsque la réussite du processus est importante et lorsque le fichier en cours de téléchargement est partagé avec d’autres applications (telles qu’une image ou une image). PDF).

 Remarque : Par défaut, les fichiers téléchargés par le gestionnaire de téléchargement sont stockés dans le répertoire du cache de téléchargement partagé (Environment.getDownloadCacheDirectory), ce qui signifie qu'ils seront disponibles pour d'autres applications et supprimés par le système s'il nécessite de l'espace. De même, ils seront gérés via l'application de téléchargement, ce qui signifie que vos téléchargements pourraient être supprimés manuellement par les utilisateurs. Vous pouvez modifier ces valeurs par défaut comme décrit plus loin dans cette section. Pour accéder au gestionnaire de téléchargement, demandez DOWNLOAD_SERVICE à l'aide de la méthode getSystemService:

  1. DownloadManager downloadManager = (DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE);

 Comme le gestionnaire de téléchargement utilise Internet, votre application doit demander l'autorisation INTERNET dans son manifeste pour pouvoir utiliser le gestionnaire de téléchargement:

  1. < uses-permission android:name="android.permission.INTERNET"/ >


Téléchargement de fichiers

 Pour demander un téléchargement, créez un nouveau DownloadManager.Request, en spécifiant l’URI du fichier à télécharger et en le transmettant à la méthode de mise en file d’attente du gestionnaire de téléchargement, comme indiqué dans le Listing 7-6.

 LISTING 7-6: Téléchargement de fichiers à l'aide du gestionnaire de téléchargement

  1. DownloadManager downloadManager = (DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE);
  2.  
  3. Uri uri = Uri.parse( "http://developer.android.com/shareables/icon_templates-v4.0.zip");
  4. DownloadManager.Request request = new DownloadManager.Request(uri);
  5. long reference = downloadManager.enqueue(request);

Vous pouvez utiliser la valeur de référence renvoyée pour effectuer des actions futures ou interroger le téléchargement, notamment en vérifiant son statut ou en l'annulant. Vous pouvez ajouter un en-tête HTTP à votre demande ou remplacer le type mime renvoyé par le serveur en appelant respectivement addRequestHeader et setMimeType sur votre objet Request. Vous pouvez également spécifier les conditions de connectivité dans lesquelles exécuter le téléchargement. La méthode setAllowedNetworkTypes vous permet de limiter les téléchargements aux réseaux Wi-Fi ou mobiles. Les méthodes setAllowedOverRoaming et setAllowedOverMetered vous permettent d'empêcher les téléchargements lorsque le téléphone est en itinérance ou via une connexion payée. L'extrait suivant montre comment s'assurer qu'un fichier volumineux est téléchargé uniquement lorsqu'il est connecté au Wi-Fi:

  1. request.setAllowedNetworkTypes(Request.NETWORK_WIFI);

After calling enqueue, the download begins as soon as suitable connectivity is available, and the Download Manager is free.

Remarque Les périphériques virtuels Android n'incluent pas de matériel Wi-Fi virtualisé. Par conséquent, les téléchargements limités au Wi-Fi uniquement seront mis en file d'attente mais ne commenceront jamais à se télécharger. Par défaut, les téléchargements en cours et terminés sont indiqués en tant que notifications. Vous devriez créer un Récepteur de diffusion qui écoute l'action ACTION_NOTIFICATION_CLICKED, qui sera diffusée chaque fois qu'un utilisateur sélectionne un téléchargement dans la barre de notification ou dans l'application Téléchargements. Il inclura un extra EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS contenant l'ID de référence du téléchargement sélectionné. Une fois le téléchargement terminé, le gestionnaire de téléchargement diffusera l'action ACTION_DOWNLOAD_ COMPLETE, avec un extra EXTRA_DOWNLOAD_ID indiquant l'ID de référence du téléchargement de fichier terminé, comme indiqué dans l'extrait 7-7.

LISTING 7-7: Implémentation d'un récepteur de diffusion pour gérer les émissions du gestionnaire de téléchargement

  1. public class DownloadsReceiver extends BroadcastReceiver {
  2. @Override
  3. public void onReceive(Context context, Intent intent) {
  4. String extraNotificationFileIds = DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS;
  5. String extraFileId = DownloadManager.EXTRA_DOWNLOAD_ID;
  6. String action = intent.getAction();
  7. if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
  8. long reference = intent.getLongExtra(extraFileId,-1);
  9. if (myDownloadReference == reference) {
  10. // Do something with downloaded file.
  11. }
  12. }
  13. else if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) {
  14. long[] references = intent.getLongArrayExtra(extraNotificationFileIds);
  15. for (long reference : references)
  16. if (myDownloadReference == reference) {
  17. // Respond to user selecting your file download notification.
  18. }
  19. }
  20. }
  21. }

Download Manager continuera à télécharger vos fichiers entre les sessions utilisateur de votre application, ainsi que les redémarrages du téléphone. Par conséquent, il est important que vous stockiez les numéros de référence de téléchargement pour vous assurer que votre application les mémorise. Pour la même raison, vous devez enregistrer vos destinataires de radiodiffusion pour les clics de notification et les finitions de téléchargement dans le manifeste, comme indiqué dans le Listing 7-8, car rien ne garantit que votre application sera en cours d'exécution lorsqu'un utilisateur sélectionne une notification de téléchargement. terminé.

 LISTING 7-8: Enregistrement d'un récepteur de diffusion pour les diffusions du gestionnaire de téléchargement

  1. <receiver
  2. android:name="com.professionalandroid.apps.MyApp.DownloadsReceiver">
  3. <intent-filter>
  4. <action
  5. android:name="android.intent.action.DOWNLOAD_NOTIFICATION_CLICKED" />
  6. <action
  7. android:name="android.intent.action.DOWNLOAD_COMPLETE" />
  8. </intent-filter>
  9. < /receiver >

 Une fois le téléchargement terminé, vous pouvez utiliser la méthode openDownloadedFile de Download Manager pour recevoir un descripteur de fichier de parcelle dans votre fichier ou utiliser l’ID pour interroger Download Manager et obtenir des détails sur les métadonnées. Pour plus d'informations sur la gestion des fichiers, reportez-vous au Chapitre 8, "Enregistrement de l'état, des préférences de l'utilisateur et Utilisation et partage de fichiers".

 Personnalisation des notifications du gestionnaire de téléchargement

Par défaut, les notifications en cours sont affichées pour chaque fichier lors de son téléchargement par le gestionnaire de téléchargement. Chaque notification indiquera la progression du téléchargement en cours et le nom du fichier (Figure 7-3).Le gestionnaire de téléchargement vous permet de personnaliser la notification affichée pour chaque demande de téléchargement, y compris de la masquer complètement. L'extrait suivant montre comment utiliser les méthodes setTitle et setDescription pour personnaliser le texte affiché dans la notification de téléchargement de fichier. La figure 7-4 montre le résultat. 

  1. request.setTitle("Hive Husks");
  2. request.setDescription("Downloading Splines for Reticulation");

La méthode setNotificationVisibility vous permet de contrôler quand et si une notification doit être affichée pour votre téléchargement à l'aide de l'un des indicateurs suivants:

  • Request.VISIBILITY_VISIBLE: une notification en cours sera visible pendant la durée du téléchargement. Il sera supprimé à la fin du téléchargement. Ceci est l'option par défaut. 
  • Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED — Une notification en cours sera affichée pendant le téléchargement et continuera de l'être une fois le téléchargement terminé, jusqu'à ce qu'il soit sélectionné ou rejeté. 
  • Request.VISIBILITY_VISIBLE_NOTIFY_ONLY_COMPLETION: utilisable uniquement lors de l'utilisation de addCompletedDownload pour ajouter un fichier déjà téléchargé au système de base de données téléchargé. Lorsque cette option est sélectionnée, une notification sera affichée une fois le fichier ajouté.
  • Request.VISIBILITY_HIDDEN: aucune notification ne sera affichée pour ce téléchargement. DansAfin de définir cet indicateur, votre application doit disposer de l'autorisation DOWNLOAD_WITHOUT_NOTIFICATION spécifiée dans son manifeste: 
  1. <uses-permission
  2. android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION"/>

Spécifier un emplacement de téléchargement

 Par défaut, tous les téléchargements Download Manager sont enregistrés dans le cache de téléchargement partagé à l'aide de noms de fichiers générés par le système, où ils peuvent être supprimés automatiquement par le système ou manuellement par les utilisateurs. Alternativement, une demande de téléchargement peut indiquer un URI vers un emplacement de téléchargement spécifique. Dans ce cas, l'emplacement doit se trouver sur un stockage externe et, par conséquent, votre application doit disposer de l'autorisation WRITE_EXTERNAL_ STORAGE définie dans son manifeste:

  1. < uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/ >

L'extrait de code suivant montre comment spécifier un chemin arbitraire sur un stockage externe:

  1. request.setDestinationUri(Uri.fromFile(f));

 Si le fichier téléchargé est spécifique à votre application, vous pouvez le placer dans le dossier de stockage externe de votre application. Notez que le contrôle d'accès n'est pas appliqué à ce dossier et que d'autres applications pourront y accéder. Si votre application est désinstallée, les fichiers stockés dans ces dossiers seront également supprimés. L’extrait suivant spécifie le stockage d’un fichier dans le dossier de téléchargement externe de votre application:

  1. request.setDestinationInExternalFilesDir(this,Environment.DIRECTORY_DOWNLOADS,"bugdroid.png");

 Pour les fichiers pouvant ou devant être partagés avec d'autres applications, en particulier celles que vous souhaitez analyser avec Media Scanner, vous pouvez spécifier un emplacement dans le dossier public du stockage externe. L'extrait suivant demande qu'un fichier soit stocké dans le dossier de musique publique:

  1. request.setDestinationInExternalPublicDir(Environment.DIRECTORY_MUSIC,"android_anthem.mp3");

REMARQUE Voir le chapitre 8 pour plus de détails sur le stockage externe et les variables d'environnement statiques que vous pouvez utiliser pour indiquer les dossiers qu'il contient. Il est important de noter que, par défaut, les fichiers téléchargés par le gestionnaire de téléchargement ne sont pas analysés par Media Scanner. Ils risquent donc de ne pas apparaître dans des applications telles que les galeries de photos et les lecteurs de musique.

 Pour rendre les fichiers téléchargés numérisables, appelez allowScanningByMediaScanner sur l'objet Request avant qu'il ne soit mis en file d'attente par le gestionnaire de téléchargement:

  1. request.allowScanningByMediaScanner() ;

Par défaut, vos fichiers seront visibles et gérables par l’application Téléchargements du système. Si vous préférez qu'ils ne le soient pas, vous pouvez appeler setVisibleInDownloadsUi en transmettant false:

  1. request.setVisibleInDownloadsUi( false);

 Annulation et suppression de téléchargements

 La méthode de suppression de Download Manager vous permet d’annuler un téléchargement en attente, d’abandonner un téléchargement en cours ou de supprimer un téléchargement terminé.Comme indiqué dans l'extrait de code suivant, la méthode remove accepte les ID de téléchargement comme arguments facultatifs, ce qui vous permet de spécifier un ou plusieurs téléchargements à annuler:

  1. downloadManager.remove(fileRef1, fileRef2, fileRef3);

 Il renvoie le nombre de téléchargements annulés avec succès. Si un téléchargement est annulé, tous les fichiers associés, qu'ils soient partiels ou complets, sont supprimés.

 Interroger le gestionnaire de téléchargement

 Vous pouvez interroger le gestionnaire de téléchargement pour connaître l'état, l'avancement et les détails de vos demandes de téléchargement à l'aide de la méthode d'interrogation, qui renvoie un curseur à la liste des téléchargements. REMARQUE La classe Cursor représente une construction de données utilisée par Android pour renvoyer des données, généralement stockées dans une base de données Content Provider ou SQLite. Pour en savoir plus sur les fournisseurs de contenu, les curseurs et la recherche des données qui y sont stockées, reportez-vous au Chapitre 10, "Fournisseurs de contenu et recherche".  La méthode de requête prend un objet DownloadManager.Query en tant que paramètre. Utilisez la méthode setFilterById sur un objet Query pour spécifier une séquence d'ID de référence de téléchargement, ou utilisez la méthode setFilterByStatus pour filtrer un statut de téléchargement à l'aide de l'une des constantes DownloadManager.STATUS_ * pour spécifier les téléchargements en cours, suspendus, échoués ou ayant abouti.  Le gestionnaire de téléchargement inclut un certain nombre de constantes de chaîne statique COLUMN_ que vous pouvez utiliser pour interroger le curseur de résultat. Vous pouvez trouver des détails pour chaque téléchargement, y compris le statut, la taille des fichiers, les octets téléchargés jusqu'à présent, le titre, la description, l'URI, le type de support et l'URI de téléchargement du fournisseur de média. De plus, le gestionnaire de téléchargement inclut les méthodes getUriForDownloadedFile et openDownloadedFile. Le Listing 7-9 étend le Listing 7-7 pour montrer comment trouver le descripteur de fichier URI ou de fichier de parcelle des téléchargements terminés à partir d'un récepteur de radiodiffusion enregistré pour écouter les terminaisons de téléchargement.

LISTING 7-9: Trouver les détails des téléchargements terminés

  1. @Override public void onReceive(Context context, Intent intent) {
  2. DownloadManager downloadManager = (DownloadManager)getSystemService(Context.DOWNLOAD_SERVICE);
  3. String extraNotificationFileIds = DownloadManager.EXTRA_NOTIFICATION_CLICK_DOWNLOAD_IDS;
  4. String extraFileId = DownloadManager.EXTRA_DOWNLOAD_ID;
  5. String action = intent.getAction();
  6. if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) {
  7. long reference = intent.getLongExtra(extraFileId,-1);
  8. if (myDownloadReference == reference) {
  9. DownloadManager.Query myDownloadQuery = new DownloadManager.Query();
  10. myDownloadQuery.setFilterById(reference);
  11. Cursor myDownload = downloadManager.query(myDownloadQuery);
  12. if (myDownload.moveToFirst()) {
  13. int fileIdIdx = myDownload.getColumnIndex(DownloadManager.COLUMN_ID);
  14. long fileId = myDownload.getLong(fileIdIdx);
  15. Uri fileUri = downloadManager.getUriForDownloadedFile(fileId);
  16. // Do something with downloaded file.
  17. }
  18. myDownload.close();
  19. }
  20. }
  21. else if (DownloadManager.ACTION_NOTIFICATION_CLICKED.equals(action)) {
  22. long[] references = intent.getLongArrayExtra(extraNotificationFileIds);
  23. for (long reference : references)
  24. if (myDownloadReference == reference) {
  25. // Respond to user selecting your file download notification.
  26. try {
  27. ParcelFileDescriptor fileDescriptor = downloadManager.openDownloadedFile(reference);
  28. } catch (FileNotFoundException e) {
  29. Log.e(TAG, "Downloaded file open error.", e);
  30. }
  31. }
  32. }
  33. }

Pour les téléchargements en pause ou ayant échoué, vous pouvez interroger la colonne COLUMN_REASON pour trouver la cause représentée par un entier. Dans le cas de téléchargements STATUS_PAUSED, vous pouvez interpréter le code de motif à l'aide de l'une des constantes statiques DownloadManager.PAUSED_ pour déterminer si le téléchargement a été suspendu pendant l'attente de la connectivité réseau, d'une connexion Wi-Fi ou en attente d'une nouvelle tentative. Pour les téléchargements STATUS_FAILED, vous pouvez déterminer la cause de l'échec à l'aide duDownloadManager.ERROR_ codes. Les codes d'erreur possibles incluent l'absence de périphérique de stockage, l'espace libre insuffisant, les noms de fichiers dupliqués ou les erreurs HTTP. Le Listing 7-10 montre comment trouver une liste des téléchargements actuellement suspendus, en extrayant la raison de la suspension du téléchargement, le nom du fichier, son titre et la progression en cours.

 LISTING 7-10: Trouver des détails sur les téléchargements mis en pause

  1. // Obtain the Download Manager Service.
  2. String serviceString = Context.DOWNLOAD_SERVICE;
  3. DownloadManager downloadManager;
  4. downloadManager = (DownloadManager)getSystemService(serviceString);
  5. // Create a query for paused downloads.
  6. DownloadManager.Query pausedDownloadQuery = new DownloadManager.Query(); pausedDownloadQuery.setFilterByStatus(DownloadManager.STATUS_PAUSED);
  7. // Query the Download Manager for paused downloads.
  8. Cursor pausedDownloads = downloadManager.query(pausedDownloadQuery);
  9. // Find the column indexes for the data we require.
  10. int reasonIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_REASON);
  11. int titleIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TITLE);
  12. int fileSizeIdx = pausedDownloads.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES);
  13. int bytesDLIdx = pausedDownloads.getColumnIndex( DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR);
  14. // Iterate over the result Cursor. while (pausedDownloads.moveToNext()) {
  15. // Extract the data we require from the Cursor.
  16. String title = pausedDownloads.getString(titleIdx);
  17. int fileSize = pausedDownloads.getInt(fileSizeIdx);
  18. int bytesDL = pausedDownloads.getInt(bytesDLIdx);
  19. // Translate the pause reason to friendly text.int reason = pausedDownloads.getInt(reasonIdx);
  20. String reasonString = "Unknown";
  21. switch (reason) {
  22. case DownloadManager.PAUSED_QUEUED_FOR_WIFI : reasonString = "Waiting for WiFi.";
  23. break;
  24. case DownloadManager.PAUSED_WAITING_FOR_NETWORK : reasonString = "Waiting for connectivity.";
  25. break;
  26. case DownloadManager.PAUSED_WAITING_TO_RETRY : reasonString = "Waiting to retry.";
  27. break;
  28. default : break;
  29. }
  30. // Construct a status summary
  31. StringBuilder sb = new StringBuilder();
  32. sb.append(title).append("\n");
  33. sb.append(reasonString).append("\n");
  34. sb.append("Downloaded ").append(bytesDL).append(" / " ).append(fileSize);
  35. // Display the status
  36. Log.d("DOWNLOAD", sb.toString());
  37. }
  38. // Close the result Cursor. pausedDownloads.close();