如何在Android下载PDF文件?

我想从url下载PDF文件。 为了查看pdf文件,我使用了下面的代码。

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

它正在工作,但我怎么从一个URL(例如http://.../example.pdf )获得PDF文件。 我想从这个URL 下载 PDF文件。 请帮帮我。 提前致谢。

Related of "如何在Android下载PDF文件?"

下载PDF与下载任何其他二进制文件相同。

  1. 打开一个HttpUrlConnection
  2. 使用连接的getInputStream()方法读取文件。
  3. 创build一个FileOutputStream并写入inputstream。

检查这个post ,例如源代码。

下载PDF文件:

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

啊,因为我刚刚发现这是依赖于设备。

场景

  1. 它将下载PDF到您的浏览器/下载/文件夹

  2. 你有一个谷歌文档帐户 – 它会要求你login,然后在浏览器中查看pdf

  3. 你有一个PDF阅读器安装 – 应用程序的依赖可能会抓住它可能不会

在所有情况下,尽pipe用户可以用一行代码访问PDF 🙂

有很多方法可以下载文件。 以下我会发布最常用的方法; 由您来决定哪种方法更适合您的应用程序。

1.使用AsyncTask并在对话框中显示下载进度

此方法将允许您执行一些后台进程并同时更新UI(在这种情况下,我们将更新进度条)。

这是一个示例代码:

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

AsyncTask将如下所示:

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

上面的方法( doInBackground )总是在后台线程上运行。 你不应该在那里做任何UI任务。 另一方面, onProgressUpdateonPreExecute在UI线程上运行,所以你可以改变进度条:

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

为了运行,你需要WAKE_LOCK权限。

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

2.从服务下载

这里最大的问题是: 如何从服务中更新我的活动? 。 在下一个示例中,我们将使用两个您可能不知道的类: ResultReceiverIntentServiceResultReceiver是允许我们从服务更新线程的那个; IntentServiceService一个子类,它产生一个线程来执行后台工作(你应该知道一个Service实际上在你的应用程序的同一个线程中运行;当你扩展Service ,你必须手动产生新线程来运行CPU阻塞操作) 。

下载服务可以像这样:

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

将该服务添加到您的清单:

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

活动将如下所示:

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

这里是ResultReceiver来玩:

 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使用Groundy库

Groundy是一个基本上可以帮助您在后台服务中运行代码的库,它基于上面显示的ResultReceiver概念。 目前这个库已经被弃用了。 这是整个代码的样子:

您正在显示对话框的活动…

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

GroundyTask用于下载文件并显示进度的GroundyTask实现:

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

只需将其添加到清单:

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

我觉得这不是件容易的事。 只要从Github抓来最新的jar子,你就可以走了。 请记住, Groundy的主要目的是在后台服务中调用外部REST API,并轻松地将结果发布到UI。 如果你在应用程序中做类似的事情,这可能是非常有用的。

2.2使用https://github.com/koush/ion

3.使用DownloadManager类( GingerBread和更新版本)

GingerBread带来了一个新function, DownloadManager ,它允许您轻松下载文件,并委托处理线程,stream等的辛勤工作,以系统。

首先,我们来看一个实用的方法:

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

方法的名字解释了这一切。 一旦你确定DownloadManager可用,你可以做这样的事情:

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

下载进度将显示在通知栏中。

最后的想法

第一种和第二种方法只是冰山一angular。 如果您希望自己的应用程序具有强大function,则需要记住很多事项。 这里是一个简短的列表:

  • 您必须检查用户是否有可用的互联网连接
  • 确保你有正确的权限( INTERNETWRITE_EXTERNAL_STORAGE ); 也ACCESS_NETWORK_STATE如果你想检查互联网的可用性。
  • 确保目录是你要下载的文件存在,并有写权限。
  • 如果下载太大,如果以前的尝试失败,可能需要实现一种恢复下载的方式。
  • 如果你允许他们中断下载,用户将不胜感激。

除非您需要详细控制下载过程,否则请考虑使用DownloadManager (3),因为它已经处理了大部分上面列出的项目。

但也要考虑到你的需求可能会改变。 例如, DownloadManager 不响应caching 。 它会盲目地多次下载同一个大文件。 事实之后没有简单的方法来修复它。 如果你从一个基本的HttpURLConnection (1,2)开始,那么你只需要添加一个HttpResponseCache 。 因此,学习基本的标准工具的初始努力可能是一个很好的投资。

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

欲了解更多信息,请点击这里http://androiddhina.blogspot.in/2015/09/how-to-download-pdf-from-url-in-android.html

有没有必要把冗长的代码打开和下载pdf在Android中,您可以使用下面的代码来打开和下载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)));