Unable to start activity ComponentInfo{

2019-09-09 13:58发布

I have the following mistake:

12-05 20:35:31.005: E/AndroidRuntime(1084): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.helplawyer/com.example.helplawyer.AndroidXMLParsingActivity}: android.os.NetworkOnMainThreadException

in xml manifest I added <uses-permission android:name="android.permission.INTERNET" />

this is my main class

package com.example.helplawyer;


public class AndroidXMLParsingActivity extends ListActivity {

// All static variables
static final String URL = "http://www.consultant.ru/rss/hotdocs.xml";
// XML node keys
static final String KEY_ITEM = "item"; // parent node
static final String KEY_TITLE = "title";
static final String KEY_DATE = "pubDate";
static final String KEY_LINK = "link";
static final String KEY_DESC = "description";

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.mainxml);

    ArrayList<HashMap<String, String>> menuItems = new ArrayList<HashMap<String, String>>();

    XMLParser parser = new XMLParser();
    String xml = parser.getXmlFromUrl(URL); // getting XML
    Document doc = parser.getDomElement(xml); // getting DOM element

    NodeList nl = doc.getElementsByTagName(KEY_ITEM);
    // looping through all item nodes <item>
    for (int i = 0; i < nl.getLength(); i++) {
        // creating new HashMap
        HashMap<String, String> map = new HashMap<String, String>();
        Element e = (Element) nl.item(i);
        // adding each child node to HashMap key => value

        map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
        map.put(KEY_LINK, parser.getValue(e, KEY_LINK));
        map.put(KEY_DATE, parser.getValue(e, KEY_DATE));
        map.put(KEY_DESC, parser.getValue(e, KEY_DESC));

        // adding HashList to ArrayList
        menuItems.add(map);
    }

    // Adding menuItems to ListView
    ListAdapter adapter = new SimpleAdapter(this, menuItems,
            R.layout.list_item,
            new String[] { KEY_TITLE, KEY_DESC, KEY_DATE, KEY_LINK }, new int[] {
                    R.id.name, R.id.description, R.id.cost, R.id.link });

    setListAdapter(adapter);

    // selecting single ListView item
    ListView lv = getListView();

    lv.setOnItemClickListener(new OnItemClickListener() {

        public void onItemClick(AdapterView<?> parent, View view,
                int position, long id) {
            // getting values from selected ListItem
            String name = ((TextView) view.findViewById(R.id.name)).getText().toString();
            String cost = ((TextView) view.findViewById(R.id.cost)).getText().toString();
            String link = ((TextView) view.findViewById(R.id.link)).getText().toString();
            String description = ((TextView) view.findViewById(R.id.description)).getText().toString();

            // Starting new intent
            Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
            in.putExtra(KEY_TITLE, name);
            in.putExtra(KEY_DATE, cost);
            in.putExtra(KEY_LINK, link);
            in.putExtra(KEY_DESC, description);
            startActivity(in);

        }
    });
}

}

XMLParser

package com.example.helplawyer;

public class XMLParser {

// constructor
public XMLParser() {

}

/**
 * Getting XML from URL making HTTP request
 * @param url string
 * */
public String getXmlFromUrl(String url) {
    String xml = null;

    try {
        // defaultHttpClient
        DefaultHttpClient httpClient = new DefaultHttpClient();
        HttpGet httpGet = new HttpGet(url);

        HttpResponse httpResponse = httpClient.execute(httpGet);
        HttpEntity httpEntity = httpResponse.getEntity();
        xml = EntityUtils.toString(httpEntity);

    } catch (UnsupportedEncodingException e) {
        e.printStackTrace();
    } catch (ClientProtocolException e) {
        e.printStackTrace();
    } catch (IOException e) {
        e.printStackTrace();
    }
    // return XML
    return xml;
}

/**
 * Getting XML DOM element
 * @param XML string
 * */
public Document getDomElement(String xml){
    Document doc = null;
    DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
    try {

        DocumentBuilder db = dbf.newDocumentBuilder();

        InputSource is = new InputSource();
            is.setCharacterStream(new StringReader(xml));
            doc = db.parse(is); 

        } catch (ParserConfigurationException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        } catch (SAXException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        } catch (IOException e) {
            Log.e("Error: ", e.getMessage());
            return null;
        }

        return doc;
}

/** Getting node value
  * @param elem element
  */
 public final String getElementValue( Node elem ) {
     Node child;
     if( elem != null){
         if (elem.hasChildNodes()){
             for( child = elem.getFirstChild(); child != null; child = child.getNextSibling() ){
                 if( child.getNodeType() == Node.TEXT_NODE  ){
                     return child.getNodeValue();
                 }
             }
         }
     }
     return "";
 }

 /**
  * Getting node value
  * @param Element node
  * @param key string
  * */
 public String getValue(Element item, String str) {     
        NodeList n = item.getElementsByTagName(str);        
        return this.getElementValue(n.item(0));
    }

}

I read on stackoverflow that I need to use new Thread(new Runnable() { but I don't understand how to rewrite my code that my app works good. Please, help me with my problem! Thank you

3条回答
欢心
2楼-- · 2019-09-09 14:20

From the Android documentation.

The exception that is thrown when an application attempts to perform a networking operation on its main thread.

This is only thrown for applications targeting the Honeycomb SDK or higher. Applications targeting earlier SDK versions are allowed to do networking on their main event loop threads, but it's heavily discouraged. See the document Designing for Responsiveness.

Also see StrictMode.

Look here for examples of running this operation in the background (Find "How to Avoid ANRs")

查看更多
beautiful°
3楼-- · 2019-09-09 14:25

You cannot access network from your main thread. you need to use AsyncTask . Check my answer at Android Connecting with PHP and MySql Force Close

Note the AsyncTask<String, Void, String>, here first String is the parameter to doInBackground , Void is parameter to onProgressUpdate(), we are not implementing this method, second String is parameter to onPostExecute()

Now, from MainActivity when you call new InnerClass().execute(urltoxml); Android will automatically call doInBackground() and will pass urltoxml as the argument`

Do all your network stuff inside doInbackground, when finished, doInBackground will return a result string and android will pass that as the parameter to onPostExecute(). Use that string however you want from onPostExecute

public class MainActivity extends Activity implements OnClickListener{ 

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button button = (Button)findViewById(R.id.button1);
    button.setOnClickListener( new OnClickListener(){

    @Override
    public void onClick(View v){
        new InnerClass().execute(urltoxml);
    }

    });
}

public class InnerClass extends AsyncTask<String, Void, String>{


    @Override
    protected String doInBackground(String... arg0) {
        String returnVal;
        //process your xml here
        //store the result in returnVal;
        return returnVal;
    }

    @Override
    protected void onPostExecute(String result) {
        //do something with the data
    }

}

}
查看更多
等我变得足够好
4楼-- · 2019-09-09 14:34

You are running Network Request on main UI thread.

Android >=3.0 does not allow to run Network Request on main UI thread. You need to use

AsyncTask to do network operation.

查看更多
登录 后发表回答