【问题标题】:how to get html content from a webview?如何从 webview 中获取 html 内容?
【发布时间】:2012-01-02 07:27:07
【问题描述】:

从 webview 获取 html 代码的最简单方法是什么? 我尝试了 stackoverflow 和 google 的几种方法,但找不到确切的方法。请提供一个确切的方法。

public class htmldecoder extends Activity implements OnClickListener,TextWatcher
{
TextView txturl;
Button btgo;
WebView wvbrowser;
TextView txtcode;
ImageButton btcode;
LinearLayout llayout;
int flagbtcode;
public void onCreate(Bundle savedInstanceState)
{
            super.onCreate(savedInstanceState);
                setContentView(R.layout.htmldecoder);

    txturl=(TextView)findViewById(R.id.txturl);

    btgo=(Button)findViewById(R.id.btgo);
    btgo.setOnClickListener(this);

    wvbrowser=(WebView)findViewById(R.id.wvbrowser);
    wvbrowser.setWebViewClient(new HelloWebViewClient());
    wvbrowser.getSettings().setJavaScriptEnabled(true);
    wvbrowser.getSettings().setPluginsEnabled(true);
    wvbrowser.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
    wvbrowser.addJavascriptInterface(new MyJavaScriptInterface(),"HTMLOUT");
    //wvbrowser.loadUrl("http://www.google.com");
    wvbrowser.loadUrl("javascript:window.HTMLOUT.showHTML('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");


    txtcode=(TextView)findViewById(R.id.txtcode);
    txtcode.addTextChangedListener(this);

    btcode=(ImageButton)findViewById(R.id.btcode);
    btcode.setOnClickListener(this);

    }

public void onClick(View v)
{
    if(btgo==v)
    {
        String url=txturl.getText().toString();
        if(!txturl.getText().toString().contains("http://"))
        {
            url="http://"+url;
        }
        wvbrowser.loadUrl(url);
        //wvbrowser.loadData("<html><head></head><body><div style='width:100px;height:100px;border:1px red solid;'></div></body></html>","text/html","utf-8");
    }
    else if(btcode==v)
    {
        ViewGroup.LayoutParams params1=wvbrowser.getLayoutParams();
        ViewGroup.LayoutParams params2=txtcode.getLayoutParams();
        if(flagbtcode==1)
        {
            params1.height=200;
            params2.height=220;
            flagbtcode=0;
            //txtcode.setText(wvbrowser.getContentDescription());
        }
        else
        {
            params1.height=420;
            params2.height=0;
            flagbtcode=1;
        }
        wvbrowser.setLayoutParams(params1);
        txtcode.setLayoutParams(params2);

    }
}

public class HelloWebViewClient extends WebViewClient {
    @Override
    public boolean shouldOverrideUrlLoading(WebView view, String url) {

        view.loadUrl(url);
        return true;
    }
    /*@Override
    public void onPageFinished(WebView view, String url)
    {
        // This call inject JavaScript into the page which just finished loading. 
        wvbrowser.loadUrl("javascript:window.HTMLOUT.processHTML('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
    }*/

}
class MyJavaScriptInterface
{
    @SuppressWarnings("unused")
    public void showHTML(String html)
    {

        txtcode.setText(html);
    }
}

public void afterTextChanged(Editable s) {
    // TODO Auto-generated method stub

}

public void beforeTextChanged(CharSequence s, int start, int count,
        int after) {
    // TODO Auto-generated method stub

}

public void onTextChanged(CharSequence s, int start, int before, int count) {
    wvbrowser.loadData("<html><div"+txtcode.getText().toString()+"></div></html>","text/html","utf-8");

}

}

【问题讨论】:

    标签: android android-widget webview


    【解决方案1】:

    其实这个问题有很多答案。这是其中的两个:

    • 第一个和你的几乎一样,我猜我们是从同一个教程中得到的。

    public class TestActivity extends Activity {
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.webview);
            final WebView webview = (WebView) findViewById(R.id.browser);
            webview.getSettings().setJavaScriptEnabled(true);
            webview.addJavascriptInterface(new MyJavaScriptInterface(this), "HtmlViewer");
    
            webview.setWebViewClient(new WebViewClient() {
                @Override
                public void onPageFinished(WebView view, String url) {
                    webview.loadUrl("javascript:window.HtmlViewer.showHTML" +
                            "('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>');");
                }
            });
    
            webview.loadUrl("http://android-in-action.com/index.php?post/" +
                    "Common-errors-and-bugs-and-how-to-solve-avoid-them");
        }
    
        class MyJavaScriptInterface {
    
            private Context ctx;
    
            MyJavaScriptInterface(Context ctx) {
                this.ctx = ctx;
            }
    
            public void showHTML(String html) {
                new AlertDialog.Builder(ctx).setTitle("HTML").setMessage(html)
                        .setPositiveButton(android.R.string.ok, null).setCancelable(false).create().show();
            }
    
        }
    }
    

    这样您就可以通过 javascript 获取 html。不是最漂亮的方法,但是当您拥有 javascript 界面时,您可以添加其他方法来修补它。


    • 另一种方法是使用像 there 这样的 HttpClient。

    我认为,您选择的选项还取决于您打算如何处理检索到的 html...

    【讨论】:

    • 当执行这行webview.loadUrl("javascript:window.HtmlViewer.showHTML" + "('&lt;head&gt;'+document.getElementsByTagName('html')[0].innerHTML+'&lt;/head&gt;');");时,程序就像函数finish()一样,停止那个activity。为什么?如何解决?
    • webview.addJavascriptInterface 仅适用于果冻豆及更低版本。
    • Jellybean 及更高版本对上述代码的两个重要更改: 1. 删除“窗口”。从 webview.loadUrl 行 - 以 Jellybean 为目标时,javascript 界面的附加方式不同。 2. 将@JavascriptInterface 放在“public void showHTML”之前——这是必要的,因为不只允许调用某些方法存在安全风险。
    • 仍然对我不起作用 (5.1.1).. 当我添加 MyJavaScriptInterface(带有@karlbecker_com 提示)时,当我在加载的页面系统上单击某些内容时,会要求我选择浏览器。当我删除它时,它不会再问我了。
    • 这里我开启了远程调试,不管有没有@JavascriptInterface都显示Uncaught ReferenceError: HtmlViewer is not defined
    【解决方案2】:

    在 KitKat 及以上版本中,您可以在 webview 上使用evaluateJavascript 方法

    wvbrowser.evaluateJavascript(
            "(function() { return ('<html>'+document.getElementsByTagName('html')[0].innerHTML+'</html>'); })();",
             new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String html) {
                    Log.d("HTML", html); 
                    // code here
                }
        });
    

    更多示例请参见this 答案

    【讨论】:

    • 这是迄今为止最简单的解决方案
    • 仅供参考 - 需要 API 19。
    • 记得把这个放到onPageFinished方法中。
    • @Joel 如何在 API 19 下实现这一点?
    • 如果我的评论传达了错误的想法,@PratikSaluja 非常抱歉。这里投票最多的答案比我自己的答案要老得多,可能对你有用。没有别的意思。很高兴您通过寻找其他地方找到了答案顺便说一句。
    【解决方案3】:

    对于 android 4.2,不要忘记将@JavascriptInterface 添加到所有 javascript 函数中

    【讨论】:

    • 适用于 android 4.2 及以上版本。
    【解决方案4】:

    Android WebView 只是另一个渲染引擎,它渲染从 HTTP 服务器下载的 HTML 内容,很像 Chrome 或 FireFox。我不知道您需要从 WebView 获取渲染页面(或屏幕截图)的原因。在大多数情况下,这不是必需的。您始终可以直接从 HTTP 服务器获取原始 HTML 内容。

    已经发布了关于使用 HttpUrlConnection 或 HttpClient 获取原始流的答案。或者,在Android上处理HTML内容解析/处理时有一个非常方便的库:JSoup,它提供了非常简单的API来从HTTP服务器获取HTML内容,并提供HTML文档的抽象表示来帮助我们管理HTML解析不仅具有更面向对象的风格,而且更容易:

    // Single line of statement to get HTML document from HTTP server.
    Document doc = Jsoup.connect("http://en.wikipedia.org/").get();
    

    例如,当您想先下载 HTML 文档,然后添加一些自定义 css 或 javascript,然后将其传递给 WebView 进行渲染时,它会很方便。更多在他们的官方网站上,值得一试。

    【讨论】:

    • 当您需要启用 javascript 的浏览器来获取 HTML 时没有用处。例如 twitter.com
    【解决方案5】:

    我发现需要放置的一个接触点“隐藏”在 Proguard 配置中。虽然 HTML 阅读器在调试应用程序时通过 javascript 接口调用很好,但应用程序通过 Proguard 运行后就不再起作用,除非在 Proguard 配置文件中声明了 HTML 阅读器函数,如下所示:

    -keepclassmembers class <your.fully.qualified.HTML.reader.classname.here> {
        public *; 
    }
    

    在 Android 2.3.6、4.1.1 和 4.2.1 上测试并确认。

    【讨论】:

      【解决方案6】:

      出于安全考虑,Android 不允许您这样做。邪恶的开发者可以很容易地窃取用户输入的登录信息。

      相反,您必须在显示之前捕获 web 视图中显示的文本。如果您不想设置响应处理程序(根据其他答案),我通过谷歌搜索找到了这个修复:

      URL url = new URL("https://stackoverflow.com/questions/1381617");
      URLConnection con = url.openConnection();
      Pattern p = Pattern.compile("text/html;\\s+charset=([^\\s]+)\\s*");
      Matcher m = p.matcher(con.getContentType());
      /* If Content-Type doesn't match this pre-conception, choose default and 
       * hope for the best. */
      String charset = m.matches() ? m.group(1) : "ISO-8859-1";
      Reader r = new InputStreamReader(con.getInputStream(), charset);
      StringBuilder buf = new StringBuilder();
      while (true) {
        int ch = r.read();
        if (ch < 0)
          break;
        buf.append((char) ch);
      }
      String str = buf.toString();
      

      这是很多代码,你应该可以复制/粘贴它,在它的末尾str 将包含在 webview 中绘制的相同 html。这个答案来自Simplest way to correctly load html from web page into a string in Java,它也应该适用于Android。我没有测试过,也不是自己写的,但它可能会对你有所帮助。

      此外,此拉取的 URL 是硬编码的,因此您必须更改它。

      【讨论】:

        【解决方案7】:

        为什么不先获取 html 然后将其传递给 web 视图?

        private String getHtml(String url){
            HttpGet pageGet = new HttpGet(url);
        
            ResponseHandler<String> handler = new ResponseHandler<String>() {
                public String handleResponse(HttpResponse response) throws ClientProtocolException, IOException {
                    HttpEntity entity = response.getEntity();
                    String html; 
        
                    if (entity != null) {
                        html = EntityUtils.toString(entity);
                        return html;
                    } else {
                        return null;
                    }
                }
            };
        
            pageHTML = null;
            try {
                while (pageHTML==null){
                    pageHTML = client.execute(pageGet, handler);
                }
            } catch (ClientProtocolException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }
        
            return pageHTML;
        }
        
        @Override
        public void customizeWebView(final ServiceCommunicableActivity activity, final WebView webview, final SearchResult mRom) {
            mRom.setFileSize(getFileSize(mRom.getURLSuffix()));
            webview.getSettings().setJavaScriptEnabled(true);
            WebViewClient anchorWebViewClient = new WebViewClient()
            {
        
                @Override
                public void onPageStarted(WebView view, String url, Bitmap favicon) {
                    super.onPageStarted(view, url, favicon);
        
                    //Do what you want to with the html
                    String html = getHTML(url);
        
                    if( html!=null && !url.equals(lastLoadedURL)){
                        lastLoadedURL = url;
                        webview.loadDataWithBaseURL(url, html, null, "utf-8", url);
                    }
        }
        

        这应该大致做你想做的事。改编自Is it possible to get the HTML code from WebView 并大声喊出https://stackoverflow.com/users/325081/aymon-fournier 的答案。

        【讨论】:

        • HttpClient 在 API 级别 22 中已弃用,并在 API 级别 23 中删除。因此您的代码中提到的类无法导入到 java 文件中。
        【解决方案8】:

        我建议不要尝试从 WebView 中提取 HTML,而是从 URL 中提取 HTML。我的意思是使用第三方库(例如 JSoup)为您遍历 HTML。以下代码将为您从特定 URL 获取 HTML

        public static String getHtml(String url) throws ClientProtocolException, IOException {
                HttpClient httpClient = new DefaultHttpClient();
                HttpContext localContext = new BasicHttpContext();
                HttpGet httpGet = new HttpGet(url);
                HttpResponse response = httpClient.execute(httpGet, localContext);
                String result = "";
        
                BufferedReader reader = new BufferedReader(
                    new InputStreamReader(
                        response.getEntity().getContent()
                    )
                );
        
                String line = null;
                while ((line = reader.readLine()) != null){
                    result += line + "\n";
                }
                return result;
            }
        

        【讨论】:

        • 假设通过发布数据到达获取的url。这个方法会失败。
        • 还有 cookie 呢?
        【解决方案9】:

        实现简单只需要在你的 html 中使用 javasript 方法来获取 html 内容的价值。 如您的代码上方,需要进行一些更改。

          public class htmldecoder extends Activity implements OnClickListener,TextWatcher
            {
            Button btsubmit; // this button in your xml file
            WebView wvbrowser;
            public void onCreate(Bundle savedInstanceState)
            {
                        super.onCreate(savedInstanceState);
                            setContentView(R.layout.htmldecoder);
        
        
        
                btsubmit=(Button)findViewById(R.id.btsubmit);
                btsubmit.setOnClickListener(this);
        
                wvbrowser=(WebView)findViewById(R.id.wvbrowser);
                wvbrowser.setWebViewClient(new HelloWebViewClient());
                wvbrowser.getSettings().setJavaScriptEnabled(true);
                wvbrowser.getSettings().setPluginsEnabled(true);
                wvbrowser.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
                MyJavaScriptInterface myinterface=new MyJavaScriptInterface();
                wvbrowser.addJavascriptInterface(myinterface,"interface");
                webView.loadUrl("file:///android_asset/simple.html");  //use one html file for //testing put your html file in assets. Make sure that you done JavaScript methods to get //values for html content in html file . 
           }
           public void onClick(View v)
        {
            if(btsubmit==v)
            {
        
                webView.loadUrl("javascript:showalert()");// call javascript method.  
                //wvbr
            }
        }
        
        final class MyJavaScriptInterface {
        
        
        
                MyJavaScriptInterface() {
        
                }
        
                public void sendValueFromHtml(String value) {
                   System.out.println("Here is the value from html::"+value);
                }
        
            }
        
        }
        

        您在 html 中的 Javascript

         <script type="text/javascript">
            //<![CDATA[
            var n1;
            function callme(){
            n1=document.getElementById("FacadeAL").value;
            }
            function showalert(){
             window.interface.sendValueFromHtml(n1);// this method calling the method of interface which //you attached to html file in android. // & we called this showalert javasript method on //submmit buttton click of android. 
            }
            //]]>
            </script>
        

        & 确保你在 html 中调用 callme,如下所示

        &lt;input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/&gt;
        希望这会对你有所帮助。

        【讨论】:

        • 这是什么意思&amp; Make sure you calling callme like below in html。你的意思是把输入标签放在html文件的脚本下面吗? Thank You
        • 不,伙计,你必须调用 javasript 方法 callme() onblur 在 html 标记中输入类型文本。
        • 那么在哪里添加这个输入标签。这个按钮是否可见?
        • 这段代码的工作方式类似于,当加载活动时,webview 中有一个文本框,输入的文本显示在文本框中。但我想要 webview 中的 html 代码。
        • 你能帮我解决这个问题吗? Thank you very much
        【解决方案10】:

        【讨论】:

          【解决方案11】:

          如 Sephy 所说,尝试使用 HttpClient:

          public String getHtml(String url) {
              HttpClient vClient = new DefaultHttpClient();
              HttpGet vGet = new HttpGet(url);
              String response = "";    
          
              try {
                  ResponseHandler<String> vHandler = new BasicResponseHandler();
                  response = vClient.execute(vGet, vHandler);
              } catch (Exception e) {
                  e.printStackTrace();
              }
              return response;
          }
          

          【讨论】:

          • 你能展示一个简单的工作示例吗?我无法在 sephy 的示例中实现你的代码
          • 此方法将获取给定 url 的 html 源。即 getHtml(google.com);将为您提供谷歌主页的来源
          • 没关系。是否有任何选项可以获取 webview 源。 THANKS
          • 这有点不适合我。我没有从一个测试站点获得任何内容为“hello world”的内容。
          【解决方案12】:

          上面给出的方法适用于如果你有一个 web url,但如果你有一个本地 html,那么你也可以通过这段代码获得 html

          AssetManager mgr = mContext.getAssets();
                       try {
          InputStream in = null;              
          if(condition)//you have a local html saved in assets
                                      {
                                      in = mgr.open(mFileName,AssetManager.ACCESS_BUFFER);
                                     }
                                      else if(condition)//you have an url
                                      {
                                      URL feedURL = new URL(sURL);
                            in = feedURL.openConnection().getInputStream();}
          
                                      // here you will get your html
                           String sHTML = streamToString(in);
                           in.close();
          
                           //display this html in the browser or web view              
          
          
                       } catch (IOException e) {
                       // TODO Auto-generated catch block
                       e.printStackTrace();
                       }
                  public static String streamToString(InputStream in) throws IOException {
                      if(in == null) {
                          return "";
                      }
          
                      Writer writer = new StringWriter();
                      char[] buffer = new char[1024];
          
                      try {
                          Reader reader = new BufferedReader(new InputStreamReader(in, "UTF-8"));
          
                          int n;
                          while ((n = reader.read(buffer)) != -1) {
                              writer.write(buffer, 0, n);
                          }
          
                      } finally {
          
                      }
          
                      return writer.toString();
                  }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2012-06-04
            • 1970-01-01
            • 2011-01-23
            • 1970-01-01
            • 2018-11-01
            • 2014-08-21
            • 2016-06-21
            • 1970-01-01
            相关资源
            最近更新 更多