Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Load document to WebView with JSOUP

I'm trying to parse a part of webpage to WebView. I'm using jsoup library to get part of page that i need, and then load to webview. Here is code:

public void loadArticleWithHTML (){
    Thread downloadThread = new Thread() {
        public void run() {
            try {
                doc = Jsoup.connect("http://en.wikipedia.org/").get();
                element = doc.select("#mp-itn b a");

            } catch (java.io.IOException e){
                e.printStackTrace();
            }
        }
    };
    downloadThread.start();

    mWebView.setWebViewClient(new WebViewClient() {
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            Toast.makeText(getApplicationContext(), description, Toast.LENGTH_SHORT).show();
        }
    });
    try {
        mWebView.loadData(element.html(), "text/html", "UTF-8");
    } catch (NullPointerException e){
        e.printStackTrace();
        Toast.makeText(getApplicationContext(), "error", Toast.LENGTH_LONG).show();
    }

}

But I always get an error

Attempt to invoke virtual method 'java.lang.String org.jsoup.select.Elements.html()' on a null object reference

like image 628
Personal Jesus Avatar asked Nov 07 '25 06:11

Personal Jesus


1 Answers

Your problem is that you are using a thread to download and parse the HTML content (that's the correct thing to do) and then you are trying to load from the Element object outside the thread. Because downloading the page takes some time to finish, you are calling element.html() before it has been initialize and is therefore null - which is why you are getting a NullPointerException.

To explain what's going on, lets look at the flow of your loadArticleWithHtml method:

  1. You create a thread that is supposed to download and parse HTML
  2. You start the thread and the downloading of the page probably starts
  3. You set the WebViewClient
  4. You load data into the WebView and try to access element.html() (element has not been initialized yet and is still null) and get a Null Pointer Exception
  5. Sometime after, the page downloading finishes and element is initialized

I suggest you read more about threading. When you use a thread, the process runs in parallel to the UI thread (which is where you are loading the HTML) and is not guaranteed to finish before the rest of your code in the UI thread does. In fact, doing work on the UI thread and starting a thread in the middle of it, it is almost guaranteed that the thread will finish after the UI code finishes if the code is doing anything slow like downloading.

So, the solution is to correctly thread your application and load the WebView AFTER the element variable has been initialized from within the thread. See below.

public void loadArticleWithHTML (){
    Thread downloadThread = new Thread() {
        public void run() {
            try {
                doc = Jsoup.connect("http://en.wikipedia.org/").get();
                element = doc.select("#mp-itn b a");

            } catch (java.io.IOException e){
                e.printStackTrace();
            }
            if (element == null) {
                Log.e("error", "There is a problem with the selection");
            } else {
                // post a new Runnable from a Handler in order to run the WebView loading code from the UI thread
                new Handler(Looper.getMainLooper()).post(new Runnable() {
                    @Override
                    public void run() {
                        mWebView.loadData(element.html(), "text/html", "UTF-8");
                    }
                });
            }
        }
    };

    mWebView.setWebViewClient(new WebViewClient() {
        public void onReceivedError(WebView view, int errorCode, String description, String failingUrl) {
            Toast.makeText(getApplicationContext(), description, Toast.LENGTH_SHORT).show();
        }
    });

    downloadThread.start();
}

Note, you need to run the WebView method from the UI thread as it is a view and should be accessed from the main thread. See this Q/A for additional info on running code on the UI thread.

like image 105
anthonycr Avatar answered Nov 09 '25 22:11

anthonycr