Saltar al contenido

API DownloadManager de Android: ¿abrir el archivo después de la descarga?

Solución:

Problema

API DownloadManager de Android: ¿abrir el archivo después de descargarlo?

Solución

/**
 * Used to download the file from url.
 * 

* 1. Download the file using Download Manager. * * @param url Url. * @param fileName File Name. */ public void downloadFile(final Activity activity, final String url, final String fileName) try if (url != null && !url.isEmpty()) Uri uri = Uri.parse(url); activity.registerReceiver(attachmentDownloadCompleteReceive, new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE)); DownloadManager.Request request = new DownloadManager.Request(uri); request.setMimeType(getMimeType(uri.toString())); request.setTitle(fileName); request.setDescription("Downloading attachment.."); request.allowScanningByMediaScanner(); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName); DownloadManager dm = (DownloadManager) activity.getSystemService(Context.DOWNLOAD_SERVICE); dm.enqueue(request); catch (IllegalStateException e) Toast.makeText(activity, "Please insert an SD card to download file", Toast.LENGTH_SHORT).show(); /** * Used to get MimeType from url. * * @param url Url. * @return Mime Type for the given url. */ private String getMimeType(String url) String type = null; String extension = MimeTypeMap.getFileExtensionFromUrl(url); if (extension != null) MimeTypeMap mime = MimeTypeMap.getSingleton(); type = mime.getMimeTypeFromExtension(extension); return type; /** * Attachment download complete receiver. *

* 1. Receiver gets called once attachment download completed. * 2. Open the downloaded file. */ BroadcastReceiver attachmentDownloadCompleteReceive = new BroadcastReceiver() @Override public void onReceive(Context context, Intent intent) String action = intent.getAction(); if (DownloadManager.ACTION_DOWNLOAD_COMPLETE.equals(action)) long downloadId = intent.getLongExtra( DownloadManager.EXTRA_DOWNLOAD_ID, 0); openDownloadedAttachment(context, downloadId); ; /** * Used to open the downloaded attachment. * * @param context Content. * @param downloadId Id of the downloaded file to open. */ private void openDownloadedAttachment(final Context context, final long downloadId) DownloadManager downloadManager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE); DownloadManager.Query query = new DownloadManager.Query(); query.setFilterById(downloadId); Cursor cursor = downloadManager.query(query); if (cursor.moveToFirst()) int downloadStatus = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)); String downloadLocalUri = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)); String downloadMimeType = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_MEDIA_TYPE)); if ((downloadStatus == DownloadManager.STATUS_SUCCESSFUL) && downloadLocalUri != null) openDownloadedAttachment(context, Uri.parse(downloadLocalUri), downloadMimeType); cursor.close(); /** * Used to open the downloaded attachment. *

* 1. Fire intent to open download file using external application. * * 2. Note: * 2.a. We can't share fileUri directly to other application (because we will get FileUriExposedException from Android7.0). * 2.b. Hence we can only share content uri with other application. * 2.c. We must have declared FileProvider in manifest. * 2.c. Refer - https://developer.android.com/reference/android/support/v4/content/FileProvider.html * * @param context Context. * @param attachmentUri Uri of the downloaded attachment to be opened. * @param attachmentMimeType MimeType of the downloaded attachment. */ private void openDownloadedAttachment(final Context context, Uri attachmentUri, final String attachmentMimeType) if(attachmentUri!=null) // Get Content Uri. if (ContentResolver.SCHEME_FILE.equals(attachmentUri.getScheme())) // FileUri - Convert it to contentUri. File file = new File(attachmentUri.getPath()); attachmentUri = FileProvider.getUriForFile(activity, "com.freshdesk.helpdesk.provider", file);; Intent openAttachmentIntent = new Intent(Intent.ACTION_VIEW); openAttachmentIntent.setDataAndType(attachmentUri, attachmentMimeType); openAttachmentIntent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); try context.startActivity(openAttachmentIntent); catch (ActivityNotFoundException e) Toast.makeText(context, context.getString(R.string.unable_to_open_file), Toast.LENGTH_LONG).show();

Inicializar los detalles del proveedor de archivos

Decleare FileProvider en AndroidManifest


    

Agregue el siguiente archivo “res -> xml -> file_path.xml”



    

Nota

Por qué utilizar FileProvider

  1. Desde Android 7.0 no podemos compartir FileUri con otras aplicaciones.
  2. Usando “DownloadManager.COLUMN_LOCAL_URI” obtendremos solo FileUri, por lo tanto, necesitamos convertirlo en ContentUri y compartirlo con otra aplicación.

Problema con el uso de “DownloadManager.getUriForDownloadedFile (identificación larga)”

  1. No use “DownloadManager.getUriForDownloadedFile (ID largo)” – Para obtener Uri de downloadId para abrir el archivo usando una aplicación externa.
  2. Debido a que desde Android 6.0 y 7.0 el método “getUriForDownloadedFile” devuelve un uri local (al que solo puede acceder nuestra aplicación), no podemos compartir ese Uri con otra aplicación porque no pueden acceder a ese uri (pero está arreglado en Android 7.1 consulte Confirmación de Android aquí).
  3. Consulte el código fuente de Android DownloadManager.java y Downloads.java
  4. Por lo tanto, utilice siempre la columna “DownloadManager.COLUMN_LOCAL_URI” para obtener Uri.

Referencia

  1. https://developer.android.com/reference/android/app/DownloadManager.html
  2. https://developer.android.com/reference/android/support/v4/content/FileProvider.html

Debe registrar un receptor para cuando se complete la descarga:

registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));

y un controlador BroadcastReciever

BroadcastReceiver onComplete=new BroadcastReceiver() 
    public void onReceive(Context ctxt, Intent intent) 
        // Do Something
    
;

Compre en lugar de que yo estampe todo, le sugiero que revise esto.

EDITAR:

Solo como sugerencia, no recomendaría usar API 9 todavía: http://developer.android.com/resources/dashboard/platform-versions.html

Hay formas de evitar esto, creando su propio controlador de descarga, como hice yo, porque no queríamos alienar a la mayor parte de la base de usuarios de Android, para eso necesitará: Create AsyncTask que maneja la descarga del archivo.

y recomendaré crear un cuadro de diálogo de descarga de algún tipo (si dices que es un archivo grande, lo haré aparecer en el área de notificación).

y luego necesitará manejar la apertura del archivo:

protected void openFile(String fileName) 
    Intent install = new Intent(Intent.ACTION_VIEW);
    install.setDataAndType(Uri.fromFile(new File(fileName)),
            "MIME-TYPE");
    startActivity(install);

Si crees que ha sido de provecho este post, agradeceríamos que lo compartas con el resto juniors de este modo nos ayudas a dar difusión a nuestro contenido.

¡Haz clic para puntuar esta entrada!
(Votos: 2 Promedio: 4.5)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *