Android WebView无法加载或打开PDF文件,该如何解决?
WebView处理PDF链接的实现方案
问题原因
WebView默认仅支持渲染HTML等网页资源,无法直接处理PDF文件,因此需要拦截PDF链接并做自定义处理。
实现步骤
1. 拦截PDF链接
重写WebViewClient的shouldOverrideUrlLoading方法,识别PDF格式的链接并拦截默认处理:
webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); // 判断是否为PDF链接 if (url.endsWith(".pdf")) { // 选择需要的处理方式(打开/下载) openPdfWithSystemApp(url); // downloadPdfFile(url); return true; } return super.shouldOverrideUrlLoading(view, request); } });
2. 方案一:调用系统应用打开PDF
通过Intent调用手机已有的PDF阅读器打开链接:
private void openPdfWithSystemApp(String pdfUrl) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse(pdfUrl), "application/pdf"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { startActivity(intent); } catch (ActivityNotFoundException e) { Toast.makeText(this, "未找到可打开PDF的应用,请先安装PDF阅读器", Toast.LENGTH_SHORT).show(); } }
3. 方案二:实现PDF下载功能
使用系统DownloadManager完成下载,需先添加权限:
第一步:添加权限到AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28" />
(注:Android 10及以上使用分区存储,无需WRITE_EXTERNAL_STORAGE权限;若要保存到公共目录,需申请MANAGE_EXTERNAL_STORAGE权限)
第二步:实现下载方法
private void downloadPdfFile(String pdfUrl) { DownloadManager.Request request = new DownloadManager.Request(Uri.parse(pdfUrl)); request.setTitle("PDF下载"); request.setDescription("正在下载PDF文件"); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); // 设置保存到系统下载目录 request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "downloaded_pdf.pdf"); DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); if (downloadManager != null) { downloadManager.enqueue(request); Toast.makeText(this, "开始下载PDF", Toast.LENGTH_SHORT).show(); } }
4. 方案三:在WebView内直接加载PDF(可选)
如果需要在应用内渲染PDF,可使用第三方库(如AndroidPdfViewer):
第一步:添加依赖到build.gradle(Module)
implementation 'com.github.barteksc:android-pdf-viewer:3.2.0-beta.1'
第二步:布局中添加PDFView
<com.github.barteksc.pdfviewer.PDFView android:id="@+id/pdfView" android:layout_width="match_parent" android:layout_height="match_parent"/>
第三步:修改拦截逻辑,下载并加载PDF
private void loadPdfInApp(String pdfUrl) { new AsyncTask<Void, Void, File>() { @Override protected File doInBackground(Void... voids) { try { URL url = new URL(pdfUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.connect(); File tempFile = new File(getExternalFilesDir(null), "temp_pdf.pdf"); InputStream input = connection.getInputStream(); FileOutputStream output = new FileOutputStream(tempFile); byte[] buffer = new byte[1024]; int bytesRead; while ((bytesRead = input.read(buffer)) != -1) { output.write(buffer, 0, bytesRead); } output.close(); input.close(); return tempFile; } catch (IOException e) { e.printStackTrace(); return null; } } @Override protected void onPostExecute(File file) { if (file != null && file.exists()) { PDFView pdfView = findViewById(R.id.pdfView); webView.setVisibility(View.GONE); pdfView.setVisibility(View.VISIBLE); pdfView.fromFile(file).load(); } else { Toast.makeText(WebViewPage.this, "PDF加载失败", Toast.LENGTH_SHORT).show(); } } }.execute(); }
完整修改后的代码
public class WebViewPage extends AppCompatActivity { WebView webView; Button closeweb; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_web_view_page); webView = findViewById(R.id.webview); closeweb = findViewById(R.id.closeweb); WebSettings webSettings = webView.getSettings(); webSettings.setJavaScriptEnabled(true); webView.setWebViewClient(new WebViewClient() { @Override public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) { String url = request.getUrl().toString(); if (url.endsWith(".pdf")) { openPdfWithSystemApp(url); // downloadPdfFile(url); return true; } return super.shouldOverrideUrlLoading(view, request); } }); webView.loadUrl("https://www.google.in"); closeweb.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(WebViewPage.this, HomePage.class); startActivity(intent); } }); } private void openPdfWithSystemApp(String pdfUrl) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setDataAndType(Uri.parse(pdfUrl), "application/pdf"); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); try { startActivity(intent); } catch (ActivityNotFoundException e) { Toast.makeText(this, "未找到可打开PDF的应用,请先安装PDF阅读器", Toast.LENGTH_SHORT).show(); } } private void downloadPdfFile(String pdfUrl) { DownloadManager.Request request = new DownloadManager.Request(Uri.parse(pdfUrl)); request.setTitle("PDF下载"); request.setDescription("正在下载PDF文件"); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "downloaded_pdf.pdf"); DownloadManager downloadManager = (DownloadManager) getSystemService(DOWNLOAD_SERVICE); if (downloadManager != null) { downloadManager.enqueue(request); Toast.makeText(this, "开始下载PDF", Toast.LENGTH_SHORT).show(); } } @Override public void onBackPressed() { if (webView.canGoBack()) { webView.goBack(); } else { super.onBackPressed(); } } }
内容的提问来源于stack exchange,提问作者Abm
相关产品推荐
相关产品推荐

