I'm trying to parse XML from URL and not getting any data, when I debug I see that I'm stuck in the while() loop. The variable i came up to 160 before I gave up. I don't get why I'm stuck in the while loop and not getting into any of the if statements in the loop.
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
public Task()
{
}
#Override
protected Void doInBackground(Void... params) {
makeTask();
return null;
}
public Task(String title){
mTitle = title;
}
private List<Task> makeTask(){
int i = 0;
tasks = new ArrayList<>();
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream stream = url.openStream();
xpp.setInput(stream, null);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_DOCUMENT) {
}
else if (eventType == XmlPullParser.END_DOCUMENT) {
}
else if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("Task")) {
tasks.add(new Task(xpp.nextText()));
Log.d("Task: ", xpp.nextText());
}
else if (eventType == XmlPullParser.END_TAG) {
}
else if (eventType == XmlPullParser.TEXT) {
}
eventType = xpp.next();
}
i++;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return tasks;
}
Edit:
This is the new while() loop and working thanks to #imsiso
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.nextText()));
}
eventType = xpp.next();
}
else
eventType = xpp.next();
The line below in the code List<Task> tasks = task.getTasks(); is giving error:
java.lang.NullPointerException: Attempt to invoke interface method 'int java.util.List.size()' on a null object reference
I'm think that I'm getting that error because I'm not waiting for the AsyncTask to finish and don't know how I should do that.
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
/*Removed irrelevant code here*/
Task task = new Task();
new Task().execute();
List<Task> tasks = task.getTasks();
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
return view;
}
Here's an example TaskLoader and Callback for Loader.
private LoaderManager.LoaderCallbacks<List<TaskModel>> mLoaderCallbacks = new LoaderManager.LoaderCallbacks<List<TaskModel>>()
{
#Override
public Loader<List<TaskModel>> onCreateLoader(int id, Bundle args)
{
return new TaskLoader(getContext());
}
#Override
public void onLoadFinished(Loader<List<TaskModel>> loader, List<TaskModel> data)
{
mTaskRV.setAdapter(new TaskAdapter(data));
}
#Override
public void onLoaderReset(Loader<List<TaskModel>> loader)
{
//
}
};
And the TaskLoader.
private static class TaskLoader extends AsyncTaskLoader<List<TaskModel>>
{
private static final String TAG = TaskLoader.class.getSimpleName();
private List<TaskModel> mData = null;
public TaskLoader(Context context)
{
super(context);
}
#Override
protected void onStartLoading()
{
super.onStartLoading();
if(mData != null){
deliverResult(mData);
}
if(takeContentChanged() || mData == null){
forceLoad();
}
}
#Override
public void deliverResult(List<TaskModel> data)
{
mData = data;
super.deliverResult(data);
}
#Override
public List<TaskModel> loadInBackground()
{
try{
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
URL url = new URL("http://xxx");
InputStream in = null;
try{
in = url.openStream();
xpp.setInput(in, "UTF-8");
return parseTasks(xpp);
}
finally{
if(in != null){
in.close();
}
}
}
catch(MalformedURLException e){
Log.e(TAG, "loadInBackground", e);
}
catch(XmlPullParserException e){
Log.e(TAG, "loadInBackground", e);
}
catch(IOException e){
Log.e(TAG, "loadInBackground", e);
}
return null;
}
private List<TaskModel> parseTasks(XmlPullParser xpp)
throws XmlPullParserException, IOException
{
ArrayList<TaskModel> tasks = new ArrayList<>();
int eventType = xpp.getEventType();
while(eventType != XmlPullParser.END_DOCUMENT){
if(eventType == XmlPullParser.START_TAG){
if(xpp.getName().equalsIgnoreCase("description")){
tasks.add(new TaskModel(xpp.nextText()));
}
}
eventType = xpp.next();
}
return tasks;
}
}
You should provide a listener to the async task that will be triggered when the doInBackground() completes. For instance:
public interface TaskListener{
public void onTaskDone(List<Task> results);
}
public class Task extends AsyncTask<Void,Void,Void> {
private List<Task> tasks;
private TaskListener mListener;
public Task(TaskListener listener)
{
this.mListener = listener;
}
protected Void doInBackground(Void... params) {
.... xml parsing...
if (mListener != null){
mListener.onTaskDone(tasks);
}
}
}
and when you create the task:
Task task = new Task(this);
letting the class implementing the TaskListener interface.
In this method you provide the task's result to the adapter.
public void onTaskDone(final List<Task> tasks){
runOnUiThread(new Runnable() {
#Override
public void run() {
mAdapter = new TaskAdapter(tasks);
mTaskRV.setAdapter(mAdapter);
}
});
}
First let's use this for while which is more clear. And using get text should be better cause it can avoid jumping over a tag or such in other cases.
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("name")) {
tasks.add(new Task(xpp.getText()));
}
}
eventType = xpp.next();
}
And a out that error in List<Task> tasks = task.getTasks(); This should help https://stackoverflow.com/a/218510/2226796
Also I didn't get this part :
Task task = new Task();
new Task().execute();
Related
I want to make a simple Rss Reader app and it doesn't working. More exactly, it doesn't show nothing, almost nothing. For example, for this feed http://feeds.feedburner.com/telefoane-mobilissimo, I get "https://www.mobilissimo.ro/telefoane/" and "Telefoane mobile: specificații, galerii foto, video, benchmark-uri, teste".
Here is the code:
public List<FeedModel> parseFeed(InputStream inputStream) throws XmlPullParserException,
IOException {
String title = null;
String description = null;
String link=null;
String content=null;
String pubDate=null;
Bitmap bitmap=null;
URL url;
boolean isItem = false;
List<FeedModel> items = new ArrayList<>();
try {
XmlPullParser xmlPullParser = Xml.newPullParser();
xmlPullParser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
xmlPullParser.setInput(inputStream, null);
xmlPullParser.nextTag();
while (xmlPullParser.next() != XmlPullParser.END_DOCUMENT) {
int eventType = xmlPullParser.getEventType();
String name = xmlPullParser.getName();
if(name == null)
continue;
if(eventType == XmlPullParser.END_TAG) {
if(name.equalsIgnoreCase("item")) {
isItem = false;
}
continue;
}
if (eventType == XmlPullParser.START_TAG) {
if(name.equalsIgnoreCase("item")) {
isItem = true;
continue;
}
}
String result = "";
if (xmlPullParser.next() == XmlPullParser.TEXT) {
result = xmlPullParser.getText();
xmlPullParser.nextTag();
}
System.out.println(result);
System.out.println(isItem);
if (name.equalsIgnoreCase("title")) {
title = result;
} else if (name.equalsIgnoreCase("description")) {
description = result.substring(result.indexOf("<img"));
}
else if (name.equalsIgnoreCase("pubDate"))
pubDate=result;
else if (name.equalsIgnoreCase("link"))
link = result;
else if (name.equalsIgnoreCase("content:encoded"))
content=result.substring(result.indexOf("<div"),result.indexOf("]]")-1);
if (description!=null&&description.startsWith("<img"))
{
System.out.println(description.substring(10,74));
url=new URL(description.substring(10,74));
description=description.substring(description.indexOf("/>")+2);
bitmap = BitmapFactory.decodeStream(url.openConnection().getInputStream());
}
if (title != null && description != null && bitmap!=null && link!=null) {
if(isItem) {
FeedModel item = new FeedModel(title, description, pubDate, content, bitmap, feed, link);
items.add(item);
}
title = null;
description = null;
pubDate=null;
link=null;
content=null;
bitmap=null;
isItem = false;
}
}
return items;
} finally {
inputStream.close();
}
}
public class FeedTask extends AsyncTask<Void,Void,Void>{
private String feedTask;
public FeedTask(String feed)
{
this.feedTask=feed;
}
#Override
protected void onPreExecute() {
if (anInt==1)
{
MainActivity.this.anInt=0;
centerError.animate().alpha(0f).setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime)).setListener(new AnimatorListenerAdapter() {
#Override
public void onAnimationEnd(Animator animation) {
centerError.setVisibility(View.GONE);
super.onAnimationStart(animation);
}
});
}
swipeRefreshLayout.setRefreshing(true);
recyclerView.animate().alpha(0f).setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
super.onPreExecute();
}
#Override
protected Void doInBackground(Void... params) {
try {
URL url = new URL(feedTask);
InputStream inputStream = url.openConnection().getInputStream();
feedModelList = parseFeed(inputStream);
}
catch (Exception e){}
return null;
}
#Override
protected void onPostExecute(Void aVoid) {
if (feedModelList!=null) {
recyclerView.setAdapter(new FeedAdapter(feedModelList, MainActivity.this));
recyclerView.animate().alpha(1f).setDuration(getResources().getInteger(android.R.integer.config_mediumAnimTime));
}
else System.out.println("heeey");
swipeRefreshLayout.setRefreshing(false);
super.onPostExecute(aVoid);
}
}
I'm trying to Parse an XML file into a List, however it is only getting the last entry in the XML file. I have a sample below
<?xml version="1.0"?>
<stops>
<stop>
<number>stop_code</number>
<lat>stop_lat</lat>
<lon>stop_lon</lon>
<name>stop_name</name>
</stop>
<stop>
<number>112112</number>
<lat> 51.060931</lat>
<lon>-114.065158</lon>
<name>"CRESCENT HEIGHTS HIGH SCHOOL"</name>
</stop>
<stop>
<number>2110</number>
<lat> 51.082803</lat>
<lon>-114.214888</lon>
<name>"EB CAN OLYMPIC RD#OLYMPIC CE ENTR"</name>
</stop>
.....
<stop>
<number>9988</number>
<lat> 51.047388</lat>
<lon>-114.067770</lon>
<name>"NB 2 ST#6 AV SW"</name>
</stop>
<stop>
<number>9998</number>
<lat> 50.997509</lat>
<lon>-114.013415</lon>
<name>"19 St # 62 Ave SE nb ns"</name>
</stop>
And my pull parser is
ublic class PullParser {
public static final String STOP_NAME = "name";
public static final String STOP_LAT = "lat";
public static final String STOP_LON = "lon";
public static final String NUMBER = "number";
private Stops currentStop = null;
private String currentTag= null;
List<Stops> stops = new ArrayList<Stops>();
public List<Stops> parseXML (Context context) {
try {
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
InputStream stream = context.getResources().openRawResource(R.raw.stops_xml);
xpp.setInput(stream,null);
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
handleStartTag(xpp.getName());
} else if (eventType == XmlPullParser.END_TAG) {
currentTag = null;
} else if (eventType == XmlPullParser.TEXT) {
handleText(xpp.getText());
}
eventType = xpp.next();
}
} catch (Resources.NotFoundException e) {
Log.d(MainActivity.TAG, e.getMessage());
} catch (XmlPullParserException e) {
Log.d(MainActivity.TAG, e.getMessage());
} catch (IOException e) {
Log.d(MainActivity.TAG, e.getMessage());
}
return stops;
}
private void handleText(String text) {
String xmlText = text;
if (currentStop != null && currentTag != null) {
if (currentTag.equals(STOP_NAME)) {
currentStop.setName(xmlText);
}
else if (currentTag.equals(STOP_LAT)) {
currentStop.setLat(xmlText);
}
else if (currentTag.equals(STOP_LON)) {
currentStop.setLon(xmlText);
}
else if (currentTag.equals(NUMBER)) {
currentStop.setNumber(xmlText);
}
}
}
private void handleStartTag(String name) {
if (name.equals("stop")) {
currentStop = new Stops();
stops.add(currentStop);
}
else {
currentTag = name;
}
}
}
When I run this it only returns a stop number of 9998 for all 5882 entries (That is the correct number of entries in the file). Any thing obvious that I'm missing?
MyXmlPullParser objMyXmlPullParser = new MyXmlPullParser(context);
List<Map<String , String>> list = objMyXmlPullParser.readXml("Xml respose put here", "Table");
public class MyXmlPullParser
{
Context _context ;
public MyXmlPullParser(Context _context)
{
this._context = _context ;
}
public List<Map<String , String>> readXml(String XmlString , String ParentTag)
{
Map<String , String > map = new HashMap<String, String>();
List<Map<String , String >> list = new ArrayList<Map<String , String >>();
try
{
String Tag = "" ;
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader (XmlString));
int eventType = xpp.getEventType();
while (true)
{
if(eventType == XmlPullParser.START_TAG)
{
Tag = xpp.getName();
}
else if(eventType == XmlPullParser.END_TAG)
{
Tag = "" ;
if(xpp.getName().equals(ParentTag))
{
list.add(map);
map = new HashMap<String, String>();
}
}
else if(eventType == XmlPullParser.TEXT)
{
String text = xpp.getText();
if(!Tag.equals("") && !Tag.equals(ParentTag))
{
map.put(Tag, text);
}
}
else if(eventType == XmlPullParser.END_DOCUMENT)
{
System.out.println("End document");
break ;
}
eventType = xpp.next();
}
}
catch (XmlPullParserException e)
{
Log.e("xml reader" , "error in parsing xml");
return null ;
}
catch (IOException e)
{
Log.e("xml reader" , "error in IO in xml");
return null ;
}
return list ;
}
Hope it may helps you
I need to update UI from onPostExecute method in may async task. What I am trying is I am parsing an xml and take texts from there.. I need to create textView dynamically from onPostExecute() for each xml node it contain text and add it to my layout..
when I try to do this a got NetworkOnMainThreadException..
me tried handler to solve this issue, but didn't get working properly.
please check my code.
protected void onPostExecute(final InputStream stream) {
// dismiss the dialog after getting all albums
pDialog.dismiss();
try {
XmlPullParser xpp = Xml.newPullParser();
xpp.setInput(stream, null);
xpp.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
xpp.next();
int eventType = xpp.getEventType();
System.out.println("eventType : " + eventType);
String tagname = null;
String type = null;
String link = null;
String content = null;
while (eventType != XmlPullParser.END_DOCUMENT)
{
if(eventType == XmlPullParser.START_DOCUMENT){
// str += "\nXML Parsing Starting...\n";
eventType = xpp.next();
continue;
}
else if(eventType == XmlPullParser.START_TAG)
{
// str += "\nroot tag: "+xpp.getName();
tagname = xpp.getName();
if(xpp.getName().equals("text")){
if(xpp.getAttributeCount()>0){
type = xpp.getAttributeValue(null, "type");
// str += "\nroot attr: "+type;
}
}
else if((xpp.getName().equals("image")) || (xpp.getName().equals("audio")) || (xpp.getName().equals("video")) ){
if(xpp.getAttributeCount()>0){
link = xpp.getAttributeValue(null, "src");
// str += "\nroot attr: "+link;
}
}
}
else if(eventType == XmlPullParser.TEXT)
{
content = xpp.getText();
// str += "\nvalue : "+xpp.getText();
}
else if(eventType == XmlPullParser.END_TAG)
{
// str += "\nending tag: "+xpp.getName();
eventType = xpp.next();
continue;
}
System.out.println("content : " + content);
System.out.println("tagname : " + tagname);
if(content != null ){
if((tagname.equals("text") || tagname.equals("preview")) ){
// UPDATE_TEXT =1;
// TextView text = new TextView(ContentView.this);
text = new TextView(getBaseContext());
text.setText(content);
if(type != null){
if(type.equals("heading1"))
text.setTextAppearance(ContentView.this, R.style.heading1);
else if(type.equals("heading2"))
text.setTextAppearance(ContentView.this, R.style.heading2);
else if(type.equals("heading3"))
text.setTextAppearance(ContentView.this, R.style.heading3);
else if(type.equals("heading4"))
text.setTextAppearance(ContentView.this, R.style.heading4);
type = null;
}
if (text != null && layout != null){
Log.e(getPackageName(), text.toString());
runOnUiThread(new Runnable() {
public void run() {
Message message = handler.obtainMessage();
message.what = 1;
handler.sendMessage(message);
// handler.sendEmptyMessage(1);
// layout.addView(text);
}
});
}
content = null;
}
else if((tagname.equals("image"))){
text = new TextView(ContentView.this);
text.setText(content);
if(link != null){
link = null;
}
runOnUiThread(new Runnable() {
public void run() {
handler.sendEmptyMessage(1);
// layout.addView(text);
}
});
content = null;
}
}
eventType = xpp.next();
}
// str += "\n\nXML parsing Ending......";
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
check my handler class in activity class..
protected Handler handler = new Handler() {
#Override
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
layout.addView(text);
break;
case 2:
layout.addView(text);
break;
}
}
};
still am getting same error.
you need Object Model for data infos and setter and can used this:
private ProgressDialog progressBar;
class MyTask extends AsyncTask<String, Void, String> {
#Override
protected void onPreExecute() {
super.onPreExecute();
progressBar = new ProgressDialog(getApplicationContext());
progressBar.setMessage("please, waiting ...");
progressBar.setCancelable(false);
progressBar.show();
}
#Override
protected String doInBackground(String... params) {
try {
// parsing xml and get data
// get info and set them in my model ...
} catch (Exception e) {
e.printStackTrace();
}
return params[0];
}
#Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
if (null != progressBar && progressBar.isShowing()) {
progressBar.dismiss();
}
// do work in UI and set getter informations and set layout ...
switch(select) {
case 1:
layout.addView(text);
break;
case 2:
layout.addView(text);
break;
}
}
}
You failed to post the entire AsyncTask, forcing everyone to have to guess.
My guess is that you did the HTTP connection in doInBackground(), then passed the resulting InputStream to onPostExecute(). This will not work, as that InputStream is tied to a network socket.
Move your InputStream and XML parsing into doInBackground().
I've an activity where the RSS feeds are loaded from a website and get displayed in a list view. The thing is it takes few seconds to load stuffs into listview. And i want to implement a progressbar to notify the user about the loading of data.
Below is the code of displaying the RSS feeds..
public class RSS extends ListActivity {
List<String> headlines;
List<String> links;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_rss);
// Initializing instance variables
headlines = new ArrayList<String>();
links = new ArrayList<String>();
try {
URL url = new URL("http://feeds.pcworld.com/pcworld/latestnews");
XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
factory.setNamespaceAware(false);
XmlPullParser xpp = factory.newPullParser();
// We will get the XML from an input stream
xpp.setInput(getInputStream(url), "UTF_8");
boolean insideItem = false;
// Returns the type of current event: START_TAG, END_TAG, etc..
int eventType = xpp.getEventType();
while (eventType != XmlPullParser.END_DOCUMENT) {
if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equalsIgnoreCase("item")) {
insideItem = true;
} else if (xpp.getName().equalsIgnoreCase("title")) {
if (insideItem)
headlines.add(xpp.nextText()); //extract the headline
} else if (xpp.getName().equalsIgnoreCase("link")) {
if (insideItem)
links.add(xpp.nextText()); //extract the link of article
}
}else if(eventType==XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){
insideItem=false;
}
eventType = xpp.next(); //move to next element
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (XmlPullParserException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// Binding data
ArrayAdapter<String> adapter = new ArrayAdapter<String>(this,
android.R.layout.simple_list_item_1, headlines);
setListAdapter(adapter);
}
private InputStream getInputStream(URL url) {
// TODO Auto-generated method stub
try {
return url.openConnection().getInputStream();
} catch (IOException e) {
return null;
}
}
#Override
protected void onListItemClick(ListView l, View v, int position, long id) {
// TODO Auto-generated method stub
Uri uri = Uri.parse((String) links.get(position));
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
}
}
So can someone help me out in implementing a simple progressbar when loading the data? :)
You should use an AsyncTask to perform all of you downloading stuff. Then in the AsyncTask's onProgessUpdate method, refresh the adapter to the listview.
class LoadingTask extends AsyncTask<URL, Integer, Integer> {
ProgressDialog mDialog;
BaseAdapter mAdapter
public LoadingTask(Context context, BaseAdapter adapter) {
mDialog = new ProgressDialog(context);
mAdapter = adapter;
// Do your dialog stuff here
}
#Override
public Integer doInBackground(URL... urls) {
int result = 0; // number of loaded entities
while (needsToDownload) {
// Do your downloading here
updateProgress(result / urls.length);
}
return result;
}
#Override
public void onProgressUpdate(Integer... ints) {
mDialog.setProgress(ints[0]);
mAdapter.notifyDatasetChanged()
}
public void onPostExecute(Integer result) {
mDialog.dismiss()
Toast.makeToast(context, "Loaded " + result + " urls...", 1).show();
}
}
You should use Async Task for this.
I am new to android and i am trying to build a RSS reader for Android. I have built all the classes and XML files but its not giving the required output. Its just showing the message
No RSS feed available.
Please can some one suggest what should i do.
Here is the code which i took from the tutorial and tried to manipulate-
public final String RSSFEEDOFCHOICE = "http://blog.01synergy.com/feed/";
public final String tag = "RSSReader";
private RSSFeed feed = null;
/** Called when the activity is first created. */
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.main);
// go get our feed!
feed = getFeed(RSSFEEDOFCHOICE);
// display UI
UpdateDisplay();
}
private RSSFeed getFeed(String urlToRssFeed)
{
try
{
// setup the url
URL url = new URL(urlToRssFeed);
// create the factory
SAXParserFactory factory = SAXParserFactory.newInstance();
// create a parser
SAXParser parser = factory.newSAXParser();
// create the reader (scanner)
XMLReader xmlreader = parser.getXMLReader();
// instantiate our handler
RSSHandler theRssHandler = new RSSHandler();
// assign our handler
xmlreader.setContentHandler(theRssHandler);
// get our data via the url class
InputSource is = new InputSource(url.openStream());
// perform the synchronous parse
xmlreader.parse(is);
// get the results - should be a fully populated RSSFeed instance, or null on error
return theRssHandler.getFeed();
}
catch (Exception ee)
{
// if we have a problem, simply return null
return null;
}
}
public boolean onCreateOptionsMenu(Menu menu)
{
super.onCreateOptionsMenu(menu);
menu.add(0,0,0, "Choose RSS Feed");
menu.add(0,1,0, "Refresh");
Log.i(tag,"onCreateOptionsMenu");
return true;
}
public boolean onOptionsItemSelected(Menu item){
switch (((View) item).getId()) {
case 0:
Log.i(tag,"Set RSS Feed");
return true;
case 1:
Log.i(tag,"Refreshing RSS Feed");
return true;
}
return false;
}
private void UpdateDisplay()
{
TextView feedtitle = (TextView) findViewById(R.id.feedtitle);
TextView feedpubdate = (TextView) findViewById(R.id.feedpubdate);
ListView itemlist = (ListView) findViewById(R.id.itemlist);
if (feed == null)
{
feedtitle.setText("No RSS Feed Available");
return;
}
feedtitle.setText(feed.getTitle());
feedpubdate.setText(feed.getPubDate());
ArrayAdapter<RSSItem> adapter = new ArrayAdapter<RSSItem>(this,android.R.layout.simple_list_item_1,feed.getAllItems());
itemlist.setAdapter(adapter);
itemlist.setOnItemClickListener(this);
itemlist.setSelection(0);
}
public void onItemClick(AdapterView parent, View v, int position, long id)
{
Log.i(tag,"item clicked! [" + feed.getItem(position).getTitle() + "]");
Intent itemintent = new Intent(this,ShowDescription.class);
Bundle b = new Bundle();
b.putString("title", feed.getItem(position).getTitle());
b.putString("description", feed.getItem(position).getDescription());
b.putString("link", feed.getItem(position).getLink());
b.putString("pubdate", feed.getItem(position).getPubDate());
itemintent.putExtra("android.intent.extra.INTENT", b);
startSubActivity(itemintent,0);
}
private void startSubActivity(Intent itemintent, int i) {
// TODO Auto-generated method stub
}
}
This is my first approach to RSS Reader, It's no so dynamic and has boilerplate code but worked well for myself.
Usage:
RssParser parser = new RssParser(feedUrl);
Log.i("LOG", "Description: " + parser.getItem(3).description); //4th item's description
Class:
package com.uncocoder.course.app.feed_reader;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;
import org.xml.sax.helpers.DefaultHandler;
import android.util.Log;
public class RssParser extends DefaultHandler {
private StringBuilder content;
private boolean inChannel;
private boolean inImage;
private boolean inItem;
private ArrayList<Item> items = new ArrayList<Item>();
private Channel channel = new Channel();
private Item lastItem;
public RssParser(String url) {
try {
SAXParserFactory spf = SAXParserFactory.newInstance();
SAXParser sp = spf.newSAXParser();
XMLReader xr = sp.getXMLReader();
URL sourceUrl = new URL(url);
xr.setContentHandler(this);
xr.parse(new InputSource(sourceUrl.openStream()));
}
catch (ParserConfigurationException e) {
e.printStackTrace();
}
catch (SAXException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
public class Item {
public String title;
public String description;
public String link;
public String category;
public String pubDate;
public String guid;
}
public class Channel {
public String title;
public String description;
public String link;
public String lastBuildDate;
public String generator;
public String imageUrl;
public String imageTitle;
public String imageLink;
public String imageWidth;
public String imageHeight;
public String imageDescription;
public String language;
public String copyright;
public String pubDate;
public String category;
public String ttl;
}
#Override
public void startDocument() throws SAXException {
Log.i("LOG", "StartDocument");
}
#Override
public void endDocument() throws SAXException {
Log.i("LOG", "EndDocument");
}
#Override
public void startElement(String uri, String localName, String qName, Attributes atts) throws SAXException {
if (localName.equalsIgnoreCase("image")) {
inImage = true;
}
if (localName.equalsIgnoreCase("channel")) {
inChannel = true;
}
if (localName.equalsIgnoreCase("item")) {
lastItem = new Item();
items.add(lastItem);
inItem = true;
}
content = new StringBuilder();
}
#Override
public void endElement(String uri, String localName, String qName) throws SAXException {
if (localName.equalsIgnoreCase("image")) {
inImage = false;
}
if (localName.equalsIgnoreCase("channel")) {
inChannel = false;
}
if (localName.equalsIgnoreCase("item")) {
inItem = false;
}
if (localName.equalsIgnoreCase("title")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.title = content.toString();
} else if (inImage) {
channel.imageTitle = content.toString();
} else if (inChannel) {
channel.title = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("description")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.description = content.toString();
} else if (inImage) {
channel.imageDescription = content.toString();
} else if (inChannel) {
channel.description = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("link")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.link = content.toString();
} else if (inImage) {
channel.imageLink = content.toString();
} else if (inChannel) {
channel.link = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("category")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.category = content.toString();
} else if (inChannel) {
channel.category = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("pubDate")) {
if (content == null) {
return;
}
if (inItem) {
lastItem.pubDate = content.toString();
} else if (inChannel) {
channel.pubDate = content.toString();
}
content = null;
}
if (localName.equalsIgnoreCase("guid")) {
if (content == null) {
return;
}
lastItem.guid = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("url")) {
if (content == null) {
return;
}
channel.imageUrl = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("width")) {
if (content == null) {
return;
}
channel.imageWidth = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("height")) {
if (content == null) {
return;
}
channel.imageHeight = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("language")) {
if (content == null) {
return;
}
channel.language = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("copyright")) {
if (content == null) {
return;
}
channel.copyright = content.toString();
content = null;
}
if (localName.equalsIgnoreCase("ttl")) {
if (content == null) {
return;
}
channel.ttl = content.toString();
content = null;
}
}
#Override
public void characters(char[] ch, int start, int length) throws SAXException {
if (content == null) {
return;
}
content.append(ch, start, length);
}
public Item getItem(int index) {
return items.get(index);
}
}
Check following link, It's open source RSS reader for Android, You can download code for reference
http://code.google.com/p/android-rss/
There is a tutorial (including complete source code) on how to build an Android RSS reder here:
part 1 (complete application)
part 2 (application updated to parse image tags from desciption)
part 3 (application update with Android 3.0)
The tutorial uses SAX parser and includes a complete Android project that accesses an RSS feed and then displays the feed in a list view.
There still seems to be a lot of people interested in this - so if you are looking for an Android 3.0+ with fragments/async tasks etc, as well as complete application code, I have updated the posts again, and they can be found here!
You can download and check my project on google-play.
This project is about some turkish sport channels feeds. Lots of channels are in one application.
You can check source code of project on github.
Parse this type of Rss Feeds easily using XmlPullParser
public class RSSParser {
public static ArrayList<Pojo> getParserData(String Data){
try {
RSSXMLTag currentTag = null;
ArrayList<Pojo> postDataList = new ArrayList<>();
XmlPullParserFactory factory = XmlPullParserFactory
.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp = factory.newPullParser();
xpp.setInput(new StringReader(Data));
int eventType = xpp.getEventType();
Pojo pdData = null;
SimpleDateFormat dateFormat = new SimpleDateFormat(
"EEEE, DD MMM yyyy ");
while (eventType != XmlPullParser.END_DOCUMENT) {
int i = 0;
if (eventType == XmlPullParser.START_DOCUMENT) {
} else if (eventType == XmlPullParser.START_TAG) {
if (xpp.getName().equals("item")) {
pdData = new Pojo();
currentTag = RSSXMLTag.IGNORETAG;
} else if (xpp.getName().equals("title")) {
currentTag = RSSXMLTag.TITLE;
} else if (xpp.getName().equals("link")) {
currentTag = RSSXMLTag.LINK;
} else if (xpp.getName().equals("pubDate")) {
currentTag = RSSXMLTag.DATE;
} else if (xpp.getName().equals("creator")) {
currentTag = RSSXMLTag.CREATOR;
} else if (xpp.getName().equals("category")) {
currentTag = RSSXMLTag.CATEGORY;
} else if (xpp.getName().equals("description")) {
currentTag = RSSXMLTag.DESCRIPTION;
}
} else if (eventType == XmlPullParser.END_TAG) {
if (xpp.getName().equals("item")) {
// format the data here, otherwise format data in
// Adapter
Date postDate = dateFormat.parse(pdData.postDate);
pdData.postDate = dateFormat.format(postDate);
postDataList.add(pdData);
} else {
currentTag = RSSXMLTag.IGNORETAG;
}
} else if (eventType == XmlPullParser.TEXT) {
String content = xpp.getText();
content = content.trim();
Log.d("debug", content);
if (pdData != null) {
switch (currentTag) {
case TITLE:
if (content.length() != 0) {
if (pdData.postTitle != null) {
pdData.postTitle += content;
} else {
pdData.postTitle = content;
}
}
break;
case LINK:
if (content.length() != 0) {
if (pdData.postLink != null) {
pdData.postLink += content;
} else {
pdData.postLink = content;
}
}
break;
case DATE:
if (content.length() != 0) {
if (pdData.postDate != null) {
pdData.postDate += content;
} else {
pdData.postDate = content;
}
}
break;
case CATEGORY:
if (content.length() != 0) {
if (pdData.postCategory != null) {
i = i + 1;
if (i == 1) {
pdData.postCategory = content;
}
} else {
i = i + 1;
if (i == 1) {
pdData.postCategory = content;
}
}
}
break;
case DESCRIPTION:
if (content.length() != 0) {
if (pdData.postDescription != null) {
String s = content;
String string = s.substring(s.indexOf("src=\"") + 5, s.indexOf("\" class=\""));
pdData.postDescription += string;
} else {
String s = content;
String string = s.substring(s.indexOf("src=\"") + 5, s.indexOf("\" class=\""));
pdData.postDescription = string;
}
}
break;
case CREATOR:
if (content.length() != 0) {
if (pdData.postCreator != null) {
pdData.postCreator += content;
} else {
pdData.postCreator = content;
}
}
break;
default:
break;
}
}
}
eventType = xpp.next();
}
return postDataList;
}catch (Exception e){
e.printStackTrace();
}
return null;
}
public enum RSSXMLTag {
IGNORETAG, TITLE, LINK, DATE,CREATOR,CATEGORY, DESCRIPTION;
}
public class Pojo {
public String getPostTitle() {
return postTitle;
}
public void setPostTitle(String postTitle) {
this.postTitle = postTitle;
}
public String getPostLink() {
return postLink;
}
public void setPostLink(String postLink) {
this.postLink = postLink;
}
public String getPostDate() {
return postDate;
}
public void setPostDate(String postDate) {
this.postDate = postDate;
}
public String getPostCategory() {
return postCategory;
}
public void setPostCategory(String postCategory) {
this.postCategory = postCategory;
}
public String getPostDescription() {
return postDescription;
}
public void setPostDescription(String postDescription) {
this.postDescription = postDescription;
}
public String getPostCreator() {
return postCreator;
}
public void setPostCreator(String postCreator) {
this.postCreator = postCreator;
}
public String postTitle;
public String postLink;
public String postDate;
public String postCategory;
public String postDescription;
public String postCreator;
}
}