问题
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
回答1:
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")
回答2:
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
}
}
}
回答3:
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.
来源:https://stackoverflow.com/questions/13728594/unable-to-start-activity-componentinfo