online inoreader greader google feedly best android xml xml-parsing rss sax

inoreader - Android RSS Reader se corta después del primer párrafo



rss reader android (1)

Estoy creando una aplicación para el periódico de mi escuela y me encuentro con un problema cuando intento mostrar el artículo completo. Actualmente tengo una lista de artículos que aparecen extraídos de una fuente RSS, y cuando se hace clic en uno se abre el contenido del artículo. Sin embargo, solo se muestra el primer párrafo en TextView, sin importar cuánto tiempo sea. Esto también me lleva a pensar que tiene algo que ver con las etiquetas HTML <p></p> . No estoy tan familiarizado con los canales RSS o analizando XML (esta es la primera vez que lo intento) y he buscado formas de hacer lo que intento lograr.

De: Android TextView se corta después de un párrafo

Estoy creando esta pregunta en base a los resultados de la pregunta anterior. Pensé que el problema con mi aplicación tenía algo que ver con el TextView y sus propiedades, pero al usar texto sin formato que codifiqué duro funciona bien.

En función de los comentarios y las cosas que probé, el problema parece ser cómo la aplicación está leyendo información de la fuente RSS. Como dije antes, esta es la primera vez que trabajo con feeds RSS en Android, y estoy usando un código de proyectos de muestra (se puede encontrar en las preguntas anteriores). A continuación se muestra el código relevante para la fuente RSS:

RSSFeed .java:

public class RSSFeed { private String title = null; private String description = null; private String link = null; private String pubdate = null; private String content = null; private List<RSSItem> itemList; RSSFeed(){ itemList = new Vector<RSSItem>(0); } void addItem(RSSItem item){ itemList.add(item); } RSSItem getItem(int location){ return itemList.get(location); } List<RSSItem> getList(){ return itemList; } void setTitle(String value){ title = value; } void setDescription(String value){ description = value; } void setLink(String value){ link = value; } void setPubdate(String value){ pubdate = value; } public void setContent(String value) { content=value; } String getTitle(){ return title; } String getDescription(){ return description; } String getLink(){ return link; } String getPubdate(){ return pubdate; } String getContent() { return content; } }

RSSHandler .java:

public class RSSHandler extends DefaultHandler { // Feed and Article objects to use for temporary storage private Article currentArticle = new Article(); private List<Article> articleList = new ArrayList<Article>(); // Number of articles added so far private int articlesAdded = 0; // Number of articles to download private static final int ARTICLES_LIMIT = 15; //Current characters being accumulated StringBuffer chars = new StringBuffer(); /* * This method is called every time a start element is found (an opening XML marker) * here we always reset the characters StringBuffer as we are only currently interested * in the the text values stored at leaf nodes * * (non-Javadoc) * @see org.xml.sax.helpers.DefaultHandler#startElement(java.lang.String, java.lang.String, java.lang.String, org.xml.sax.Attributes) */ public void startElement(String uri, String localName, String qName, Attributes atts) { chars = new StringBuffer(); } /* * This method is called every time an end element is found (a closing XML marker) * here we check what element is being closed, if it is a relevant leaf node that we are * checking, such as Title, then we get the characters we have accumulated in the StringBuffer * and set the current Article''s title to the value * * If this is closing the "Item", it means it is the end of the article, so we add that to the list * and then reset our Article object for the next one on the stream * * * (non-Javadoc) * @see org.xml.sax.helpers.DefaultHandler#endElement(java.lang.String, java.lang.String, java.lang.String) */ public void endElement(String uri, String localName, String qName) throws SAXException { if (localName.equalsIgnoreCase("title")) { Log.d("LOGGING RSS XML", "Setting article title: " + chars.toString()); currentArticle.setTitle(chars.toString()); } else if (localName.equalsIgnoreCase("description")) { Log.d("LOGGING RSS XML", "Setting article description: " + chars.toString()); currentArticle.setDescription(chars.toString()); } else if (localName.equalsIgnoreCase("pubDate")) { Log.d("LOGGING RSS XML", "Setting article published date: " + chars.toString()); currentArticle.setPubDate(chars.toString()); } else if (localName.equalsIgnoreCase("encoded")) { Log.d("LOGGING RSS XML", "Setting article content: " + chars.toString()); currentArticle.setEncodedContent(chars.toString()); } else if (localName.equalsIgnoreCase("item")) { } else if (localName.equalsIgnoreCase("link")) { try { Log.d("LOGGING RSS XML", "Setting article link url: " + chars.toString()); currentArticle.setUrl(new URL(chars.toString())); } catch (MalformedURLException e) { Log.e("RSA Error", e.getMessage()); } } // Check if looking for article, and if article is complete if (localName.equalsIgnoreCase("item")) { articleList.add(currentArticle); currentArticle = new Article(); // Lets check if we''ve hit our limit on number of articles articlesAdded++; if (articlesAdded >= ARTICLES_LIMIT) { throw new SAXException(); } } } /* * This method is called when characters are found in between XML markers, however, there is no * guarantee that this will be called at the end of the node, or that it will be called only once * , so we just accumulate these and then deal with them in endElement() to be sure we have all the * text * * (non-Javadoc) * @see org.xml.sax.helpers.DefaultHandler#characters(char[], int, int) */ public void characters(char ch[], int start, int length) { chars.append(new String(ch, start, length)); } /** * This is the entry point to the parser and creates the feed to be parsed * * @param feedUrl * @return */ public List<Article> getLatestArticles(String feedUrl) { URL url = null; try { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); url = new URL(feedUrl); xr.setContentHandler(this); xr.parse(new InputSource(url.openStream())); } catch (IOException e) { Log.e("RSS Handler IO", e.getMessage() + " >> " + e.toString()); } catch (SAXException e) { Log.e("RSS Handler SAX", e.toString()); } catch (ParserConfigurationException e) { Log.e("RSS Handler Parser Config", e.toString()); } return articleList; }

}

RSSItem .java:

public class RSSItem { private String title = null; private String description = null; private String link = null; private String pubdate = null; private String content = null; RSSItem(){ } void setTitle(String value){ title = value; } void setDescription(String value){ description = value; } void setLink(String value){ link = value; } void setPubdate(String value){ pubdate = value; } public void setContent(String value) { content=value; } String getTitle(){ return title; } String getDescription(){ return description; } String getLink(){ return link; } String getPubdate(){ return pubdate; } public String getContent() { return content; } @Override public String toString() { // TODO Auto-generated method stub return title; }

}

AllStoriesFragment .java:

public class AllStoriesFragment extends ListFragment { /********************************************************************* * RSS Async Task *********************************************************************/ public class RssLoadingTask extends AsyncTask<Void, Void, Void> { @Override protected void onPostExecute(Void result) { // TODO Auto-generated method stub displayRss(); } @Override protected void onPreExecute() { // TODO Auto-generated method stub preReadRss(); } @Override protected void onProgressUpdate(Void... values) { // TODO Auto-generated method stub //super.onProgressUpdate(values); } @Override protected Void doInBackground(Void... arg0) { // TODO Auto-generated method stub readRss(); return null; } } /********************************************************************* * End RSS Async Task *********************************************************************/ private RSSFeed myRssFeed = null; TextView feedTitle; TextView feedDescription; /********************************************************************* * Custom Array Adapter *********************************************************************/ public class MyCustomAdapter extends ArrayAdapter<RSSItem> { public MyCustomAdapter(Context context, int textViewResourceId, List<RSSItem> list) { super(context, textViewResourceId, list); } @Override public View getView(int position, View convertView, ViewGroup parent) { // TODO Auto-generated method stub //return super.getView(position, convertView, parent); View row = convertView; if(row==null){ LayoutInflater inflater=getActivity().getLayoutInflater(); row=inflater.inflate(R.layout.row, parent, false); } //Set Item Title TextView listTitle=(TextView)row.findViewById(R.id.listtitle); listTitle.setText(myRssFeed.getList().get(position).getTitle()); //Set Item PubDate TextView listPubdate=(TextView)row.findViewById(R.id.listpubdate); listPubdate.setText(myRssFeed.getList().get(position).getPubdate()); if (position%2 == 0){ listTitle.setBackgroundColor(0xff101010); listPubdate.setBackgroundColor(0xff101010); } else{ listTitle.setBackgroundColor(0xff080808); listPubdate.setBackgroundColor(0xff080808); } return row; } } /********************************************************************* * End Custom Array Adapter *********************************************************************/ /** Called when the fragment is first created. */ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View v = inflater.inflate(R.layout.fragment_allstories, null); Log.d("MainActivity", "AllStoriesFragment started."); feedTitle = (TextView)v.findViewById(R.id.feedtitle); feedDescription = (TextView)v.findViewById(R.id.feeddescription); startReadRss(); return v ; } private void startReadRss(){ new RssLoadingTask().execute(); } private void preReadRss(){ setListAdapter(null); Toast.makeText(getActivity(), "Reading RSS, Please wait.", Toast.LENGTH_LONG).show(); } private void readRss(){ try { URL rssUrl = new URL("http://www.campusslate.com/feed/"); InputSource myInputSource = new InputSource(rssUrl.openStream()); SAXParserFactory mySAXParserFactory = SAXParserFactory.newInstance(); SAXParser mySAXParser = mySAXParserFactory.newSAXParser(); RSSHandler myRSSHandler = new RSSHandler(); XMLReader myXMLReader = mySAXParser.getXMLReader(); myXMLReader.setContentHandler(myRSSHandler); myXMLReader.parse(myInputSource); myRssFeed = myRSSHandler.getFeed(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ParserConfigurationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } private void displayRss(){ if (myRssFeed!=null){ MyCustomAdapter adapter = new MyCustomAdapter(getActivity(), R.layout.row, myRssFeed.getList()); setListAdapter(adapter); } } public void onListItemClick(ListView l, View v, int position, long id) { // TODO Auto-generated method stub Intent intent = new Intent(getActivity(), ShowDetails.class); intent.putExtra("keyPubdate", myRssFeed.getItem(position).getPubdate()); intent.putExtra("keyLink", myRssFeed.getItem(position).getLink()); intent.putExtra("keyTitle", myRssFeed.getItem(position).getTitle()); intent.putExtra("keyContent", myRssFeed.getItem(position).getContent()); startActivity(intent); } @Override public boolean onOptionsItemSelected(MenuItem item) { // TODO Auto-generated method stub switch(item.getItemId()){ case (0): readRss(); break; default: break; } return true; } }

ShowDetails.java está publicado en la otra pregunta, aunque el código puede ser ligeramente diferente de lo que tengo actualmente. El problema ahora es que cada elemento de la lista es el último elemento leído de la fuente RSS.

Publicaría una imagen si tuviera suficiente reputación.


Un elemento XML puede tener múltiples nodos de texto. Su código asume que solo hay uno. Utilice una operación de adición, no una operación establecida, en la devolución de llamada de sus characters() .