¿Cómo descargar un archivo pdf en Android?

Quiero descargar un archivo pdf de una url. Para ver el archivo pdf he utilizado el código de abajo.

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

Está funcionando, pero ¿cómo puedo obtener el archivo pdf de una url (por ejemplo http://.../example.pdf ). Quiero descargar el archivo pdf de esta url. Por favor, ayúdame. Gracias por adelantado.

La descarga de un PDF funciona igual que la descarga de cualquier otro archivo binario.

  1. Abra una HttpUrlConnection
  2. Utilice el método getInputStream() la conexión para leer el archivo.
  3. Cree un FileOutputStream y escriba el inputtream.

Compruebe esta publicación por ejemplo código fuente.

Descargue un pdf:

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

Ah, como acabo de descubrir que esto depende del dispositivo.

Escenarios

  1. Se descargará el pdf a su navegador / descargado / carpeta

  2. Usted tiene una cuenta de google docs – le pedirá que inicie sesión y ver el pdf en el navegador

  3. Usted tiene un lector de pdf instalado – dependiente de la aplicación puede coger no puede

En todos los escenarios, aunque el usuario tiene acceso al PDF con una línea de código 🙂

Hay muchas maneras de descargar archivos. A continuación publicaré las formas más comunes; Depende de usted decidir qué método es mejor para su aplicación.

1. Utilice AsyncTask y muestre el progreso de la descarga en un diálogo

Este método le permitirá ejecutar algunos procesos en segundo plano y actualizar la interfaz de usuario al mismo tiempo (en este caso, actualizaremos una barra de progreso).

Este es un ejemplo de código:

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

El AsyncTask se verá así:

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

El método anterior ( doInBackground ) se ejecuta siempre en un subproceso de fondo. Usted no debe hacer ninguna tarea de IU allí. Por otro lado, onProgressUpdate y onPreExecute ejecutan en el subproceso de interfaz de usuario, por lo que puede cambiar la barra de progreso:

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

Para que esto funcione, necesita el permiso de WAKE_LOCK.

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

2. Descargar desde el servicio

La gran pregunta aquí es: ¿cómo puedo actualizar mi actividad de un servicio? . En el siguiente ejemplo vamos a usar dos clases que puede que no ResultReceiver : ResultReceiver e IntentService . ResultReceiver es el que nos permitirá actualizar nuestro hilo de un servicio; IntentService es una subclase de Service que genera un hilo para hacer el trabajo de fondo desde allí (debe saber que un Service ejecuta realmente en el mismo hilo de la aplicación, cuando se extiende el Service , debe generar nuevos hilos para ejecutar las operaciones de bloqueo de CPU) .

El servicio de descarga puede verse así:

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

Agregue el servicio a su manifiesto:

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

Y la actividad se verá así:

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

Aquí es donde ResultReceiver viene a jugar:

 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 Utilizar la biblioteca de Groundy

Groundy es una biblioteca que básicamente le ayuda a ejecutar piezas de código en un servicio de fondo, y se basa en el concepto de ResultReceiver mostrado anteriormente. Esta biblioteca está obsoleta en este momento. Así es como se vería todo el código:

La actividad en la que está mostrando el diálogo …

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

Una implementación GroundyTask utilizada por Groundy para descargar el archivo y mostrar el progreso:

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

Y simplemente añada esto al manifiesto:

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

No podría ser más fácil creo. Sólo tienes que agarrar el último frasco de Github y que está listo para ir. Tenga en cuenta que el propósito principal de Groundy es hacer llamadas a apis REST externo en un servicio de fondo y publicar resultados en la interfaz de usuario con facilidad. Si estás haciendo algo así en tu aplicación, podría ser muy útil.

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

3. Utilice la clase DownloadManager (sólo GingerBread y más reciente)

GingerBread trajo una nueva característica, DownloadManager , que le permite descargar archivos fácilmente y delegar el trabajo duro de la manipulación de hilos, corrientes, etc para el sistema.

En primer lugar, vamos a ver un método de utilidad:

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

El nombre del método lo explica todo. Una vez que esté seguro de que DownloadManager está disponible, puede hacer algo como esto:

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

El progreso de la descarga se mostrará en la barra de notificación.

Pensamientos finales

Los métodos primero y segundo son sólo la punta del iceberg. Hay muchas cosas que tienes que tener en cuenta si quieres que tu aplicación sea robusta. Aquí hay una breve lista:

  • Debe comprobar si el usuario tiene una conexión a Internet disponible
  • Asegúrese de tener los permisos adecuados ( INTERNET y WRITE_EXTERNAL_STORAGE ); También ACCESS_NETWORK_STATE si desea comprobar la disponibilidad de Internet.
  • Asegúrese de que el directorio donde va a descargar archivos existen y tiene permisos de escritura.
  • Si la descarga es demasiado grande, es posible que desee implementar una forma de reanudar la descarga si los intentos anteriores fallaron.
  • Los usuarios estarán agradecidos si les permites interrumpir la descarga.

A menos que necesite un control detallado del proceso de descarga, considere utilizar DownloadManager (3) porque ya maneja la mayoría de los elementos enumerados anteriormente.

Pero también considere que sus necesidades pueden cambiar. Por ejemplo, DownloadManager no realiza la caché de respuestas . Descargará ciegamente el mismo archivo grande varias veces. No hay manera fácil de arreglarlo después del hecho. Donde si empiezas con una HttpURLConnection básica (1, 2), entonces todo lo que necesitas es agregar un HttpResponseCache . Así que el esfuerzo inicial de aprender las herramientas básicas y estándar puede ser una buena inversión.

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

Para más información, haga clic aquí http://androiddhina.blogspot.in/2015/09/how-to-download-pdf-from-url-in-android.html

  • Retrofit 2 archivo hacia abajo / subir
  • Android DownloadManager "Imposible abrir archivo"
  • Android: ¿Cómo puedo obtener el tamaño de archivo de un archivo FTP a través de FTPClient?
  • ANDROID: ¿Cómo puedo descargar un archivo de vídeo a una tarjeta SD?
  • ¿Cómo descarga un archivo a la carpeta Descargas de Android usando Phonegap?
  • Descarga de archivos / archivos subidos en Android
  • Descargar la aplicación de Google Play por programación
  • SocketException durante la descarga de archivos zip de gran tamaño
  • Android Webview: No se puede llamar a determinedVisibility () - nunca vio una conexión para el pid
  • Cómo guardar el archivo desde el sitio web a sdcard
  • ¿por qué mi portadora móvil re-codifica un archivo cuando lo descargo?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.