studio - Administrador de descargas de Android completado
gestor de descargas android 2018 (4)
Pequeña pregunta sobre el gestor de descargas en Android. Es la primera vez que trabajo con él, descargué exitosamente varios archivos y los abrí. Pero mi pregunta es ¿cómo puedo verificar si la descarga se completó?
La situación es que descargo un archivo PDF y lo abro, y generalmente el archivo es tan pequeño que se completa antes de abrirlo. Pero si el archivo es un poco más grande, ¿cómo compruebo si el administrador de descargas ha terminado con la descarga antes de abrirlo?
Cómo descargo:
Intent intent = getIntent();
DownloadManager downloadManager = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
Uri Download_Uri = Uri.parse(intent.getStringExtra("Document_href"));
DownloadManager.Request request = new DownloadManager.Request(Download_Uri);
//Restrict the types of networks over which this download may proceed.
request.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI | DownloadManager.Request.NETWORK_MOBILE);
//Set whether this download may proceed over a roaming connection.
request.setAllowedOverRoaming(false);
//Set the title of this download, to be displayed in notifications.
request.setTitle(intent.getStringExtra("Document_title"));
//Set the local destination for the downloaded file to a path within the application''s external files directory
request.setDestinationInExternalFilesDir(this,Environment.DIRECTORY_DOWNLOADS,intent.getStringExtra("Document_title") + ".pdf");
//Enqueue a new download and same the referenceId
Long downloadReference = downloadManager.enqueue(request);
Como abro el archivo
Uri uri = Uri.parse("content://com.app.applicationname/" + "/Download/" + intent.getStringExtra("Document_title") + ".pdf");
Intent target = new Intent(Intent.ACTION_VIEW);
target.setDataAndType(uri, "application/pdf");
target.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
startActivity(target);
Entonces, en algún lugar entre la descarga y la apertura del archivo, quiero una sentencia if para comprobar si debe continuar o esperar el archivo.
He pasado más de una semana investigando cómo descargar y abrir archivos con el DownloadManager y nunca encontré una respuesta que fuera completamente perfecta para mí, por lo que dependía de mí tomar partes para encontrar lo que funcionaba. Me aseguré de documentar mi código lo mejor que pueda. Si tiene alguna pregunta, no dude en dejarla en los comentarios debajo de la respuesta.
Además, ¡no olvide agregar esta línea a su archivo AndroidManifest.xml!
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
Mi gestor de descargas:
import android.app.DownloadManager;
import android.content.ActivityNotFoundException;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.net.Uri;
import android.os.Environment;
import android.webkit.CookieManager;
import android.webkit.DownloadListener;
import android.widget.Toast;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class MyDownloadListener implements DownloadListener {
private Context mContext;
private DownloadManager mDownloadManager;
private long mDownloadedFileID;
private DownloadManager.Request mRequest;
public MyDownloadListener(Context context) {
mContext = context;
mDownloadManager = (DownloadManager) mContext
.getSystemService(Context.DOWNLOAD_SERVICE);
}
@Override
public void onDownloadStart(String url, String userAgent, String
contentDisposition, final String mimetype, long contentLength) {
// Function is called once download completes.
BroadcastReceiver onComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Prevents the occasional unintentional call. I needed this.
if (mDownloadedFileID == -1)
return;
Intent fileIntent = new Intent(Intent.ACTION_VIEW);
// Grabs the Uri for the file that was downloaded.
Uri mostRecentDownload =
mDownloadManager.getUriForDownloadedFile(mDownloadedFileID);
// DownloadManager stores the Mime Type. Makes it really easy for us.
String mimeType =
mDownloadManager.getMimeTypeForDownloadedFile(mDownloadedFileID);
fileIntent.setDataAndType(mostRecentDownload, mimeType);
fileIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
try {
mContext.startActivity(fileIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(mContext, "No handler for this type of file.",
Toast.LENGTH_LONG).show();
}
// Sets up the prevention of an unintentional call. I found it necessary. Maybe not for others.
mDownloadedFileID = -1;
}
};
// Registers function to listen to the completion of the download.
mContext.registerReceiver(onComplete, new
IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
mRequest = new DownloadManager.Request(Uri.parse(url));
// Limits the download to only over WiFi. Optional.
mRequest.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI);
// Makes download visible in notifications while downloading, but disappears after download completes. Optional.
mRequest.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE);
mRequest.setMimeType(mimetype);
// If necessary for a security check. I needed it, but I don''t think it''s mandatory.
String cookie = CookieManager.getInstance().getCookie(url);
mRequest.addRequestHeader("Cookie", cookie);
// Grabs the file name from the Content-Disposition
String filename = null;
Pattern regex = Pattern.compile("(?<=filename=/").*?(?=/")");
Matcher regexMatcher = regex.matcher(contentDisposition);
if (regexMatcher.find()) {
filename = regexMatcher.group();
}
// Sets the file path to save to, including the file name. Make sure to have the WRITE_EXTERNAL_STORAGE permission!!
mRequest.setDestinationInExternalFilesDir(mContext, Environment.DIRECTORY_DOWNLOADS, filename);
// Sets the title of the notification and how it appears to the user in the saved directory.
mRequest.setTitle(filename);
// Adds the request to the DownloadManager queue to be executed at the next available opportunity.
mDownloadedFileID = mDownloadManager.enqueue(mRequest);
}
}
Simplemente agregue esto a su WebView existente agregando esta línea a su clase de WebView:
webView.setDownloadListener(new MyDownloadListener(webView.getContext()));
No necesitas crear un archivo solo para verlo. El URI en COLUMN_LOCAL_URI se puede usar en setDataAndType (). Vea el ejemplo a continuación.
int uriIndex = cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI);
String downloadedPackageUriString = cursor.getString(uriIndex);
Intent open = new Intent(Intent.ACTION_VIEW);
open.setDataAndType(Uri.parse(downloadedPackageUriString), mimeType);
open.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
startActivity(open);
Una acción de intento de difusión enviada por el administrador de descargas cuando se completa una descarga, por lo que debe registrar un receptor para cuando se complete la descarga:
Registrar receptor
registerReceiver(onComplete, new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
y un controlador BroadcastReciever
BroadcastReceiver onComplete=new BroadcastReceiver() {
public void onReceive(Context ctxt, Intent intent) {
// your code
}
};
También puede crear AsyncTask para manejar la descarga de archivos grandes
Cree un cuadro de diálogo de descarga de algún tipo para mostrar la descarga en el área de notificación y luego 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);
}
También puede consultar el enlace de muestra.
Cortesía: Android DonwnloadManager Ejemplo
La respuesta aceptada no es del todo correcta. Recibir la emisión de ACTION_DOWNLOAD_COMPLETE no significa que su descarga esté completa . Tenga en cuenta que DownloadManager difunde ACTION_DOWNLOAD_COMPLETE cuando se completa cualquier descarga. No significa necesariamente que sea la misma descarga que estás esperando
La solución es guardar el ID de descarga devuelto por enqueue () al iniciar la descarga. Esta ID de descarga larga es única en todo el sistema y se puede usar para verificar el estado de la descarga
DownloadManager downloadManager= (DownloadManager) getSystemService(DOWNLOAD_SERVICE);
long downloadID = downloadManager.enqueue(request);// enqueue puts the download request in the queue.
Puede recibir una notificación cuando se complete la descarga siguiendo estos tres pasos
Cree un BroadcastReceiver como se muestra en el fragmento a continuación. Dentro del receptor, simplemente verificamos si la transmisión recibida es para nuestra descarga, haciendo coincidir la ID de la descarga recibida con nuestra descarga en cola.
private BroadcastReceiver onDownloadComplete = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Fetching the download id received with the broadcast
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
//Checking if the received broadcast is for our enqueued download by matching download id
if (downloadID == id) {
Toast.makeText(MainActivity.this, "Download Completed", Toast.LENGTH_SHORT).show();
}
}
};
Una vez que se crea el BroadcastReceiver, puede registrarse para ACTION_DOWNLOAD_COMPLETE en el método onCreate de su actividad.
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
registerReceiver(onDownloadComplete,new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
También es importante anular el registro de BroadcastReceiver en onDestroy. Esto asegura que solo escuches esta transmisión mientras la actividad esté activa
@Override
public void onDestroy() {
super.onDestroy();
unregisterReceiver(onDownloadComplete);
}
Les pido que lean el ejemplo completo aquí.