0

I want to download XML file from some URL and use it like input for my XMLPullParser.

XML is big - about 6-8Mb.

So I wrote AsyncTask for downloading XML and call it in my code, but I have got NullPointerException:

java.lang.RuntimeException: Unable to start activity java.lang.NullPointerException: Attempt to invoke interface method 'void org.xmlpull.v1.XmlPullParser.setInput(java.io.InputStream, java.lang.String)' on a null object reference

Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'void org.xmlpull.v1.XmlPullParser.setInput(java.io.InputStream, java.lang.String)' on a null object reference

Here starts my Activity and AsynTask:

public class Parsing extends AppCompatActivity {
    private final static String url = "http://validURL";
    InputStream parserInput;
    XmlPullParser parser;

    protected void onCreate(Bundle savedInstanceState) {
...
        try {
            parserInput = new GetXML(this).execute(url).get();
        } catch (ExecutionException e) {
            e.printStackTrace();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (XmlPullParserException e) {
            e.printStackTrace();
        }
...
}
    class GetXML extends AsyncTask<String, Void, InputStream> {
        private Parsing activity;
        private String url;
        private ProgressDialog pDialog;

        public GetXML(Parsing activity/*, String url*/) {
            this.activity = activity;
            this.url = url;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            pDialog = new ProgressDialog(activity);
            pDialog.setTitle("Getting XML");
            pDialog.setMessage("Loading...");
            pDialog.show();
        }

        @Override
        protected InputStream doInBackground(String... params) {
            try {
                URL url = new URL(this.url);
                HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                connection.setReadTimeout(10000 /* milliseconds */);
                connection.setConnectTimeout(15000 /* milliseconds */);
                connection.setRequestMethod("GET");
                connection.setDoInput(true);
                connection.connect();
                InputStream stream = connection.getInputStream();

                stream.close();
                return stream;

            } catch (Exception e) {
                e.printStackTrace();
                Log.e("AsyncTask", "exception");
                return null;
            }
        }

        @Override
        protected void onPostExecute(InputStream result) {
            pDialog.dismiss();
        if (result != null) {
            try {
                parser.setInput(result, null);
            } catch (XmlPullParserException e) {
                e.printStackTrace();
            }
        }
        }
    }


}

What is wrong in my code?

Why I am getting NullPointer exception instead of loading xml and setting it like input data for XMLPullParser?

So according to: What is a NullPointerException, and how do I fix it?

I should use ... = null; where I have not initialize object? But after initializing InputStream parserInput = null; I am getting the same error.

UPD

Parser:

        try {
            parserInput = new GetXML(this).execute(url).get();

            while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {

                switch (parser.getEventType()) {

                    case XmlPullParser.START_DOCUMENT:
                        ...
                        break;

                    case XmlPullParser.START_TAG:
                        tagname = parser.getName();
                        if (parser.getName().equals(iconsrc)) {                
                            ...

                        }
                        break;

                    case XmlPullParser.TEXT:
                        tagtext = parser.getText();
                        break;

                    case XmlPullParser.END_TAG:
                        parser.getName();

                        break;
                    default:
                        break;
                }
                parser.next();
            }

        } catch (Throwable t) {
            Toast.makeText(this,
                    "Error: " + t.toString(), Toast.LENGTH_LONG)
                    .show();
        }

It works with local xml.

UPD 2:

According to information in answers I have done:

        factory = XmlPullParserFactory.newInstance();
        factory.setNamespaceAware(true);
        parser = factory.newPullParser();

        new GetXML(this).execute(url).get();

        while (parser.getEventType() != XmlPullParser.END_DOCUMENT) {
...

And now I am getting:

org.xmlpull.v1.XmlPullParserException: setInput() must be called first. (position START_DOCUMENT null@1:1)

Here:http://theopentutorials.com/tutorials/android/xml/android-simple-xmlpullparser-tutorial/

I see parser.setInput(is, null); after parser initializing, so this code like mine:

new GetXML(this).execute(url).get();

What Is wrong now? It looks like block try with parser.setInput(); in onPostExecute() is not executing.

danyapd
  • 2,516
  • 1
  • 14
  • 23

2 Answers2

0

parser is not initialized and is NULL by default. It should be initialized before using its setInput(parserInput,null) method

Dmytro Batyuk
  • 957
  • 8
  • 15
  • how I should initialize it? `XmlPullParser parser = null;` is not correct – danyapd Apr 25 '19 at 11:05
  • 1
    You should look at the documentation. http://theopentutorials.com/tutorials/android/xml/android-simple-xmlpullparser-tutorial/ is old one but could be used as example – Dmytro Batyuk Apr 25 '19 at 11:09
  • I have take a look on this url and now I am getting new exception about `setInput()`, I have updated my question. – danyapd Apr 25 '19 at 13:33
0

Try this:

public class Parsing extends AppCompatActivity {
private final static String url = "http://validURL";
InputStream parserInput;
XmlPullParser parser;

protected void onCreate(Bundle savedInstanceState) {

    try {
        parserInput = new GetXML(this).execute(url).get();

    } catch (ExecutionException e) {
        e.printStackTrace();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (XmlPullParserException e) {
        e.printStackTrace();
    }
}
class GetXML extends AsyncTask<String, Void, InputStream> {
    private Parsing activity;
    private String url;
    private ProgressDialog pDialog;

    public GetXML(Parsing activity/*, String url*/) {
        this.activity = activity;
        this.url = url;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        pDialog = new ProgressDialog(activity);
        pDialog.setTitle("Getting XML");
        pDialog.setMessage("Loading...");
        pDialog.show();
    }

    @Override
    protected InputStream doInBackground(String... params) {
        try {
            URL url = new URL(this.url);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();
            connection.setReadTimeout(10000 /* milliseconds */);
            connection.setConnectTimeout(15000 /* milliseconds */);
            connection.setRequestMethod("GET");
            connection.setDoInput(true);
            connection.connect();
            InputStream stream = connection.getInputStream();

            stream.close();
            return stream;

        } catch (Exception e) {
            e.printStackTrace();
            Log.e("AsyncTask", "exception");
            return null;
        }
    }

    @Override
    protected void onPostExecute(InputStream result) {
        pDialog.dismiss();
        if(result!=null){
        parser.setInput(result,null);
    }
    }
 }
}
p.mathew13
  • 920
  • 8
  • 16
  • Getting `Attempted to invoke interface method ...getEventType() on a null object reference.` now. So it means that XML was not parsed. Also I see internet speed and understanding that application is not trying to download XML. – danyapd Apr 25 '19 at 11:47
  • I have update question with new code – danyapd Apr 25 '19 at 11:52
  • What you need to understand is that your parser is still null in the onCreate() function. parser gets your input in the onPostExecute of your asyncTask. So any operation that involves your parser should be triggered only after this method is invoked. so you should your while loop code to another function and invoke the function in onPostExecute after parser.setInput() is called. – p.mathew13 Apr 25 '19 at 11:57
  • Like Dmytro mentioned below you should also initialize your parser before calling your async task – p.mathew13 Apr 25 '19 at 12:01
  • I have done parser initializing and now getting exception about setInput(). I have updated my question. – danyapd Apr 25 '19 at 13:33