nicolas zimerman
nicolas zimerman

Reputation: 45

Android app crashes when using AsyncTask for fetching an url with jsoup

So the app shows up the dialog while loading but then crashes. Te reason I decided t use these technologies is because I have to load an html, which changes dynamically and there are heavy CSS files which I would like to cache, so I think including them as assets is a good idea. I use Jsoup because I am able to get the html page without having to download the full content. Here's the code:

public class MyWebViewFragment extends Fragment {

ProgressDialog mProgress;
WebView webview;

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
        Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.web_fragment, container,
            false);

    Bundle bundle = getArguments();

    String url = bundle.getString("url");

    webview = (WebView) rootView.findViewById(R.id.webview1);

    WebSettings settings = webview.getSettings();
    settings.setJavaScriptEnabled(true);

    mProgress = ProgressDialog.show(getActivity(), "Loading",
            "Please wait for a moment...");
    fetchUrl thread = (fetchUrl) new fetchUrl().execute();
    Document doc = thread.getDoc();
    String htmlData = null;
    doc.head().getElementsByTag("link").remove();
    doc.head().appendElement("link").attr("rel", "stylesheet").attr("type", "text/css").attr("href", "style.css");
    htmlData = doc.outerHtml();
    //TODO fetchURL here
    webview.loadDataWithBaseURL("file:///assets/", htmlData, "text/html", "UTF-8", null);

   // webview.loadUrl(url);
    webview.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            //TODO add assets loading he instead of urlLoad
            //view.loadUrl(url);
            return false;
        }

        @Override
        public void onPageFinished(WebView view, String url) {
            super.onPageFinished(view, url);
            if (mProgress.isShowing()) {
                mProgress.dismiss();
            }
        }
    });

    return rootView;
}

The class extending AsybcTask:

    private class fetchUrl extends AsyncTask<Void, Void, Document>{
    Document doc;
    @Override
    protected Document doInBackground(Void... param) {
        try {
          doc = Jsoup.connect("http://example.ch").userAgent("Chrome").get();//use url when ready
        } catch (IOException ex) {
    }
        return doc;   
    }


}

And the error log:

--------- beginning of crash
E/AndroidRuntime( 5125): FATAL EXCEPTION: main
E/AndroidRuntime( 5125): Process: com.flexenergy.swapp, PID: 5125
E/AndroidRuntime( 5125): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.flexenergy.swapp/com.flexenergy.swapp.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'org.jsoup.nodes.Element org.jsoup.nodes.Document.head()' on a null object reference
E/AndroidRuntime( 5125):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2325)
E/AndroidRuntime( 5125):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2390)
E/AndroidRuntime( 5125):    at android.app.ActivityThread.access$800(ActivityThread.java:151)
E/AndroidRuntime( 5125):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
E/AndroidRuntime( 5125):    at android.os.Handler.dispatchMessage(Handler.java:102)
E/AndroidRuntime( 5125):    at android.os.Looper.loop(Looper.java:135)
E/AndroidRuntime( 5125):    at android.app.ActivityThread.main(ActivityThread.java:5257)
E/AndroidRuntime( 5125):    at java.lang.reflect.Method.invoke(Native Method)
E/AndroidRuntime( 5125):    at java.lang.reflect.Method.invoke(Method.java:372)
E/AndroidRuntime( 5125):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
E/AndroidRuntime( 5125):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
E/AndroidRuntime( 5125): Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'org.jsoup.nodes.Element org.jsoup.nodes.Document.head()' on a null object reference
E/AndroidRuntime( 5125):    at com.flexenergy.swapp.MyWebViewFragment.onCreateView(MyWebViewFragment.java:49)
E/AndroidRuntime( 5125):    at android.app.Fragment.performCreateView(Fragment.java:2053)   
E/AndroidRuntime( 5125):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:894)
E/AndroidRuntime( 5125):    at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:1067)
E/AndroidRuntime( 5125):    at android.app.BackStackRecord.run(BackStackRecord.java:834)
E/AndroidRuntime( 5125):    at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1452)
E/AndroidRuntime( 5125):    at android.app.Activity.performStart(Activity.java:6005)
E/AndroidRuntime( 5125):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2288)
E/AndroidRuntime( 5125):    ... 10 more
W/ActivityManager( 1219):   Force finishing activity 1 com.flexenergy.swapp/.MainActivity
I/Choreographer( 1219): Skipped 30 frames!  The application may be doing too much work on its main thread.
E/EGL_emulation(  919): tid 919: eglCreateSyncKHR(1237): error 0x3004 (EGL_BAD_ATTRIBUTE)

Upvotes: 0

Views: 625

Answers (1)

Marco
Marco

Reputation: 707

AsyncTask is a concurrent process of your main thread so to use the result of that computation you need to wait until it completes his work.

You're trying to call doc.head() but doc is a null reference because the asyncTask has not completed, then has not initialized doc.

Do your stuff with doc in the OnPostExecute(result) method of the AsyncTask, in this way you'll be sure that doc is correctly initialized.

Upvotes: 1

Related Questions