how to get html content from a webview?

AndroidAndroid WidgetWebview

Android Problem Overview


Which is the simplest method to get html code from a webview? I have tried several methods from stackoverflow and google, but can't find an exact method. Please mention an exact way.

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 Solutions


Solution 1 - Android

Actually this question has many answers. Here are 2 of them :

  • This first is almost the same as yours, I guess we got it from the same tutorial.

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

    }
}

This way your grab the html through javascript. Not the prettiest way but when you have your javascript interface, you can add other methods to tinker it.


  • An other way is using an HttpClient like there.

The option you choose also depends, I think, on what you intend to do with the retrieved html...

Solution 2 - Android

In KitKat and above, you could use evaluateJavascript method on webview

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

See this answer for more examples

Solution 3 - Android

For android 4.2, dont forget to add @JavascriptInterface to all javascript functions

Solution 4 - Android

Android WebView is just another render engine that render HTML contents downloaded from a HTTP server, much like Chrome or FireFox. I don't know the reason why you need get the rendered page (or screenshot) from WebView. For most of situation, this is not necessary. You can always get the raw HTML content from HTTP server directly.

There are already answers posted talking about getting the raw stream using HttpUrlConnection or HttpClient. Alternatively, there is a very handy library when dealing with HTML content parse/process on Android: JSoup, it provide very simple API to get HTML contents form HTTP server, and provide an abstract representation of HTML document to help us manage HTML parsing not only in a more OO style but also much easily:

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

It is handy when, for example, you want to download HTML document first then add some custom css or javascript to it before passing it to WebView for rendering. Much more on their official web site, worth to check it out.

Solution 5 - Android

One touch point I found that needs to be put in place is "hidden" away in the Proguard configuration. While the HTML reader invokes through the javascript interface just fine when debugging the app, this works no longer as soon as the app was run through Proguard, unless the HTML reader function is declared in the Proguard config file, like so:

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

Tested and confirmed on Android 2.3.6, 4.1.1 and 4.2.1.

Solution 6 - Android

Android will not let you do this for security concerns. An evil developer could very easily steal user-entered login information.

Instead, you have to catch the text being displayed in the webview before it is displayed. If you don't want to set up a response handler (as per the other answers), I found this fix with some googling:

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

This is a lot of code, and you should be able to copy/paster it, and at the end of it str will contain the same html drawn in the webview. This answer is from https://stackoverflow.com/questions/1381617/simplest-way-to-correctly-load-html-from-web-page-into-a-string-in-java and it should work on Android as well. I have not tested this and did not write it myself, but it might help you out.

Also, the URL this is pulling is hardcoded, so you'll have to change that.

Solution 7 - Android

Why not get the html first then pass it to the web view?

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

This should roughly do what you want to do. It is adapted from https://stackoverflow.com/questions/3479833/is-it-possible-to-get-the-html-code-from-webview and shout out to https://stackoverflow.com/users/325081/aymon-fournier for his answer.

Solution 8 - Android

I would suggest instead of trying to extract the HTML from the WebView, you extract the HTML from the URL. By this, I mean using a third party library such as JSoup to traverse the HTML for you. The following code will get the HTML from a specific URL for you

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

Solution 9 - Android

Its Simple to implement Just need javasript methods in your html to get value of html content. As Above your code some changes to be need.

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

    }

}

Your Javascript in html

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

& Make sure you calling callme like below in html

<input name="FacadeAL" id="FacadeAL" type="text" size="5" onblur="callme()"/>
Hope this will help you.

Solution 10 - Android

I suggest to try out some Reflection approach, if you have time to spend on the debugger (sorry but I didn't have).

Starting from the loadUrl() method of the android.webkit.WebView class:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/webkit/WebView.java#WebView.loadUrl%28java.lang.String%2Cjava.util.Map%29

You should arrive on the android.webkit.BrowserFrame that call the nativeLoadUrl() native method:

http://grepcode.com/file/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1/android/webkit/BrowserFrame.java#BrowserFrame.nativeLoadUrl%28java.lang.String%2Cjava.util.Map%29

The implementation of the native method should be here:

http://gitorious.org/0xdroid/external_webkit/blobs/a538f34148bb04aa6ccfbb89dfd5fd784a4208b1/WebKit/android/jni/WebCoreFrameBridge.cpp

Wish you good luck!

Solution 11 - Android

try using HttpClient as Sephy said:

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

Solution 12 - Android

above given methods are for if you have an web url ,but if you have an local html then you can have also html by this code

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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Questionuser765970View Question on Stackoverflow
Solution 1 - AndroidSephyView Answer on Stackoverflow
Solution 2 - AndroidAkashView Answer on Stackoverflow
Solution 3 - Androiduser1842354View Answer on Stackoverflow
Solution 4 - AndroidyorkwView Answer on Stackoverflow
Solution 5 - Androiduser1756541View Answer on Stackoverflow
Solution 6 - AndroidedthethirdView Answer on Stackoverflow
Solution 7 - AndroidKarl LView Answer on Stackoverflow
Solution 8 - AndroidMimminitoView Answer on Stackoverflow
Solution 9 - AndroidMr. Sajid ShaikhView Answer on Stackoverflow
Solution 10 - AndroidlechuckcaptainView Answer on Stackoverflow
Solution 11 - AndroidChristoper HansView Answer on Stackoverflow
Solution 12 - AndroidvipinView Answer on Stackoverflow