I'm creating a weather app which gets the min/max temperature from a 5 day forecast XML with same node names. I want to use the current date to look through the XML and find the correct min/max for that day.
This is the weather XML: Link
Here is my code, I've trimmed it just enough to the part where I don't understand the multi-nodes, but still I wanted it to be reusable (Currently it just gets the first min/max as denoted by a 0):
public class MyAsyncTask extends AsyncTask < Void, Void, String > {
//========================== pre execute to get date for xml =======
protected void onPreExecute() {
try {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
} catch (Exception e) {}
}#
Override
protected String doInBackground(Void...params) {
//=========================== Load data using xml ================
try {
URL xmlUrl2 = new URL("http://api.openweathermap.org/data/2.5/forecast/daily?q=london&mode=xml&units=metric&cnt=5");
InputStream inm = xmlUrl2.openStream();
Document docm = parsem(inm);
docm.getDocumentElement().normalize();
Node nNodem = docm.getElementsByTagName("temperature").item(0);
Element eElementm = (Element) nNodem;
double dmax = Math.round(Double.parseDouble(eElementm.getAttribute("max")));
int dxmax = (int) dmax;
xmaxtemp = Integer.toString(dxmax);
double dmin = Math.round(Double.parseDouble(eElementm.getAttribute("min")));
int dxmin = (int) dmin;
xmintemp = Integer.toString(dxmin);
} catch (UnknownHostException s) {
internet = false;
} catch (IOException i) {
System.out.println("IO Exception error!");
} catch (Exception ex) {
ex.printStackTrace();
}
return xtemp;
}
//========================= show data===============
#
Override
protected void onPostExecute(String result) {
TextView minmax = (TextView) findViewById(R.id.minmax);
minmax.setText("↑" + xmaxtemp + " " + xmintemp + "↓");
}
//======================== parse document =======
public static Document parse(InputStream is) {
Document ret = null;
DocumentBuilderFactory domFactory;
DocumentBuilder builder;
try {
domFactory = DocumentBuilderFactory.newInstance();
domFactory.setValidating(false);
domFactory.setNamespaceAware(false);
builder = domFactory.newDocumentBuilder();
ret = builder.parse(is);
} catch (Exception ex) {
System.err.println("unable to load XML: " + ex);
}
return ret;
}
}
For better use, u should use xpath to have a perfect manipulation over ur xml data:
this is an example how to get all temperature nodes
String expression = "//temperature";
NodeList nodeList = (NodeList) xPath.compile(expression).evaluate(xmlDocument, XPathConstants.NODESET);
After that you can manipulate the list.
this is a good tuto to start using xpath with java:
java-xml-xpath-tutorial/
Related
public String getMetaData() {
String errors = "";
try {
URL url = new URL("http://in2streaming.com:9999/stats?sid=1.xml");
URLConnection conn = url.openConnection();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// Error Here:
Document doc = db.parse(conn.getInputStream().toString());
// get the root node
NodeList nodeList = doc.getElementsByTagName("SHOUTCASTSERVER");
Node node=nodeList.item(0);
// the node has three child nodes
for (int i = 0; i < node.getChildNodes().getLength(); i++) {
Node temp=node.getChildNodes().item(i);
if(temp.getNodeName().equalsIgnoreCase("SONGTITLE")){
return temp.getTextContent();
}
}
return "Couldn't reach XML";
}
catch (Exception e) {
return "Exception ";
}
}
Calling this function via Runnable, Got Exception android.os.NetworkOnMainThreadException
I might change the link to http://in2streaming.com:9999/7.html and use HTMl parser instead
// Refresh meta data
private final Runnable refresh_meta = new Runnable() {
#Override
public void run() {
Toast.makeText(m_context, getMetaData(), Toast.LENGTH_SHORT).show();
m_handler.postDelayed(this, 5000);
}
};
For NetworkOnMainThreadException(You can also use AsyncTask):
Executors.newSingleThreadExecutor().submit(new Runnable() {
#Override
public void run() {
Toast.makeText(MainActivity.this, getMetaData(), Toast.LENGTH_SHORT).show();
}
});
If you want to Schedule every 5 sec.
You can use ScheduledExecutorService
ScheduledExecutorService worker = Executors.newSingleThreadScheduledExecutor();
worker.scheduleAtFixedRate(refresh_meta,
1, //initial delay
5, //run every 5 seconds
TimeUnit.SECONDS);
And Update your Runnable as
private Runnable refresh_meta = new Runnable() {
#Override
public void run() {
final String text = getMetaData();
runOnUiThread(new Runnable() {
#Override
public void run() {
Toast.makeText(m_context, text, Toast.LENGTH_SHORT).show();
}
}
);
}
};
Also,
Change Document doc = db.parse(conn.getInputStream().toString()); to
Document doc = db.parse(conn.getInputStream());
First some remarks:
a) Do not muffle the exceptions like you do here :
catch (Exception e) {
return "Exception ";
}
This way you will never know what was the exception that was thrown. It is better to log/print the exception's stack trace, for example:
catch (Exception e) {
Log.e("TAG", "Error", e);
return "Exception";
}
b) conn.getInputStream().toString() doesn't do what you suppose it does (convert the InputStream to String). DocumentBuilder's parse method takes an InputStream as parameter no need to convert it to String.
Having the above in mind here is your method:
public String getMetaData() {
String errors = "";
try {
URL url = new URL("http://in2streaming.com:9999/stats?sid=1.xml");
URLConnection conn = url.openConnection();
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// Error Here:
Document doc = db.parse(conn.getInputStream());
// get the root node
NodeList nodeList = doc.getElementsByTagName("SHOUTCASTSERVER");
Node node=nodeList.item(0);
// the node has three child nodes
for (int i = 0; i < node.getChildNodes().getLength(); i++) {
Node temp=node.getChildNodes().item(i);
if(temp.getNodeName().equalsIgnoreCase("SONGTITLE")){
return temp.getTextContent();
}
}
return "Couldn't reach XML";
}
catch (Exception e) {
Log.e("TAG", "Error in getMetaData()", e);
return "Exception ";
}
}
Try running your app again and if an error arises from this method it will be printed in your logcat with the message "Error in getMetaData()". Update your question accordingly with the error to let other members help you.
I have a running async task in my android application which runs perfectly. However I would like to know if it possible to return a string value from the asynctask in android as well as update a UI item. I want to update to a rating stars in the UI update and return a list of information from my server (which is working now).
Is it possible to return a value and update a UI from one asynctask in android??
Code for my Asynctask is below:
public class ConnectToServer extends AsyncTask< String, String, ArrayList<String>> {
#Override
protected ArrayList<String> doInBackground(String... params)
{
Socket client;
DataInputStream input;
DataOutputStream output;
String results = "";
XMLCreator x = new XMLCreator();
ArrayList<String> lists = new ArrayList<String>();
try
{
Log.i("CLIENT", "Client started");
// Step 1: Create a Socket to make connection.
// client = new Socket(InetAddress.getLocalHost(), 500);
client = new Socket("*****", 5001);
Log.i("CLIENT", "Connected to: "
+ client.getInetAddress().getHostName());
publishProgress("Connected...");
// Step 2: Get the input and output streams.
input = new DataInputStream(client.getInputStream());
output = new DataOutputStream(client.getOutputStream());
Log.i("CLIENT", "Got I/O Streams");
publishProgress("Obtained Streams...");
// Step 3: Process connection.
//Read in the value that the user selected from the bundle
String Day = params[0].toString();
//put into XML document as a query
//create a string
Document doc;
try
{
//Create an XML document with tutor's student number
doc = x.createDoc();
Element tutor = doc.createElement("Query");
tutor.appendChild(x.createDayforSession(doc, "GetSessionByDay", Day));
doc.appendChild(tutor);
//Create a string
String s = x.getStringFromDocument(doc);
output.writeUTF(s);
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
publishProgress("Processing");
//Get all the session information for that day in XML string
//Create a document
//Break it up and add it to the view
results = input.readUTF();
try
{
//Creates the document
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder = factory.newDocumentBuilder();
Document document = builder.parse(new InputSource(new StringReader(results)));
//optional, but recommended
//read this - http://stackoverflow.com/questions/13786607/normalization-in-dom-parsing-with-java-how-does-it-work
document.getDocumentElement().normalize();
//Look at root node's type (e.g. <query> or <login> or <add>)
String rootNode = document.getDocumentElement().getNodeName().toString();
if (rootNode.equals("Result"))
{
//Any methods which need to be called that will be used to query the database
//Always sending the String XML through as a parameter
//Look at the child node
NodeList nList = document.getElementsByTagName("Query");
System.out.println("----------------------------");
for (int temp = 0; temp < nList.getLength(); temp++)
{
Node nNode = nList.item(temp);
if (nNode.getNodeType() == Node.ELEMENT_NODE)
{
Element eElement = (Element) nNode;
String Semester = eElement.getElementsByTagName("Semester").item(0).getTextContent();
String StartTime = eElement.getElementsByTagName("StartTime").item(0).getTextContent();
String Days = eElement.getElementsByTagName("Day").item(0).getTextContent();
String Lab = eElement.getElementsByTagName("Lab").item(0).getTextContent();
String session = "Semester: " + Semester + "\n" + "StartTime: " + StartTime + "\n" + "Days: " + Days + "\n" + "Lab: " + Lab + "\n";
lists.add(session);
}
}
}
}
catch (Exception e)
{
e.getMessage();
}
// Step 4: Close connection.
Log.i("CLIENT", "Transmission complete. "
+ "Closing connection.");
output.writeUTF("TERMINATE");
client.close();
publishProgress("Closed connection...");
} catch (IOException e) {
e.printStackTrace();
}
return lists;
}
#Override
protected void onPostExecute(ArrayList<String> lists)
{
super.onPostExecute(lists);
//UPDATE A STAR RATING HERE
}
#Override
protected void onProgressUpdate(String... values)
{
super.onProgressUpdate(values);
}
}
You cannot return a value. But you can update the UI in onPostExecute(). Remove all super calls in your asynctask.
you should override onPostExecute!! you can access your UI from this function and the inputs of this function is the result of doInBackground!!
I am creating an Android application. In that, I am showing the result by parsing an XML file that is stored in the SD card of the mobile. But it is taking more than one minute to parse the XMl file.
So for this I have implemented the AsyncTask functionality, but still it is taking more than one min.
The same code, if I am running as a Java application for parsing the XML, is taking 3-5 seconds to parse the complete XML and printing the data.
Parsing code
public class ParseMyTripResponseXML {
String aprovedStatus="";
SetFlightRecordsData objFlight;
public MyTripRespone parseMyTripXML(File filename) {
MyTripRespone respObj = new MyTripRespone();
DocumentBuilderFactory dbFactory = DocumentBuilderFactory.newInstance();
DocumentBuilder dBuilder = null;
CorporateBookingApprovals corpApprovalObj = null;
List<CorporateBookingApprovals> corpApprovalList = new ArrayList<CorporateBookingApprovals>();
try {
dBuilder = dbFactory.newDocumentBuilder();
}
catch (ParserConfigurationException e) {
e.printStackTrace();
}
Document doc = null;
try {
doc = dBuilder.parse(filename);
}
catch (SAXException e) {
Log.d("SAXException", e.getMessage()+"");
}
catch (IOException e) {
Log.d("IOException", e.getMessage()+"");
}
doc.getDocumentElement().normalize();
Node rootNode = doc.getElementsByTagName("Root").item(0);
Element rootElement = (Element) rootNode;
String status = getTagValue("StatusCode", rootElement);
if (status.equals("200")) {
NodeList corpList = ((Element) doc.getElementsByTagName("Result").item(0)).getElementsByTagName("CorporateBookingApprovals");
for (int i = 0; i < corpList.getLength(); i++) {
try {
Node corporateDetailsNode = corpList.item(i);
Element corporateDetailsElement = (Element) corporateDetailsNode;
corpApprovalObj = new CorporateBookingApprovals();
corpApprovalObj.setApprovalId(getTagValue("ApprovalId", corporateDetailsElement));
corpApprovalObj.setAgentId(getTagValue("AgentId", corporateDetailsElement));
String statusApproval = getTagValue("ApprovalStatus", corporateDetailsElement);
if(statusApproval.equals("approved")){
aprovedStatus = "A";
}else if (statusApproval.equals("pending")) {
aprovedStatus = "P";
}
else if (statusApproval.equals("inqueue")) {
aprovedStatus = "Q";
}
else if (statusApproval.equals("rejected")) {
aprovedStatus = "R";
}
corpApprovalObj.setApprovalStatus(aprovedStatus);
corpApprovalObj.setInsertTime(getTagValue("InsertTime", corporateDetailsElement));
objFlight = new SetFlightRecordsData();
objFlight.setFlightData(doc, corpApprovalObj);
corpApprovalList.add(corpApprovalObj);
}
catch (Exception e) {
Log.d("exception in main", e.getMessage()+"");
continue;
}
}
respObj.setCoroprateBookingDetails(corpApprovalList);
}
return respObj;
}
public static String getTagValue(String sTag, Element eElement) {
NodeList nlList = eElement.getElementsByTagName(sTag).item(0)
.getChildNodes();
Node nValue = (Node) nlList.item(0);
if (nValue == null) {
return "";
}
else {
return nValue.getNodeValue();
}
}
How do I make it faster?
I am using the DOM parser.
I suggest the general approach to speeding up your XML parse routine by adding timer functions and process of elimination, commenting out sections and rerunning it so you know exactly what is causing your slow down. Usual suspects would be object creation calls and string handling.
long startTime;
long endTime;
startTime = android.os.SystemClock.uptimeMillis();
// parse routine here
endTime = android.os.SystemClock.uptimeMillis();
Log.d("xmlparse", "Excution time: "+(endTime-startTime)+" ms");
this is my first post on stackoverflow and i'm new to Android. I already searched the forum for a similar question and found this one: SAX parser progress monitoring.
But unfortunately it doesn't help me.
My app has to register events in the calendar.
The first thing i achieved was to progress the download of a xml file. You can see this in the attached code.
After that i want the progressDialog to reset and start tracking the progress of the parsing. Would be great if this could be done with a new setMessage() and a percentage value.
After the parsing the data is used to register events in the calendar, again with the same progressDialog.
But at first i want to know how i can track the progress of the parsing. Would be great if have some ideas.
Thank you
public class AddCoursesToCalendar extends Activity {
public static final int progress_bar_type = 0;
ArrayList<String> selectedCourses;
public ProgressDialog progressDialog;
#Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
setContentView(R.layout.activity_add_courses_to_calendar);
if (bundle != null) {
selectedCourses = bundle.getStringArrayList("selectedCourses");
}
new GetDataTask().execute();
}
private Boolean isOnline() {
ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni = cm.getActiveNetworkInfo();
if (ni != null && ni.isConnected())
return true;
return false;
}
#Override
protected Dialog onCreateDialog(int id) {
switch (id) {
case progress_bar_type:
progressDialog = new ProgressDialog(this);
progressDialog.setMessage("Downloading file. Please wait...");
progressDialog.setIndeterminate(false);
progressDialog.setMax(100);
progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
progressDialog.setCancelable(true);
progressDialog.show();
return progressDialog;
default:
return null;
}
}
public class GetDataTask extends AsyncTask<String, String, Integer> {
private static final String URL = "http://10.0.2.2/WIN2.xml";
private static final String KEY_ITEM = "Item";
private static final String KEY_DAUER = "Duration";
private static final String KEY_ENDE = "End";
private static final String KEY_SEMESTER_DOZENT = "Location";
private static final String KEY_RAUMMITSTOCKWERK = "Organizer";
private static final String KEY_START = "Start";
private static final String KEY_VERANSTALTUNGSNAME = "Subject";
#Override
protected void onPreExecute() {
super.onPreExecute();
onCreateDialog(progress_bar_type);
}
#Override
protected Integer doInBackground(String... params) {
if (isOnline()) {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL, this);
long id = 0;
Document doc = parser.getDomElement(xml, this);
NodeList nl = doc.getElementsByTagName(KEY_ITEM);
for (int i = 0; i < nl.getLength(); i++){
Element e = (Element) nl.item(i);
for (String s : selectedCourses) {
if (parser.getValue(e, KEY_VERANSTALTUNGSNAME)
.contains(s)) {
String dozent = null;
int spaceIndex = parser.getValue(e,
KEY_SEMESTER_DOZENT).indexOf(" ");
int lastIndex = parser.getValue(e,
KEY_SEMESTER_DOZENT).length();
if (spaceIndex != -1) {
dozent = parser
.getValue(e, KEY_SEMESTER_DOZENT)
.substring(spaceIndex, lastIndex);
}
addEvent(
parser.getValue(e, KEY_VERANSTALTUNGSNAME),
parser.getValue(e, KEY_START),
parser.getValue(e, KEY_ENDE),
parser.getValue(e, KEY_DAUER),
dozent,
parser.getValue(e, KEY_RAUMMITSTOCKWERK),
id);
} id++;
}
}
} else {
Toast.makeText(AddCoursesToCalendar.this, "No Connection..",
Toast.LENGTH_LONG).show();
}
return 1;
}
public void doProgress(String value){
publishProgress(value);
}
#Override
protected void onPostExecute(Integer result) {
progressDialog.dismiss();
super.onPostExecute(result);
}
protected void onProgressUpdate(String... progress) {
progressDialog.setProgress(Integer.parseInt(progress[0]));
}
protected void addEvent(String title, String start, String end,
String duration, String organizer, String location, long id) {
SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss");
long startInMillis = 0, endInMillis = 0;
Date startDate, endDate;
try {
startDate = format.parse(start);
endDate = format.parse(end);
startInMillis = startDate.getTime();
endInMillis = endDate.getTime();
} catch (ParseException e1) {
e1.printStackTrace();
}
TimeZone timeZone = TimeZone.getDefault();
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
values.put(CalendarContract.Events.EVENT_TIMEZONE, timeZone.getID());
values.put(CalendarContract.Events.DTSTART, startInMillis);
values.put(CalendarContract.Events.DTEND, endInMillis);
values.put(CalendarContract.Events.TITLE, title);
values.put(CalendarContract.Events.EVENT_LOCATION, "Location: " + location);
values.put(CalendarContract.Events.CALENDAR_ID, 1);
Uri uri = cr.insert(CalendarContract.Events.CONTENT_URI, values);
ContentUris.withAppendedId(uri, id);
}
}
}
And here the class responsible for the downloading and parsing:
public class XMLParser {
public String getXmlFromUrl(String url, AddCoursesToCalendar.GetDataTask task) {
String xml = null;
try {
int count;
DefaultHttpClient httpClient = new DefaultHttpClient();
HttpPost httpPost = new HttpPost(url);
HttpResponse httpResponse = httpClient.execute(httpPost);
HttpEntity httpEntity = httpResponse.getEntity();
long lenghtOfFile = httpEntity.getContentLength();
byte data[] = new byte[1024];
long total = 0;
while ((count = httpEntity.getContent().read(data)) != -1) {
total += count;
task.doProgress(""+(int)((total*100)/lenghtOfFile));
}
xml = EntityUtils.toString(httpEntity, "UTF-8");
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (ClientProtocolException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return xml;
}
public Document getDomElement(String xml, AddCoursesToCalendar.GetDataTask task) {
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
try {
DocumentBuilder db = dbf.newDocumentBuilder();
InputSource is = new InputSource();
StringReader reader = new StringReader(xml);
is.setCharacterStream(reader);
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;
}
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 "";
}
}
I hope the style of my first post was ok, if not please tell me. Thank you in advance
I assume that the XML is very large and that the parsing takes at least 30 seconds. Otherwise, do yourself a favor and just show an indeterminate indicator ;)
Also, to simplify your code, you may want to use URL.openStream() instead of a full featured HttpClient, and switch to a simple GET (since you don't send any parameter I wonder why your server requires a POST).
Assumed that the file is a very big one (for a phone, of course), memory usage must be taken into account, and you'll switch from the DOM to the SAX interface to process the XML. SAX provides you with an event-based interface while it scans the stream, so you don't have to load the entire file in memory before even starting to process it. Remember, it's a big file and we don't want to run out of memory.
Using SAX we can parse the file while it's downloading, so we can leave network latencies off when computing total and remaining time. At this point, the progress can be approximated by current item / total. You can update an internal counter to keep track of the current item, but the problem now is how to compute the total. You can think in terms of
Bytes (eg processed 12932/2791290 Bytes)
Business items (eg processed 80/291 Items)
In both cases you need some support from the server. It should provide a Content-Length HTTP header or a preamble (called <manifest> in this snippet):
<root>
<manifest>
<total>291</total>
</manifest>
...
<item id="foobar1">
<foo>Foo</foo>
<bar>Bar</bar>
</item>
...
</root>
The AsyncTask part is quite easy: you can use publishProgress() inside your doInBackground(), and in turn it will invoke onProgressUpdate() on the UI thread. Inside this method, you will update the progress of the dialog.
Just a couple of final notes: when the screen is rotated (default configuration assumed), your activity is destroyed, and then recreated. Note that dialogs shown via Activity.showDialog are automatically recreated by the system, but the old AsyncTask keeps running, and it may keep references to the old (now probably destroyed but not garbage collected) Activity and the old dialog. You have to work on this on your own, there are too many alternatives (including the Loader framework).
I hope you understand now that the task is not as simple as it might sound, so my advice is to carefully examine business requirements and come up with the simplest and more robust solution - after all, downloading an XML and showing a progress dialog is not the main task of your app ;)
I have this code here that worked all this time in 2.3 now we have to update it and I am getting a lot of errors like NetworkOnMainThreadException. I want to go and grab a xml from my web service, bring it down and parse it into an array list. Here is the code
//Gets the xml from the url specified
String CallWebService(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;
}
//Parses the xml to get DOM element
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;
}
//Gets the child nodes of the xml
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 || child.getNodeType() == Node.CDATA_SECTION_NODE){
return child.getNodeValue();
}
}
}
}
return "";
}
I also have a getChildElements method. The problem is when I call this method. I used to do so like this:
String serviceURL = "http://webservice.example.com/";
String xml = CallWebService(serviceURL);
Document doc = GetDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName("details");
getChildElements(nl);
But now in 4.1 I need to do this asynchronously and I don't know how. Any help will be greatly appreciated.
EDIT
Here is what i have bu the Thread does not start
final String serviceURL = "urlString";
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == JOB_COMPLETE) {
String xml = (String) msg.obj;
Document doc = GetDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName("details");
getChildElements(nl);
}
super.handleMessage(msg);
}
};
Thread t = new Thread() {
#Override
public void run() {
String xml = CallWebService(serviceURL);
Message msg = Message.obtain(mHandler, JOB_COMPLETE, xml);
msg.sendToTarget();
}
};
t.start();
EDIT
So I am trying the async way and it still wont work. Its not hitting the GetDomElement at all. Here is the code.
//I call this in my onCreate()
new getAppInfo().execute("http://webservice.example.com");
private class getAppInfo extends AsyncTask<String, Void, String> {
/** The system calls this to perform work in a worker thread and
* delivers it the parameters given to AsyncTask.execute() */
protected String doInBackground(String... urls) {
return CallWebService(urls[0]);
}
/** The system calls this to perform work in the UI thread and delivers
* the result from doInBackground() */
protected void onPostExecute(String xml) {
Document doc = GetDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName("details");
getChildElements(nl);
}
}
You have to implement an AsyncTask:
http://developer.android.com/reference/android/os/AsyncTask.html
Btw this is needed from Android 3 (if I remember well).
I've implemented this in my app, you can browse my code here: https://github.com/enrichman/roma-tre/blob/master/src/com/roma3/infovideo/utility/rss/RssTask.java
Hope this help
http://www.techrepublic.com/blog/app-builder/using-androids-asynctask-to-handle-long-running-io/670?pg=2&tag=content;siu-container
Define a Handler in your main ui thread in activity onCreate for example
private Handler mHandler;
private static int JOB_COMPLETE = 1;
mHandler = new Handler() {
#Override
public void handleMessage(Message msg) {
if(msg.what == JOB_COMPLETE) {
String xml = (String) msg.obj;
// do whatever you want with that string
}
super.handleMessage(msg);
}
};
Then run all your long jobs in background thread
final String url = "...........";
Thread t = new Thread() {
#Override
public void run() {
String xml = CallWebService(url);
Message msg = Message.obtain(mHandler, JOB_COMPLETE, xml);
msg.sendToTarget();
}
};
t.start();
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 android developers page
Do your network related task using Async task or try using safe threads