I am having a lot of difficulty adding a Asynctask to my app. I have a ArticleList Activity which pulls xml from the wen then populates a ListView. The Activity uses external classes including a LazyAdapter.java, ImageLoader.java and XMLParser.java. How do i put the part where it fetches the data from the web into an AsyncTask class.
Here is the Main Activity:
package com.jamfactory.articles;
import java.util.ArrayList;
import java.util.HashMap;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import android.app.ActionBar;
import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.os.StrictMode;
import android.util.Log;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
import com.jamfactory.articles.utilities.XMLParser;
public class ArticleList extends Activity {
// All static variables
static final String URL = "http://192.168.12.21/sebastian/broadcast/index.php/blog?format=stream";
// XML node keys
static final String KEY_ARTICLE = "article"; // parent node
static final String KEY_ID = "id";
static final String KEY_TITLE = "title";
static final String KEY_CONTENT = "content";
static final String KEY_THUMB_URL = "thumb_url";
ListView list;
LazyAdapter adapter;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (android.os.Build.VERSION.SDK_INT > 9) {
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
}
setContentView(R.layout.list);
// Set the title
ActionBar ab = getActionBar();
ab.setTitle("Latest Articles");
// ArrayList for XML
ArrayList<HashMap<String, String>> articlesList = new ArrayList<HashMap<String, String>>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ARTICLE);
// looping through all song nodes <song>
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_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_CONTENT, parser.getValue(e, KEY_CONTENT));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
articlesList.add(map);
}
list = (ListView) findViewById(R.id.list);
// Getting adapter by passing xml data ArrayList
adapter = new LazyAdapter(this, articlesList);
list.setAdapter(adapter);
// Click event for single list row
list.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View v, int pos,
long id) {
// Set items to be sent
TextView title = (TextView) v.findViewById(R.id.title);
TextView content = (TextView) v.findViewById(R.id.content);
TextView thumb_url = (TextView) v.findViewById(R.id.thumb_url);
// Start the intent
Intent i = new Intent(ArticleList.this, Article.class);
// Send along intent
i.putExtra("title", title.getText().toString().trim());
i.putExtra("content", content.getText().toString().trim());
i.putExtra("thumb_url", thumb_url.getText().toString());
startActivity(i);
}
});
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.article_list, menu);
return super.onCreateOptionsMenu(menu);
}
// Refresh Page
#Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.action_refresh:
reList();
return true;
default:
return super.onOptionsItemSelected(item);
}
}
public void reList() {
finish();
overridePendingTransition(0, 0);
startActivity(getIntent());
Toast.makeText(this, "Reload Complete", Toast.LENGTH_SHORT).show();
}
}
Here is the XMLParser.java:
package com.jamfactory.articles.utilities;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.util.Log;
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();
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;
}
/**
* 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));
}
}
You can try as follows...
public class ArticleLoaderTask extends AsyncTask<Void, Void, Void> {
// ArrayList for XML
ArrayList<HashMap<String, String>> articlesList = new ArrayList<HashMap<String, String>>();
LazyAdapter adapter;
Context mContext;
public ArticleLoaderTask(Context context) {
mContext.this = context;
}
#Override
protected Void doInBackground(Void... params) {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ARTICLE);
// looping through all song nodes <song>
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_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_CONTENT, parser.getValue(e, KEY_CONTENT));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
articlesList.add(map);
}
return null;
}
#Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
adapter = new LazyAdapter(mContext, articlesList);
list.setAdapter(adapter);
}
}
In MainActivity.java...
new ArticleLoaderTask(MainActivity.this).execute();
Try this
In activity oncreate
new AppDownloader(this).execute("");
Inside class
class AppDownloader extends AsyncTask<String, String, String> {
Context mContext;
ArrayList<HashMap<String, String>> articlesList= new ArrayList<HashMap<String, String>>();
public AppDownloader(Context context) {
mContext = context;
}
#Override
protected void onPreExecute() {
super.onPreExecute();
// show dialog here
}
#Override
protected String doInBackground(String... params) {
// ArrayList for XML
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_ARTICLE);
// looping through all song nodes <song>
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_ID, parser.getValue(e, KEY_ID));
map.put(KEY_TITLE, parser.getValue(e, KEY_TITLE));
map.put(KEY_CONTENT, parser.getValue(e, KEY_CONTENT));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
articlesList.add(map);
}
return null;
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
adapter = new LazyAdapter(mContext, articlesList);
list.setAdapter(adapter);
}
}
Basically, as the examples suggest, you put the things you want to execute in the doInBackground() method, then you can call whatever lifecycle methods you want to do things at different times (before or after the things in your doInBackground method).
So a an simple template would be started using this command:
new MyAsyncTask.execute();
and the class would look like:
class MyAsyncTask extends AsyncTask<String, String, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
// do stuff before
}
#Override
protected String doInBackground(String... params) {
// Do stuff here (off the UI thread)
// In your case, you can just cut and paste all your XML parsing logic here
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
// Things you do after
}
}
Related
Hi everyone i just want to ask, how will i be able to notify my phone
if its gonna rain like when you send a request for the current weather
the request should run on background and if its gonna rain then it will notify.
Can anyone give some hints or any tutorial for me
to able to send a request through a service and notify me
if its gonna rain please share some ideas
cause i really need it and thank you.
i have done a class for requesting the current location and i use openweathermap API for me to get the current weather.
package com.example.autoapp;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.StatusLine;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.DefaultHttpClient;
import org.json.JSONObject;
public class WeatherJSONParser {
public WeatherJSONParser()
{
}
public JSONObject getWeatherFromUrl(String url)
{
String holder= null;
JSONObject jobj=null;
try
{
HttpClient client= new DefaultHttpClient();
HttpGet get= new HttpGet(url);
HttpResponse response= client.execute(get);
StatusLine sLine= response.getStatusLine();
int status= sLine.getStatusCode();
if(status==200)
{
HttpEntity content= response.getEntity();
InputStream iStream= content.getContent();
StringBuilder cBuilder= new StringBuilder();
BufferedReader bReader= new BufferedReader(new InputStreamReader(iStream));
String cLine=null;
while((cLine=bReader.readLine())!= null)
{
cBuilder.append(cLine);
}
iStream.close();
holder= cBuilder.toString();
jobj= new JSONObject(holder);
return jobj;
}
}
catch(Exception e)
{
e.printStackTrace();
}
return null;
}
}
private final String URL = "http://api.worldweatheronline.com/free/v1/weather.ashx?key=***your api key*****&q=00.00,00.00&cc=no&date=2010-04-23&format=xml";
private static final String KEY_SONG = "weather"; // parent node
// public variable
public static final String KEY_TEMPERATURE_MAXIMUM = "tempMaxC";
public static final String KEY_TEMPERATURE_MINIMUM = "tempMinC";
public static final String KEY_WEATHER_DESCRIPTION = "weatherDesc";
public static final String KEY_PRECIPITATION = "precipMM";
public static final String KEY_THUMB_URL = "weatherIconUrl";
private ArrayList<HashMap<String, String>> aList =null;
#Override
protected void onCreate(Bundle savedInstanceState) {
new LongOperation().execute("");
}
private class LongOperation extends AsyncTask<String, Void, String> {
#Override
protected String doInBackground(String... params) {
aList = new ArrayList<HashMap<String, String>>();
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(URL); // getting XML from URL
Document doc = parser.getDomElement(xml);
NodeList nl = doc.getElementsByTagName(KEY_SONG);
// looping through all song nodes <song>
try {
for (int i = 0; i < nl.getLength(); i++) {
// creating new HashMap
map = new HashMap<String, String>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_TEMPERATURE_MAXIMUM, parser.getValue(e, KEY_TEMPERATURE_MAXIMUM));
map.put(KEY_TEMPERATURE_MINIMUM, parser.getValue(e, KEY_TEMPERATURE_MINIMUM));
map.put(KEY_WEATHER_DESCRIPTION, parser.getValue(e, KEY_WEATHER_DESCRIPTION).trim());
map.put(KEY_PRECIPITATION, parser.getValue(e, KEY_PRECIPITATION));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
aList.add(map);
}
} catch (NullPointerException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
adapter = new LazyAdapterForWeather(WeatherReportActivity.this, aList, 0);
return "Executed";
}
#Override
protected void onPostExecute(String result) {
if(mProgressDialog.isShowing()){
mProgressDialog.dismiss();
}
list.setAdapter(adapter);
}
#Override
protected void onPreExecute() {
ShowLoading();
}
#Override
protected void onProgressUpdate(Void... values) {
}
}
See in this way you can get the weather report . For running the same thing in service at regular interval
you need to merge two code
I'm retrieving an XML from the Google Maps Directions API.
The result is something like this:
<DirectionsResponse>
<status>OK</status>
<route>
<summary>I-40 W</summary>
<leg>
<step>
<travel_mode>DRIVING</travel_mode>
<start_location>
<lat>41.8507300</lat>
<lng>-87.6512600</lng>
</start_location>
<end_location>
<lat>41.8525800</lat>
<lng>-87.6514100</lng>
</end_location>
<polyline>
<points>a~l~Fjk~uOwHJy#P</points>
</polyline>
<duration>
<value>19</value>
<text>1 min</text>
</duration>
<html_instructions>Head <b>north</b> on <b>S Morgan St</b> toward <b>W Cermak Rd</b></html_instructions>
<distance>
<value>207</value>
<text>0.1 mi</text>
</distance>
</step>
...
... additional steps of this leg
...
... additional legs of this route
<duration>
<value>74384</value>
<text>20 hours 40 mins</text>
</duration>
<distance>
<value>2137146</value>
<text>1,328 mi</text>
</distance>
<start_location>
<lat>35.4675602</lat>
<lng>-97.5164276</lng>
</start_location>
<end_location>
<lat>34.0522342</lat>
<lng>-118.2436849</lng>
</end_location>
<start_address>Oklahoma City, OK, USA</start_address>
<end_address>Los Angeles, CA, USA</end_address>
<copyrights>Map data ©2010 Google, Sanborn</copyrights>
<overview_polyline>
<points>a~l~Fjk~uOnzh#vlbBtc~#tsE`vnApw{A`dw#~w\|tNtqf#l{Yd_Fblh#rxo#b}#xxSfytAblk#xxaBeJxlcBb~t#zbh#jc|Bx}C`rv#rw|#rlhA~dVzeo#vrSnc}Axf]fjz#xfFbw~#dz{A~d{A|zOxbrBbdUvpo#`cFp~xBc`Hk#nurDznmFfwMbwz#bbl#lq~#loPpxq#bw_#v|{CbtY~jGqeMb{iF|n\~mbDzeVh_Wr|Efc\x`Ij{kE}mAb~uF{cNd}xBjp]fulBiwJpgg#|kHntyArpb#bijCk_Kv~eGyqTj_|#`uV`k|DcsNdwxAott#r}q#_gc#nu`CnvHx`k#dse#j|p#zpiAp|gEicy#`omFvaErfo#igQxnlApqGze~AsyRzrjAb__#ftyB}pIlo_BflmA~yQftNboWzoAlzp#mz`#|}_#fda#jakEitAn{fB_a]lexClshBtmqAdmY_hLxiZd~XtaBndgC</points>
</overview_polyline>
<optimized_waypoint_index>0</optimized_waypoint_index>
<optimized_waypoint_index>1</optimized_waypoint_index>
<bounds>
<southwest>
<lat>34.0523600</lat>
<lng>-118.2435600</lng>
</southwest>
<northeast>
<lat>41.8781100</lat>
<lng>-87.6297900</lng>
</northeast>
</bounds>
</route>
</DirectionsResponse>
I try to print the value of the tag , but it shows also the <b> or the <div>.
Thus I try to use the class StringEscapeUtils like this:
StringEscapeUtils.escapeHtml4(KEY_HTML_INSTRUCTIONS);
but it doesn't work.
I use this XML Parser:
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.util.Log;
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 "";
}
}
And here is the activity that shows the information taken from the XML:
import maps.XMLParser;
import org.apache.commons.lang3.StringEscapeUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
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 DirectionsActivity extends ListActivity {
String url = "";
XMLParser parser;
String xml = "";
ArrayList<HashMap<String, String>> menuItems;
// All static variables
static final String KEY_STEP = "step"; // parent node
static final String KEY_HTML_INSTRUCTIONS = "html_instructions";
static final String KEY_DURATION = "duration";
static final String KEY_DISTANCE = "distance";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = this.getIntent();
url = intent.getExtras().getString("url");
System.out.println("---------------" + url);
menuItems = new ArrayList<HashMap<String, String>>();
parser = new XMLParser();
DownloadTask downloadTask = new DownloadTask();
// Start downloading json data from Google Directions API
downloadTask.execute(url);
// selecting single ListView item
ListView lv = getListView();
// listening to single listitem click
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.instruction)).getText().toString();
// String cost = ((TextView) view.findViewById(R.id.cost)).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_HTML_INSTRUCTIONS, name);
// in.putExtra(KEY_COST, cost);
// in.putExtra(KEY_DESC, description);
startActivity(in);
}
});
}
/** A class to download data from Google Directions URL */
private class DownloadTask extends AsyncTask<String, Void, String>{
ListAdapter adapter;
private ProgressDialog pd;
#Override
protected void onPreExecute() {
pd = new ProgressDialog(DirectionsActivity.this);
pd.setTitle("Processing...");
pd.setMessage("Calcolo direzione in corso dalla posizione corrente...");
pd.setCancelable(false);
pd.setIndeterminate(true);
pd.show();
}
// Downloading data in non-ui thread
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try{
// Fetching the data from web service
data = parser.getXmlFromUrl(url[0]);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
// Executes in UI thread, after the execution of
// doInBackground()
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Document doc = parser.getDomElement(result); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_STEP);
// 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
String escapeKeyHtmlInstructions = StringEscapeUtils.escapeXml(KEY_HTML_INSTRUCTIONS);
// KEY_HTML_INSTRUCTIONS.replaceAll("\\<.*?>", "");
map.put(KEY_HTML_INSTRUCTIONS, parser.getValue(e, escapeKeyHtmlInstructions));
// map.put(KEY_DURATION, parser.getValue(e, KEY_DURATION));
// map.put(KEY_DISTANCE, "Rs." + parser.getValue(e, KEY_DISTANCE));
// map.put(KEY_DESC, parser.getValue(e, KEY_DESC));
// adding HashList to ArrayList
menuItems.add(map);
}
// Adding menuItems to ListView
adapter = new SimpleAdapter(DirectionsActivity.this, menuItems,R.layout.list_item,
new String[] { KEY_HTML_INSTRUCTIONS}, new int[] {
R.id.instruction});
setListAdapter(adapter);
pd.dismiss();
}
}
}
How can I fix that? Is there other libraries I can use?
I was able to fix that by adding this code in the activity:
instructionValue = parser.getValue(e, KEY_HTML_INSTRUCTIONS);
instructionValueFixed = Html.fromHtml(instructionValue).toString();
map.put(KEY_HTML_INSTRUCTIONS, instructionValueFixed);
you should use XML parser for such type of data. As it is XML not HTML you can use any parser like DOM , SAX or any, that you can get the data properly and save each tag data separately..
I'm developing an Android app in which I created an activity that shows a list of directions taken from Google Directions API.
The url used is something like this: http://maps.googleapis.com/maps/api/directions/xml?origin=Chicago,IL&destination=Los+Angeles,CA&waypoints=Joplin,MO|Oklahoma+City,OK&sensor=false
And the result is something like this:
<DirectionsResponse>
<status>OK</status>
<route>
<summary>I-40 W</summary>
<leg>
<step>
<travel_mode>DRIVING</travel_mode>
<start_location>
<lat>41.8507300</lat>
<lng>-87.6512600</lng>
</start_location>
<end_location>
<lat>41.8525800</lat>
<lng>-87.6514100</lng>
</end_location>
<polyline>
<points>a~l~Fjk~uOwHJy#P</points>
</polyline>
<duration>
<value>19</value>
<text>1 min</text>
</duration>
<html_instructions>Head <b>north</b> on <b>S Morgan St</b> toward <b>W Cermak Rd</b></html_instructions>
<distance>
<value>207</value>
<text>0.1 mi</text>
</distance>
</step>
...
... additional steps of this leg
...
... additional legs of this route
<duration>
<value>74384</value>
<text>20 hours 40 mins</text>
</duration>
<distance>
<value>2137146</value>
<text>1,328 mi</text>
</distance>
<start_location>
<lat>35.4675602</lat>
<lng>-97.5164276</lng>
</start_location>
<end_location>
<lat>34.0522342</lat>
<lng>-118.2436849</lng>
</end_location>
<start_address>Oklahoma City, OK, USA</start_address>
<end_address>Los Angeles, CA, USA</end_address>
<copyrights>Map data ©2010 Google, Sanborn</copyrights>
<overview_polyline>
<points>a~l~Fjk~uOnzh#vlbBtc~#tsE`vnApw{A`dw#~w\|tNtqf#l{Yd_Fblh#rxo#b}#xxSfytAblk#xxaBeJxlcBb~t#zbh#jc|Bx}C`rv#rw|#rlhA~dVzeo#vrSnc}Axf]fjz#xfFbw~#dz{A~d{A|zOxbrBbdUvpo#`cFp~xBc`Hk#nurDznmFfwMbwz#bbl#lq~#loPpxq#bw_#v|{CbtY~jGqeMb{iF|n\~mbDzeVh_Wr|Efc\x`Ij{kE}mAb~uF{cNd}xBjp]fulBiwJpgg#|kHntyArpb#bijCk_Kv~eGyqTj_|#`uV`k|DcsNdwxAott#r}q#_gc#nu`CnvHx`k#dse#j|p#zpiAp|gEicy#`omFvaErfo#igQxnlApqGze~AsyRzrjAb__#ftyB}pIlo_BflmA~yQftNboWzoAlzp#mz`#|}_#fda#jakEitAn{fB_a]lexClshBtmqAdmY_hLxiZd~XtaBndgC</points>
</overview_polyline>
<optimized_waypoint_index>0</optimized_waypoint_index>
<optimized_waypoint_index>1</optimized_waypoint_index>
<bounds>
<southwest>
<lat>34.0523600</lat>
<lng>-118.2435600</lng>
</southwest>
<northeast>
<lat>41.8781100</lat>
<lng>-87.6297900</lng>
</northeast>
</bounds>
</route>
</DirectionsResponse>
In every item of the list I want to show the information contained in <html_instructions>, <text> child of <distance> and <text> child of <duration>.
I was able to obtain the value of <html_instructions> tag, using this parser:
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.util.Log;
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 "";
}
}
How can I modify this parser in order to shows also the values of the other two tags?
I was able to fix that by adding another method in XMLParser class:
public String getSecondValue(Element item, String str) {
NodeList n = item.getElementsByTagName(str);
return this.getElementValue(n.item(1));
}
and here is the usage in the activity:
import java.util.ArrayList;
import java.util.HashMap;
import maps.XMLParser;
import org.apache.commons.lang3.StringEscapeUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
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 DirectionsActivity extends ListActivity {
String url = "";
XMLParser parser;
String xml = "";
ArrayList<HashMap<String, String>> menuItems;
// All static variables
static final String KEY_STEP = "step"; // parent node
static final String KEY_HTML_INSTRUCTIONS = "html_instructions";
static final String KEY_DURATION = "duration";
static final String KEY_DISTANCE = "distance";
static final String KEY_TEXT = "text";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Intent intent = this.getIntent();
url = intent.getExtras().getString("url");
System.out.println("---------------" + url);
menuItems = new ArrayList<HashMap<String, String>>();
parser = new XMLParser();
DownloadTask downloadTask = new DownloadTask();
// Start downloading XML data from Google Directions API
downloadTask.execute(url);
// selecting single ListView item
ListView lv = getListView();
// listening to single listitem click
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
// getting values from selected ListItem
String instruction = ((TextView) view.findViewById(R.id.instruction)).getText().toString();
// Starting new intent
Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
in.putExtra(KEY_HTML_INSTRUCTIONS, instruction);
startActivity(in);
}
});
}
/** A class to download data from Google Directions URL */
private class DownloadTask extends AsyncTask<String, Void, String>{
ListAdapter adapter;
private ProgressDialog pd;
#Override
protected void onPreExecute() {
pd = new ProgressDialog(DirectionsActivity.this);
pd.setTitle("Processing...");
pd.setMessage("Calcolo direzione in corso dalla posizione corrente...");
pd.setCancelable(false);
pd.setIndeterminate(true);
pd.show();
}
// Downloading data in non-ui thread
#Override
protected String doInBackground(String... url) {
// For storing data from web service
String data = "";
try{
// Fetching the data from web service
data = parser.getXmlFromUrl(url[0]);
}catch(Exception e){
Log.d("Background Task",e.toString());
}
return data;
}
// Executes in UI thread, after the execution of
// doInBackground()
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
Document doc = parser.getDomElement(result); // getting DOM element
NodeList nl = doc.getElementsByTagName(KEY_STEP);
// looping through all item nodes <step>
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
String escapedKeyHtmlInstructions = StringEscapeUtils.escapeHtml4(KEY_HTML_INSTRUCTIONS);
// KEY_HTML_INSTRUCTIONS.replaceAll("\\<.*?>", "");
map.put(KEY_HTML_INSTRUCTIONS, parser.getValue(e, escapedKeyHtmlInstructions));
map.put(KEY_DURATION, parser.getValue(e, KEY_TEXT));
map.put(KEY_DISTANCE, parser.getSecondValue(e, KEY_TEXT));
// adding HashList to ArrayList
menuItems.add(map);
}
// Adding menuItems to ListView
adapter = new SimpleAdapter(DirectionsActivity.this, menuItems,R.layout.list_item,
new String[] { KEY_HTML_INSTRUCTIONS, KEY_DURATION, KEY_DISTANCE}, new int[] {
R.id.instruction, R.id.duration, R.id.distance});
setListAdapter(adapter);
pd.dismiss();
}
}
}
I want to retrieve the image link inside the description tag, my tags are all working, here is the sample of description tag:
[http://news.instaforex.com/analytics/rss][1]
I want to retrieve the image link or to show the image. My question is how to that base on my code below?
mainactivity
public class AndroidXMLParsingActivity extends ListActivity {
// All static variables
static final String URL = "http://news.instaforex.com/analytics/rss";
// XML node keys
static final String KEY_ITEM = "item"; // parent node
static final String KEY_TITLE = "title";
static final String KEY_PUBDATE = "pubDate";
static final String KEY_DESCRIPTION = "description";
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ArrayList<HashMap<String, Spanned>> menuItems = new ` ArrayList<HashMap<String, Spanned>>();
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, Spanned> map = new HashMap<String, Spanned>();
Element e = (Element) nl.item(i);
// adding each child node to HashMap key => value
map.put(KEY_TITLE, Html.fromHtml(parser.getValue(e, KEY_TITLE)));
map.put(KEY_PUBDATE, Html.fromHtml(parser.getValue(e, KEY_PUBDATE)));
String description = parser.getValue(e, KEY_DESCRIPTION);;
int index = description.indexOf("The material has been provided by InstaForex Company", 0);
description = description.substring(0, index-1);
map.put(KEY_DESCRIPTION, Html.fromHtml(description));
// 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_PUBDATE }, new int[] {
R.id.name, R.id.cost });
setListAdapter(adapter);
((BaseAdapter) adapter).notifyDataSetChanged();
// selecting single ListView item
ListView lv = getListView();
lv.setOnItemClickListener(new OnItemClickListener() {
#Override
public void onItemClick(AdapterView<?> parent, View view,
int position, long id) {
String title = menuItems.get(position).get(KEY_TITLE).toString();
String pubDate = menuItems.get(position).get(KEY_PUBDATE).toString();
String description= menuItems.get(position).get(KEY_DESCRIPTION).toString();
System.out.println("PubDate==>"+pubDate+"\n Description===>"+description);
// Starting new intent
Intent in = new Intent(getApplicationContext(), SingleMenuItemActivity.class);
in.putExtra(KEY_TITLE, title);
in.putExtra(KEY_PUBDATE, pubDate);
in.putExtra(KEY_DESCRIPTION, description);
startActivity(in);
}
});
}
}
xmlparser
package com.androidhive.xmlparsing;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.text.Html;
import android.util.Log;
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();
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;
}
/**
* Getting XML DOM element
* #param XML string
* */
public Document getDomElement(String xml){
Document doc = null;
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setCoalescing(true);
dbf.setNamespaceAware(true);
if (dbf.isNamespaceAware()==Boolean.TRUE) {
dbf.setNamespaceAware(Boolean.FALSE);
}
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 || child.getNodeType() == Node.CDATA_SECTION_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'm trying to make an app that parses an RSS feed. I run my app but the fetching of data is very slow although the source link ( http://api.androidhive.info/music/music.xml ) is very fast.
I need my app to respond quickly.
My app code :
package com.sta.map;
import java.util.ArrayList;
import java.util.HashMap;
import org.w3c.dom.Document;
import org.w3c.dom.NodeList;
import org.w3c.dom.Element;
import android.app.Activity;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.ListView;
import android.widget.TextView;
public class POSTS extends Activity {
static final String KEY_ARTIST = "artist";
static final String KEY_THUMB_URL = "thumb_url";
ListView list;
WbAdapter adapter;
static String URL = "http://api.androidhive.info/music/music.xml";
ProgressDialog pDialog;
ArrayList<HashMap<String, String>> songsList = new ArrayList<HashMap<String, String>>();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.posts);
new ParseXMLTask().execute();
}
class ParseXMLTask extends AsyncTask<String, String, String> {
protected void onPreExecute() {
// Showing progress dialog before sending http request
pDialog = new ProgressDialog(POSTS.this);
pDialog.setMessage("Please wait..");
pDialog.setIndeterminate(true);
pDialog.setCancelable(false);
pDialog.show();
}
#Override
protected String doInBackground(String... unused) {
XMLParser parser = new XMLParser();
String xml = parser.getXmlFromUrl(url); // getting XML from URL
return xml;
}
#Override
protected void onPostExecute(String result) {
pDialog.dismiss();
XMLParser parser = new XMLParser();
Document doc = parser.getDomElement(result); // getting DOM element
NodeList nl = doc.getElementsByTagName("song");
// looping through all song nodes <song>
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_ARTIST, parser.getValue(e, KEY_ARTIST));
map.put(KEY_THUMB_URL, parser.getValue(e, KEY_THUMB_URL));
// adding HashList to ArrayList
songsList.add(map);
}
list=(ListView)findViewById(R.id.list);
adapter= new WbAdapter(POSTS.this, songsList);
list.setAdapter(adapter);
}
}
}
XMLParser class :
package com.sta.map;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
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.apache.http.util.EntityUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import android.util.Log;
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();
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;
}
/**
* 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));
}
}
EDIT 1: In the manifest I found this code :
<uses-sdk
android:minSdkVersion="8"
android:targetSdkVersion="16" />
I remove this part android:targetSdkVersion="16" and the parsing become very fast
Why ??
I found that on large files the performance of the XMLParser is very poor and very memory hungry. Specifically if one node in xml is very large, like an encoded bitmap. Think about it it has to load the entire string into memory at one time. I switched to parsing the file myself since I was only looking for one specific section and reading the data using a BufferedInputStream to avoid the memory spike.
This may not be your problem, but know that for very large files the XMLParser is not usable.