0

I am trying to parse an XML from online on my android project but I get an error. I tried parsing the xml as a basic java project and it works but I don't know how to implement it in my android project. The error on the console says android.os.networkmainthreadException. I did add the permission to App manifest. My code below:

package com.example.medrec;

import java.io.IOException;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import android.os.Build;

public class Details extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_details);

        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();
        }   
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.details, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

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

            //Code to parse starts here
            String name[] = null;
            String id[] = null;
            String type[] = null;
            String dosage[] = null;
            String remaining[] = null;

            DocumentBuilderFactory builderFactory = DocumentBuilderFactory
                    .newInstance();
            DocumentBuilder builder = null;
            try {
                builder = builderFactory.newDocumentBuilder();
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            }

            Document document = null;
            String xmlDocument = "http://www2.southeastern.edu/Academics/Faculty/jburris/emr.xml";
            try {
                document = builder.parse(new URL(xmlDocument).openStream());
            } catch (SAXException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }


            int total = 0;

            // Creates a list of nodes for the root element, emr
            NodeList emrRoot = document.getElementsByTagName("emr");
            // Gets the first node in the list... really just our root node
            Node emrNode = (Node) emrRoot.item(0);
            if (emrNode instanceof Element) {
                Element emrElement = (Element) emrNode;
                // Gets the list of all patient_info nodes
                NodeList patInfoList = emrElement
                        .getElementsByTagName("patient_order");

                // Total Number of Records
                total = patInfoList.getLength();
                System.out.println("Total number of records is: " + total);

                name = new String[total];
                id = new String[total];
                type = new String[total];
                dosage = new String[total];
                remaining = new String[total];
                // Gets the first patient_info node... the first in the list of
                // patients
                // Fill in the values of our strings. The first is tricky because
                // it is an attribute and not the content of the element.
                for (int i = 0; i < total; i++) {
                    Node patInfoNode = (Node) patInfoList.item(i);
                    if (patInfoNode instanceof Element) {
                        // Get the element information for parient_info
                        Element pat_info = (Element) patInfoNode;
                        // Get the name...
                        Node n = pat_info.getElementsByTagName("patientName").item(
                                0);
                        name[i] = n.getTextContent();
                        // Get the id...
                        n = pat_info.getElementsByTagName("patientID").item(0);
                        id[i] = n.getTextContent();
                        // Get the type...
                        n = pat_info.getElementsByTagName("type").item(0);
                        type[i] = n.getTextContent();
                        // Get the dosage...
                        n = pat_info.getElementsByTagName("dosage").item(0);
                        dosage[i] = n.getTextContent();
                        // Get the remaining...
                        n = pat_info.getElementsByTagName("refillsremaining").item(
                                0);
                        remaining[i] = n.getTextContent();
                    }
                }
            }

            //Toast.makeText(getApplicationContext(), type[5], Toast.LENGTH_SHORT).show();


            //Code ends here

            return rootView;
        }
    }

}

New Code with asyncTask

package com.example.medrec;

import java.io.IOException;
import java.net.URL;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import android.support.v7.app.ActionBarActivity;
import android.support.v7.app.ActionBar;
import android.support.v4.app.Fragment;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.StrictMode;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;
import android.os.Build;

public class Details extends ActionBarActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN);
        setContentView(R.layout.activity_details);
        new LongOperation().execute("");
        if (savedInstanceState == null) {
            getSupportFragmentManager().beginTransaction()
                    .add(R.id.container, new PlaceholderFragment()).commit();
        }   
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.details, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }


    private class LongOperation extends AsyncTask<String, Void, String> {
        @Override
        protected String doInBackground(String... params) {
            String name[] = null;
            String id[] = null;
            String type[] = null;
            String dosage[] = null;
            String remaining[] = null;

            DocumentBuilderFactory builderFactory = DocumentBuilderFactory
                    .newInstance();
            DocumentBuilder builder = null;
            try {
                builder = builderFactory.newDocumentBuilder();
            } catch (ParserConfigurationException e) {
                e.printStackTrace();
            }

            Document document = null;
            String xmlDocument = "http://www2.southeastern.edu/Academics/Faculty/jburris/emr.xml";
            try {
                document = builder.parse(new URL(xmlDocument).openStream());
            } catch (SAXException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }


            int total = 0;

            // Creates a list of nodes for the root element, emr
            NodeList emrRoot = document.getElementsByTagName("emr");
            // Gets the first node in the list... really just our root node
            Node emrNode = (Node) emrRoot.item(0);
            if (emrNode instanceof Element) {
                Element emrElement = (Element) emrNode;
                // Gets the list of all patient_info nodes
                NodeList patInfoList = emrElement
                        .getElementsByTagName("patient_order");

                // Total Number of Records
                total = patInfoList.getLength();
                System.out.println("Total number of records is: " + total);

                name = new String[total];
                id = new String[total];
                type = new String[total];
                dosage = new String[total];
                remaining = new String[total];
                // Gets the first patient_info node... the first in the list of
                // patients
                // Fill in the values of our strings. The first is tricky because
                // it is an attribute and not the content of the element.
                for (int i = 0; i < total; i++) {
                    Node patInfoNode = (Node) patInfoList.item(i);
                    if (patInfoNode instanceof Element) {
                        // Get the element information for parient_info
                        Element pat_info = (Element) patInfoNode;
                        // Get the name...
                        Node n = pat_info.getElementsByTagName("patientName").item(
                                0);
                        name[i] = n.getTextContent();
                        // Get the id...
                        n = pat_info.getElementsByTagName("patientID").item(0);
                        id[i] = n.getTextContent();
                        // Get the type...
                        n = pat_info.getElementsByTagName("type").item(0);
                        type[i] = n.getTextContent();
                        // Get the dosage...
                        n = pat_info.getElementsByTagName("dosage").item(0);
                        dosage[i] = n.getTextContent();
                        // Get the remaining...
                        n = pat_info.getElementsByTagName("refillsremaining").item(
                                0);
                        remaining[i] = n.getTextContent();
                    }
                }
            }

            Toast.makeText(getApplicationContext(), type[5], Toast.LENGTH_SHORT).show();




            return null;
        }

        @Override
        protected void onPostExecute(String result) {
        }

        @Override
        protected void onPreExecute() {
        }

        @Override
        protected void onProgressUpdate(Void... values) {
        }
    }

    /**
     * A placeholder fragment containing a simple view.
     */
    public static class PlaceholderFragment extends Fragment {

        public PlaceholderFragment() {
        }

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



            return rootView;
        }
    }

}

enter image description here

nishantvodoo
  • 835
  • 3
  • 17
  • 32
  • What line of code does the exception occur on? Did you debug to see what line it blows up on? – selbie Apr 25 '14 at 01:10
  • Also - never a good idea to download anything on the UI thread (which it appears you are attempting to do). The UI will freeze while your XML downloads and parses. Consider using an AsyncTask. – selbie Apr 25 '14 at 01:11
  • Oh Wait - that is YOUR error! – selbie Apr 25 '14 at 01:12
  • So how do I use AsyncTask? I have never done that. Can you provide me code and explain it? – nishantvodoo Apr 25 '14 at 01:12

2 Answers2

1

that is a NullPoint error ,I find you may be in the pat_info.getElementsByTagName("refillsremaining"),the "refillsremaining" should be "refillsrRmaining".The r is R.

chinaanihchen
  • 396
  • 2
  • 5
  • wow. I can't believe you caught that error. It's not crashing now. Thank you so much. also can i do a toast on the dobackground method? The Toast is crashing the app again. – nishantvodoo Apr 25 '14 at 02:05
  • In the inside Thread use Toast you should use the Looper.prepare() before Toast and Looper.loop() after Toast. – chinaanihchen Apr 25 '14 at 02:51
0

NetworkOnMainThreadException indicates you are trying to do a long blocking I/O operation on the UI thread. Move your XML download and parsing to its own thread - I recommend AsyncTask to get the job done. AsyncTask will issue a callback to your UI thread when the operation is done.

Example of AsyncTask: AsyncTask Android example

Another example: How to fix android.os.NetworkOnMainThreadException?

Community
  • 1
  • 1
selbie
  • 100,020
  • 15
  • 103
  • 173