Search code examples
androideclipsesax

SAX-parser doesn't retrieve image from rss feed


I'm following a guid in Head First Android Development, and I can't seem to get this part right. The code is supposed to get a image with title and description from a Nasa RSS feed, but it does not retrieve the image. Any help would be awesome :)

package com.olshausen.nasadailyimage;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;

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.os.Bundle;
import android.widget.ImageView;
import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.view.Menu;
import android.widget.TextView;



public class DailyImage extends Activity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_daily_image);
        IotdHandler handler = new IotdHandler ();
        handler.processFeed();
        resetDisplay (handler.getTitle(), handler.getDate(), handler.getImage(), handler.getDescription());
    }

    public class IotdHandler extends DefaultHandler {
        private String url = "http://www.nasa.gov/rss/image_of_the_day.rss";
        private boolean inUrl = false;
        private boolean inTitle = false;
        private boolean inDescription = false;
        private boolean inItem = false;
        private boolean inDate = false;
        private Bitmap image = null;
        private String title = null;
        private StringBuffer description = new StringBuffer();
        private String date = null;


        public void processFeed() {
            try {
            SAXParserFactory factory =
            SAXParserFactory.newInstance();
            SAXParser parser = factory.newSAXParser();
            XMLReader reader = parser.getXMLReader();
            reader.setContentHandler(this);
            InputStream inputStream = new URL(url).openStream();
            reader.parse(new InputSource(inputStream));
            } catch (Exception e) {  }
        }

            private Bitmap getBitmap(String url) {
                try {
                HttpURLConnection connection = (HttpURLConnection)new URL(url).openConnection();
                connection.setDoInput(true);
                connection.connect();
                InputStream input = connection.getInputStream();
                Bitmap bilde = BitmapFactory.decodeStream(input);
                input.close();
                return bilde;
                } catch (IOException ioe) { return null; }
                }

            public void startElement(String url, String localName, String qName, Attributes attributes) throws SAXException {
                    if (localName.endsWith(".jpg")) { inUrl = true; }
                    else { inUrl = false; }

                    if (localName.startsWith("item")) { inItem = true; }
                    else if (inItem) {

                        if (localName.equals("title")) { inTitle = true; }
                        else { inTitle = false; }

                        if (localName.equals("description")) { inDescription = true; }
                        else { inDescription = false; }

                        if (localName.equals("pubDate")) { inDate = true; }
                        else { inDate = false; }
                        }
                    }


            public void characters(char ch[], int start, int length) { String chars = new String(ch).substring(start, start + length);
                if (inUrl && url == null) { image = getBitmap(chars); }
                if (inTitle && title == null) { title = chars; }
                if (inDescription) { description.append(chars); }
                if (inDate && date == null) { date = chars; }


         }

        public Bitmap getImage() { return image; }
        public String getTitle() { return title; }
        public StringBuffer getDescription() { return description; }
        public String getDate() { return date; }


}

    private void resetDisplay (String title, String date, Bitmap image, StringBuffer description) {

        TextView titleView = (TextView) findViewById (R.id.image_title);
        titleView.setText(title);

        TextView dateView = (TextView) findViewById(R.id.image_date);
        dateView.setText(date);

        ImageView imageView = (ImageView) findViewById (R.id.image_display);
        imageView.setImageBitmap(image);

        TextView descriptionView = (TextView) findViewById (R.id.image_description);
        descriptionView.setText(description);
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.activity_daily_image, menu);
        return true;
    }



}

I must honestly say that I copied most of this code without checking it, the parser was "ready bake code", so its not really what is supposed to be tought in this chapter :)


Solution

  • Try using a framework instead - even the simplistic built-in framework is better than that horrible kludge you found.

    This example uses the RootElement / Element and associated listeners from the android.sax package.

    class NasaParser {
        private String mTitle;
        private String mDescription;
        private String mDate;
        private String mImageUrl;
    
        public void parse(InputStream is) throws IOException, SAXException {
            RootElement rss = new RootElement("rss");
            Element channel = rss.requireChild("channel");
            Element item = channel.requireChild("item");
            item.setElementListener(new ElementListener() {
                public void end() {
                    onItem(mTitle, mDescription, mDate, mImageUrl);
                }
                public void start(Attributes attributes) {
                    mTitle = mDescription = mDate = mImageUrl = null;
                }
            });
            item.getChild("title").setEndTextElementListener(new EndTextElementListener() {
                public void end(String body) {
                    mTitle = body;
                }
            });
            item.getChild("description").setEndTextElementListener(new EndTextElementListener() {
                public void end(String body) {
                    mDescription = body;
                }
            });
            item.getChild("pubDate").setEndTextElementListener(new EndTextElementListener() {
                public void end(String body) {
                    mDate = body;
                }
            });
            item.getChild("enclosure").setStartElementListener(new StartElementListener() {
                public void start(Attributes attributes) {
                    mImageUrl = attributes.getValue("", "url");
                }
            });
            Xml.parse(is, Encoding.UTF_8, rss.getContentHandler());
        }
    
        public void onItem(String title, String description, String date, String imageUrl) {
            // This is where you handle the item in the RSS channel, etc. etc.  
            // (Left as an exercise for the reader)         
            System.out.println("title=" + title);
            System.out.println("description=" + description);
            System.out.println("date=" + date);
            // This needs to be downloaded for instance
            System.out.println("imageUrl=" + imageUrl);
        }
    }