Sunday, April 8, 2012

how to get html content from a webview?


which is the most simplest method to get html code from webview. i have tried several methods from stackoverflow and google.but cant 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");

}

}


Source: Tips4all

11 comments:

  1. 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" +
    "('<head>'+document.getElementsByTagName('html')[0].innerHTML+'</head>');");
    }
    });

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

    ReplyDelete
  2. 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("http://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 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.

    ReplyDelete
  3. 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;
    }

    ReplyDelete
  4. 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 Is it possible to get the HTML code from WebView
    and shout out to http://stackoverflow.com/users/325081/aymon-fournier for his answer.

    ReplyDelete
  5. 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.

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

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

    ReplyDelete
  8. check this link.
    http://xebralabs.blogspot.in/2011/03/extract-html-from-android-webview.html

    ReplyDelete
  9. 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!

    ReplyDelete
  10. 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;
    }

    ReplyDelete
  11. Android does not provide direct methods for getting vebview contents.

    You may please through your knowledge through and ask questions
    http://developer.android.com/reference/android/webkit/WebView.html

    ReplyDelete