Android异步任务异常
Posted
技术标签:
【中文标题】Android异步任务异常【英文标题】:Android asynctask exception 【发布时间】:2012-10-26 23:52:29 【问题描述】:我正在做一个必须从 url 获取 XML 文件并对其进行解析的应用程序。我总是找到这个日志猫(PS:我找不到正确的 google prettify sintax 代码突出显示):
11-06 23:12:44.940: E/Trace(8751): error opening trace file: No such file or directory(2)
11-06 23:12:51.345: E/Error:(8751): expected: /hr read: body (position:END_TAG </body>@6:8 in java.io.StringReader@431887b8)
11-06 23:12:51.360: E/androidRuntime(8751): FATAL EXCEPTION: AsyncTask #1
11-06 23:12:51.360: E/AndroidRuntime(8751): java.lang.RuntimeException: An error occured while executing doInBackground()
11-06 23:12:51.360: E/AndroidRuntime(8751): at android.os.AsyncTask$3.done(AsyncTask.java:299)
11-06 23:12:51.360: E/AndroidRuntime(8751): at java.util.concurrent.FutureTask$Sync.innerSetException(FutureTask.java:273)
11-06 23:12:51.360: E/AndroidRuntime(8751): at java.util.concurrent.FutureTask.setException(FutureTask.java:124)
11-06 23:12:51.360: E/AndroidRuntime(8751): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:307)
11-06 23:12:51.360: E/AndroidRuntime(8751): at java.util.concurrent.FutureTask.run(FutureTask.java:137)
11-06 23:12:51.360: E/AndroidRuntime(8751): at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:230)
11-06 23:12:51.360: E/AndroidRuntime(8751): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1076)
11-06 23:12:51.360: E/AndroidRuntime(8751): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:569)
11-06 23:12:51.360: E/AndroidRuntime(8751): at java.lang.Thread.run(Thread.java:856)
11-06 23:12:51.360: E/AndroidRuntime(8751): Caused by: java.lang.NullPointerException
11-06 23:12:51.360: E/AndroidRuntime(8751): at com.ambro.app.Update$connection.doInBackground(Update.java:39)
11-06 23:12:51.360: E/AndroidRuntime(8751): at com.ambro.app.Update$connection.doInBackground(Update.java:1)
11-06 23:12:51.360: E/AndroidRuntime(8751): at android.os.AsyncTask$2.call(AsyncTask.java:287)
11-06 23:12:51.360: E/AndroidRuntime(8751): at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:305)
11-06 23:12:51.360: E/AndroidRuntime(8751): ... 5 more
xml 可以在以下位置找到:http://www.lookedpath.tk/apps/firstapp/version.xml
update.java 代码:
public class Update extends Activity
private TextView testo2;
@Override
public void onCreate(Bundle savedInstanceState)
setContentView(R.layout.update);
super.onCreate(savedInstanceState);
testo2= (TextView) findViewById(R.id.textView2);
public void goToUpdate (View view)
System.out.println("ciao");
new connection().execute();
public class connection extends AsyncTask<Void, Void, Boolean>
protected Boolean doInBackground(Void... params)
boolean updated=false;
String lastversion=null;
Element e=null;
final String URL = "http://www.lookedpath.tk/apps/firstapp/version.xml";
final String VERSION = "version";
final String APPLICATION = "application";
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(APPLICATION);
for (int i=0;i<nl.getLength();i++)
e = (Element) nl.item(0);
lastversion = parser.getValue(e, VERSION); // name child value
String actver = getString(R.string.version);
if(actver==lastversion) updated=true;
return updated;
protected void onPostExecute(Boolean... result)
if(result[0]==false)
testo2.setText(R.string.newversion);
else
testo2.setText(R.string.nonewversion);
;
这是 xmlparser.java 文件:
public class XMLParser
public String getXmlFromUrl(String url)
String xml = null;
try
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
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;
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 DOM
return doc;
public String getValue(Element item, String str)
NodeList n = item.getElementsByTagName(str);
return this.getElementValue(n.item(0));
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 "";
logcat 说错误在更新类的第 39 行:
NodeList nl = doc.getElementsByTagName(APPLICATION);
但我无法解决问题。谁能帮帮我?
更新: 我已经修复了错误 405,但我仍然有一个空指针异常。我发现程序运行正确,但由于这个异常,我从来没有进入 post execute 方法..
【问题讨论】:
【参考方案1】:嘿,看看我的Library。
您可以使用它轻松操作 XML ;)
【讨论】:
感谢您的回答,但我不明白如何使用您的代码来解析我的 xml :) 我是 android dev 的新手,您的帮助真的很有用 在您的链接中只有 4 行代码。在哪里可以找到源代码和 example.java?在您的代码中,您有 String myXMLDocument = "您可以查看此链接以从 xml 解析 xml。 http://www.androidhive.info/2012/02/android-custom-listview-with-image-and-text/
在您的活动中,您正在开发AsyncTask
,但您忘记覆盖onPreExecute
方法。请参阅此示例了解如何在您的活动中开发AsyncTask
。
package com.androidhive.jsonparsing;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.HashMap;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import android.app.ListActivity;
import android.app.ProgressDialog;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import android.widget.TextView;
public class AndroidJSONParsingActivity extends ListActivity
// url to make request
private static String url = "http://api.androidhive.info/contacts/";
// JSON Node names
private static final String TAG_CONTACTS = "contacts";
private static final String TAG_ID = "id";
private static final String TAG_NAME = "name";
private static final String TAG_EMAIL = "email";
private static final String TAG_ADDRESS = "address";
private static final String TAG_GENDER = "gender";
private static final String TAG_PHONE = "phone";
private static final String TAG_PHONE_MOBILE = "mobile";
private static final String TAG_PHONE_HOME = "home";
private static final String TAG_PHONE_OFFICE = "office";
static InputStream is = null;
static JSONObject jObj = null;
static String json = "";
// contacts JSONArray
JSONArray contacts = null;
@Override
public void onCreate(Bundle savedInstanceState)
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
new GetEventsTask().execute("");
protected class GetEventsTask extends
AsyncTask<String, Integer, ArrayList<HashMap<String, String>>>
protected ArrayList<HashMap<String, String>> contactList;
private final ProgressDialog dialog = new ProgressDialog(
AndroidJSONParsingActivity.this);
//PreExecute Method
protected void onPreExecute()
this.dialog.setMessage("Loading, Please Wait..");
this.dialog.setCancelable(false);
this.dialog.show();
//doInBackground Method
@Override
protected ArrayList<HashMap<String, String>> doInBackground(
String... params)
contactList = new ArrayList<HashMap<String, String>>();
// Making HTTP request
try
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
is = httpEntity.getContent();
BufferedReader reader = new BufferedReader(
new InputStreamReader(is, "iso-8859-1"), 8);
StringBuilder sb = new StringBuilder();
String line = null;
while ((line = reader.readLine()) != null)
sb.append(line + "\n");
is.close();
json = sb.toString();
catch (UnsupportedEncodingException e)
e.printStackTrace();
catch (ClientProtocolException e)
e.printStackTrace();
catch (IOException e)
e.printStackTrace();
// try parse the string to a JSON object
try
jObj = new JSONObject(json);
Log.i("json objects",""+json);
catch (JSONException e)
Log.e("JSON Parser", "Error parsing data " + e.toString());
try
// Getting Array of Contacts
contacts = jObj.getJSONArray(TAG_CONTACTS);
// looping through All Contacts
for (int i = 0; i < contacts.length(); i++)
JSONObject c = contacts.getJSONObject(i);
// Storing each json item in variable
String id = c.getString(TAG_ID);
String name = c.getString(TAG_NAME);
String email = c.getString(TAG_EMAIL);
String address = c.getString(TAG_ADDRESS);
String gender = c.getString(TAG_GENDER);
// Phone number is agin JSON Object
JSONObject phone = c.getJSONObject(TAG_PHONE);
String mobile = phone.getString(TAG_PHONE_MOBILE);
String home = phone.getString(TAG_PHONE_HOME);
String office = phone.getString(TAG_PHONE_OFFICE);
// creating new HashMap
HashMap<String, String> map = new HashMap<String, String>();
// adding each child node to HashMap key => value
map.put(TAG_ID, id);
map.put(TAG_NAME, name);
map.put(TAG_EMAIL, email);
map.put(TAG_PHONE_MOBILE, mobile);
// adding HashList to ArrayList
contactList.add(map);
catch (JSONException e)
e.printStackTrace();
return contactList;
//onPostExecute Method
protected void onPostExecute(ArrayList<HashMap<String, String>> result)
ListAdapter adapter = new SimpleAdapter(getApplicationContext(),
contactList, R.layout.list_item, new String[] TAG_NAME,
TAG_EMAIL, TAG_PHONE_MOBILE , new int[]
R.id.name, R.id.email, R.id.mobile );
// selecting single ListView item
ListView lv = getListView();
lv.setAdapter(adapter);
// Launching new screen on Selecting Single ListItem
lv.setOnItemClickListener(new OnItemClickListener()
@Override
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.email)).getText().toString();
String description = ((TextView) view.findViewById(R.id.mobile)).getText().toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(),SingleMenuItemActivity.class);
in.putExtra(TAG_NAME, name);
in.putExtra(TAG_EMAIL, cost);
in.putExtra(TAG_PHONE_MOBILE, description);
startActivity(in);
);
if (this.dialog.isShowing())
this.dialog.dismiss();
【讨论】:
现在我重写 onPreExecute 方法,但错误仍然相同。我已经使用了您链接的 xml 解析器,它是否显示此错误 不,我没有在这里使用 asny 任务。如果您从 url 获取数据,则首先在没有 asyn 任务的情况下进行解析,然后您会考虑 asyntask。在真实设备上运行它或检查您的 avd 互联网设置【参考方案3】:从日志中,我可以看到您在 Update.java 的第 39 行中有一个 NullPointer。您可以从那里开始。我相信它与 AsyncTask 无关。
【讨论】:
我看到错误在第 39 行,但我不明白错误在哪里。谢谢 NodeList nl = doc.getElementsByTagName(APPLICATION); 你检查过xml是否有效吗?看起来不是,这就是为什么你得到 null parser.getDomElement() 我认为 xml 文件是有效的,如果不是,我找不到错误:【参考方案4】:你在那个位置只得到空 xml,所以调试你的应用程序首先检查你得到的任何 xml 响应吗????
如果你得到 null xml 然后使用下面的代码来解析 xml
import org.xml.sax.Attributes;
import org.xml.sax.SAXException;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
public class XMLHandler extends DefaultHandler
String elementValue = null;
Boolean elementOn = false;
userdata d = userdata.getInstance();
public static XMLGettersSetters data = null;
public static XMLGettersSetters getXMLData()
return data;
public static void setXMLData(XMLGettersSetters data)
XMLHandler.data = data;
/**
* This will be called when the tags of the XML starts.
**/
@Override
public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException
elementOn = true;
if (localName.equals("application"))
data = new XMLGettersSetters();
/**
* This will be called when the tags of the XML end.
**/
@Override
public void endElement(String uri, String localName, String qName)
throws SAXException
elementOn = false;
/**
* Sets the values after retrieving the values from the XML tags
* */
if (localName.equalsIgnoreCase("version"))
System.out.println("ststus" + elementValue);
d.setIsregi(elementValue);
/**
* This is called to get the tags value
**/
@Override
public void characters(char[] ch, int start, int length)
throws SAXException
if (elementOn)
elementValue = new String(ch, start, length);
elementOn = false;
【讨论】:
【参考方案5】:我试过你的代码没有任何问题,没问题。问题出在链接中。
在浏览器中是这样的
<?xml version="1.0" encoding="UTF-8"?>
<menu>
<application>
<version>1.5</version>
</application>
</menu>
但是当我打印 xml 变量时它给了我
<html>
<head><title>405 Not Allowed</title></head>
<body bgcolor="white">
<center><h1>405 Not Allowed</h1></center>
<hr><center>nginx</center>
</body>
</html>
然后在 dom 变量中你得到 null 并且当你尝试在 nl 变量中找到为 null 的元素时你得到错误..,.
我用其他一些 xml 提要尝试了你的代码,效果很好..,.
【讨论】:
那么你有什么建议呢?我该如何修复 xml 文件? 对不起,我不知道。我得到“”“405 错误经常出现与 POST 方法。您可能试图在网站上引入某种输入表单,但并非所有 ISP 都允许处理表单所需的 POST 方法“” FROM checkupdown.com/status/E405.html 链接. 我已经修复了错误 405,但我仍然有一个空指针异常。我发现程序运行正确,但由于这个异常而从未进入 post execute 方法.. 您是否对代码进行了一些更改,因为这次我复制粘贴您的代码我得到了所需的结果 version=1.5 不,我没有,现在程序根本不会进入后执行方法。没有显示错误。我在 doinbackground 的末尾放了一个 println 并且消息显示正确,但是如果我把它放在 postexecutemethod 的开头,则消息不会出现在日志中【参考方案6】:您必须将正确的 DTD 添加到您的 xml(文档类型定义)中,尝试一下,您会看到解析运行顺利。 第 1 步:生成正确的 DTD 第 2 步:将其添加到您的 xml 文件并保存 第 3 步:上传您的 xml 文件,解析并享受。
【讨论】:
以上是关于Android异步任务异常的主要内容,如果未能解决你的问题,请参考以下文章
android:异步任务asyncTask介绍及异步任务下载图片(带进度条)