【问题标题】:Android - Load PDF inside webviewAndroid - 在 webview 中加载 PDF
【发布时间】:2012-05-18 04:47:34
【问题描述】:

我有这个 webview 代码,我希望在用户单击 PDF 链接时打开 PDF 文件。这是代码,你能告诉我我必须在这个PDF区域内放什么吗?我尝试了许多不同的方法,但根本无法查看 PDF。感谢您的帮助。

webview.setWebViewClient ( new WebViewClient() {
    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // do your handling codes here, which url is the requested url
        // probably you need to open that url rather than redirect:
        if (url.startsWith("tel:")) {
            startActivity(new Intent(Intent.ACTION_DIAL, Uri.parse(url)));
        } else if (url.startsWith("mailto:")) {
            url = url.replaceFirst("mailto:", "");
            url = url.trim();
            Intent i = new Intent(Intent.ACTION_SEND);
            i.setType("plain/text").putExtra(Intent.EXTRA_EMAIL,
                    new String[]{url});
            startActivity(i);

        } else if (url.startsWith("geo:")) {
            try {
            } catch (Exception e) {
                System.out.println(e);
            }

        } else if (url.endsWith("pdf")) {

            try {

            } catch (Exception e) {
                System.out.println(e);
            }

        } else {
            view.loadUrl(url);
        }
        return true;
        // then it is not handled by default action
    }
});

【问题讨论】:

    标签: java android pdf webview webviewclient


    【解决方案1】:

    这可能很简单:

    try
    {
     Intent intentUrl = new Intent(Intent.ACTION_VIEW);
     intentUrl.setDataAndType(url, "application/pdf");
     intentUrl.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
     myActivity.startActivity(intentUrl);
    }
    catch (ActivityNotFoundException e)
    {
     Toast.makeText(myActivity, "No PDF Viewer Installed", Toast.LENGTH_LONG).show();
    }
    

    虽然我没有尝试过。

    在我们的应用程序中,我们将 PDF 下载到应用程序文件系统,使其可读,然后在 Intent 中传递路径以打开 PDF 查看应用程序(例如 Acrobat Reader)。请注意,您还需要清理这些下载的 PDF!

    在你的 try 块中放

    new DownloadPDFTask().execute(url);
    

    下载PDFTask类:

    public class DownloadPDFTask extends AsyncTask<String, Void, Integer> 
    {
        protected ProgressDialog mWorkingDialog;    // progress dialog
        protected String mFileName;         // downloaded file
        protected String mError;            // for errors
    
        @Override
        protected Integer doInBackground(String... urls)
        {
    
         try
         {
          byte[] dataBuffer = new byte[4096];
              int nRead = 0;
    
              // set local filename to last part of URL
              String[] strURLParts = urls[0].split("/");
              if (strURLParts.length > 0)
                mFileName = strURLParts[strURLParts.length - 1];
              else
                    mFileName = "REPORT.pdf";
    
              // download URL and store to strFileName
    
              // connection to url
          java.net.URL urlReport = new java.net.URL(urls[0]);
              URLConnection urlConn = urlReport.openConnection();
              InputStream streamInput = urlConn.getInputStream();
              BufferedInputStream bufferedStreamInput = new BufferedInputStream(streamInput);
              FileOutputStream outputStream = myActivity.openFileOutput(mFileName,Context.MODE_WORLD_READABLE); // must be world readable so external Intent can open!
              while ((nRead = bufferedStreamInput.read(dataBuffer)) > 0)
                    outputStream.write(dataBuffer, 0, nRead);
              streamInput.close();
              outputStream.close();
          }
          catch (Exception e)
          {
           Log.e("myApp", e.getMessage());
           mError = e.getMessage();
           return (1);
          }
    
         return (0);
        }
    
        //-------------------------------------------------------------------------
        // PreExecute - UI thread setup
        //-------------------------------------------------------------------------
    
        @Override
        protected void onPreExecute()
        {
         // show "Downloading, Please Wait" dialog
         mWorkingDialog = ProgressDialog.show(myActivity, "", "Downloading PDF Document, Please Wait...", true);
         return;
        }
    
        //-------------------------------------------------------------------------
        // PostExecute - UI thread finish
        //-------------------------------------------------------------------------
    
        @Override
        protected void onPostExecute (Integer result)
        {
             if (mWorkingDialog != null)
          {
           mWorkingDialog.dismiss();
           mWorkingDialog = null;
          }
    
             switch (result)
             {
             case 0:                            // a URL
    
                // Intent to view download PDF
                Uri uri  = Uri.fromFile(myActivity.getFileStreamPath(mFileName));
    
                try
                {
                    Intent intentUrl = new Intent(Intent.ACTION_VIEW);
                    intentUrl.setDataAndType(uri, "application/pdf");
                    intentUrl.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                    myActivity.startActivity(intentUrl);
                }
                catch (ActivityNotFoundException e)
                {
                    Toast.makeText(myActivity, "No PDF Viewer Installed", Toast.LENGTH_LONG).show();
                }
    
                break;
    
            case 1:                         // Error
    
                Toast.makeText(myActivity, mError, Toast.LENGTH_LONG).show();
                break;
    
            }
    
        }
    
    }
    

    任何对“myActivity”的引用都必须替换为对您的 Activity 类的引用

    【讨论】:

    • 是否可以在不运行异步下载任务的情况下仅从 web 视图中显示 PDF 文件?
    • 不,与 iOS 上的 UIWebView 不同,Android WebView 不显示 PDF 内容。您可以尝试直接调用意图(即没有 AsyncDownloadTask),但无论如何您都会离开您的活动。
    • 嗯,所以在 android 中最好的方法是调用 async 来下载文件并保存它。您知道该过程是否可以自动找到文件名并在SD卡上保存为该名称?我在使用它时总是指定名称。谢谢!
    • 我会尝试将您的 http://{file}.pdf 网址交给意图,我认为 PDF 查看器程序(例如 Acrobat)会处理其余的事情。如果没有,下载器任务应该给你一个很好的起点。这部分代码处理文件命名,它从您的 URL 中提取文件名: // 将本地文件名设置为 URL 的最后一部分 String[] strURLParts = urls[0].split("/"); if (strURLParts.length > 0) mFileName = strURLParts[strURLParts.length - 1];否则 mFileName = "REPORT.pdf";
    【解决方案2】:

    请在 webview 中查看处理重定向 url 和打开 PDF 而不下载的示例。

    private void init()
    {
        WebView webview = (WebView) findViewById(R.id.webview);
        WebSettings settings = webview.getSettings();
        settings.setJavaScriptEnabled(true);
        webview.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
    
        PdfWebViewClient pdfWebViewClient = new PdfWebViewClient(this, webview);
        pdfWebViewClient.loadPdfUrl(
                    "https://www.google.co.in/url?sa=t&rct=j&q=&esrc=s&source=web&cd=1&ved=0ahUKEwjgwIfp3KXSAhXrhFQKHQqEDHYQFggZMAA&url=http%3A%2F%2Fwww.orimi.com%2Fpdf-test.pdf&usg=AFQjCNERYYcSfMLS5ukBcT2Qy11YxEhXqw&cad=rja");
    }
    
    private class PdfWebViewClient extends WebViewClient
    {
        private static final String TAG = "PdfWebViewClient";
        private static final String PDF_EXTENSION = ".pdf";
        private static final String PDF_VIEWER_URL = "http://docs.google.com/gview?embedded=true&url=";
    
        private Context mContext;
        private WebView mWebView;
        private ProgressDialog mProgressDialog;
        private boolean isLoadingPdfUrl;
    
        public PdfWebViewClient(Context context, WebView webView)
        {
            mContext = context;
            mWebView = webView;
            mWebView.setWebViewClient(this);
        }
    
        public void loadPdfUrl(String url)
        {
            mWebView.stopLoading();
    
            if (!TextUtils.isEmpty(url))
            {
                isLoadingPdfUrl = isPdfUrl(url);
                if (isLoadingPdfUrl)
                {
                    mWebView.clearHistory();
                }
    
                showProgressDialog();
            }
    
            mWebView.loadUrl(url);
        }
    
        @SuppressWarnings("deprecation")
        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, String url)
        {
            return shouldOverrideUrlLoading(url);
        }
    
        @SuppressWarnings("deprecation")
        @Override
        public void onReceivedError(WebView webView, int errorCode, String description, String failingUrl)
        {
            handleError(errorCode, description.toString(), failingUrl);
        }
    
        @TargetApi(Build.VERSION_CODES.N)
        @Override
        public boolean shouldOverrideUrlLoading(WebView webView, WebResourceRequest request)
        {
            final Uri uri = request.getUrl();
            return shouldOverrideUrlLoading(webView, uri.toString());
        }
    
        @TargetApi(Build.VERSION_CODES.N)
        @Override
        public void onReceivedError(final WebView webView, final WebResourceRequest request, final WebResourceError error)
        {
            final Uri uri = request.getUrl();
            handleError(error.getErrorCode(), error.getDescription().toString(), uri.toString());
        }
    
        @Override
        public void onPageFinished(final WebView view, final String url)
        {
            Log.i(TAG, "Finished loading. URL : " + url);
            dismissProgressDialog();
        }
    
        private boolean shouldOverrideUrlLoading(final String url)
        {
            Log.i(TAG, "shouldOverrideUrlLoading() URL : " + url);
    
            if (!isLoadingPdfUrl && isPdfUrl(url))
            {
                mWebView.stopLoading();
    
                final String pdfUrl = PDF_VIEWER_URL + url;
    
                new Handler().postDelayed(new Runnable()
                {
                    @Override
                    public void run()
                    {
                        loadPdfUrl(pdfUrl);
                    }
                }, 300);
    
                return true;
            }
    
            return false; // Load url in the webView itself
        }
    
        private void handleError(final int errorCode, final String description, final String failingUrl)
        {
            Log.e(TAG, "Error : " + errorCode + ", " + description + " URL : " + failingUrl);
        }
    
        private void showProgressDialog()
        {
            dismissProgressDialog();
            mProgressDialog = ProgressDialog.show(mContext, "", "Loading...");
        }
    
        private void dismissProgressDialog()
        {
            if (mProgressDialog != null && mProgressDialog.isShowing())
            {
                mProgressDialog.dismiss();
                mProgressDialog = null;
            }
        }
    
        private boolean isPdfUrl(String url)
        {
            if (!TextUtils.isEmpty(url))
            {
                url = url.trim();
                int lastIndex = url.toLowerCase().lastIndexOf(PDF_EXTENSION);
                if (lastIndex != -1)
                {
                    return url.substring(lastIndex).equalsIgnoreCase(PDF_EXTENSION);
                }
            }
            return false;
        }
    }
    

    【讨论】:

      【解决方案3】:

      我试图处理这种完全相同的情况。我想出的解决方案如下。

      public boolean shouldOverrideUrlLoading(WebView view, String url) {
                  String cleanUrl = url;
                  if (url.contains("?")) {
                      // remove the query string
                      cleanUrl = url.substring(0,url.indexOf("?"));
                  }
      
                  if (cleanUrl.endsWith("pdf")) {
      
                      try {
                          Uri uriUrl = Uri.parse(cleanUrl);
                          Intent intentUrl = new Intent(Intent.ACTION_VIEW, uriUrl);
                          startActivity(intentUrl);
                          return true;
      
                      } catch (Exception e) {
                          System.out.println(e);
                          Toast.makeText(context,"No PDF Viewer Installed", Toast.LENGTH_LONG).show();
                      }
                  }
      
                  return false;
              }
      

      我需要确保它能够处理 pdf 链接,即使有查询字符串。由于 cleanUrl 需要以“pdf”结尾,因此仍然有点麻烦,但只要这是真的,这应该可以工作。如果您通过 php 脚本或其他方式提供 pdf,您可能需要更深入地挖掘,根据 MIME 类型或其他方式处理事情。

      【讨论】:

        【解决方案4】:

        在 webview 中加载 pdf:

        WebView wv = (WebView) view.findViewById(R.id.webPage);
                    wv.getSettings().setJavaScriptEnabled(true);
                    wv.setWebViewClient(new WebClient());
                    wv.loadUrl("http://drive.google.com/viewerng/viewer?embedded=true&url=" + mUrl);
                    wv.getSettings().setBuiltInZoomControls(true);
        

        mUrl - 将成为您的 pdf 链接

        【讨论】:

          【解决方案5】:

          FWIW,mozilla 有一个PDF-reader-entirely-in-JavaScript,它是 apache 许可的。如果您不介意额外的尺寸,可能值得研究。这样您就可以在浏览器中完成所有操作,而不必依赖第三方 PDF 阅读器。

          【讨论】:

            猜你喜欢
            • 2015-12-09
            • 1970-01-01
            • 2018-12-25
            • 1970-01-01
            • 2015-08-08
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多