0

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 :)

4

4 回答 4

2

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);
    }
}
于 2012-07-29T21:24:13.060 回答
2

This Ready bake code has two problems

  1. The Network connection is made from the main UI thread.() How to fix android.os.NetworkOnMainThreadException?

  2. The Image is not retrieved from the XML properly in the example so just add one member variable for the imageUrl and access it by first reading enclosure and then url.

So the final code will be look like..

package com.Achiileus.nasadailyimageamazing;//your package name
import org.xml.sax.helpers.DefaultHandler;
import android.annotation.SuppressLint;
import android.graphics.*;
import android.os.StrictMode;

import javax.xml.parsers.*;
import org.xml.sax.*;

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

@SuppressLint("NewApi")
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 imageUrl=null;
private String title = null;
private StringBuffer description = new StringBuffer();
private String date = null;

public void processFeed() {
try {
//This part is added to allow the network connection on a main GUI thread...    
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy); 
SAXParserFactory factory = SAXParserFactory.newInstance();
SAXParser parser = factory.newSAXParser();
XMLReader reader = parser.getXMLReader();
reader.setContentHandler(this);
URL urlObj = new URL(url);
InputStream inputStream = urlObj.openConnection().getInputStream();
reader.parse(new InputSource(inputStream));
} 
catch (Exception e) 
{
    e.printStackTrace();
    System.out.println(new String("Got Exception General"));
}
}

private Bitmap getBitmap(String url) {
try {
    System.out.println(url);
HttpURLConnection connection =
(HttpURLConnection)new URL(url).openConnection();
connection.setDoInput(true);
connection.connect();
InputStream input = connection.getInputStream();
Bitmap bitmap = BitmapFactory.decodeStream(input);
input.close();
return bitmap;
} 
catch (IOException ioe) 
{
    System.out.println(new String("IOException in reading Image"));
    return null;
}
catch (Exception ioe) 
{
    System.out.println(new String("IOException GENERAL"));
    return null;
}
}

public void startElement(String uri, String localName, String qName,
Attributes attributes) throws SAXException 
{

if (localName.equals("enclosure"))
{
    System.out.println(new String("characters Image"));
    imageUrl = attributes.getValue("","url");
    System.out.println(imageUrl);
    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) {
    System.out.println(new String("characters"));
String chars = new String(ch).substring(start, start + length);
System.out.println(chars);
if (inUrl && image == null) 
{
    System.out.println(new String("IMAGE"));
    System.out.println(imageUrl);
    image = getBitmap(imageUrl);
}
if (inTitle && title == null) {
    System.out.println(new String("TITLE"));
    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; }

}
于 2013-05-17T20:33:22.680 回答
0

Seems like your main issue is in your parse() method. You will never get the image by using this condition: if (localName.endsWith(".jpg")), that will never be true. Instead, you want to make sure you're inside an enclosure tag, and then you want to read the attributes so you get the url one. So first update your clause to be if (localName.endsWith("url")) { ... }. Then to get the actual URL attribute, you can check how to do that from this link.

于 2012-07-29T22:57:47.987 回答
0
    package com.headfirstlabs.ch03.nasa.iotd;

    import java.io.IOException;
    import java.io.InputStream;
    import java.net.URL;
    import java.text.SimpleDateFormat;
    import java.util.Date;

    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.content.Context;
    import android.util.Log;

    public class IotdHandler extends DefaultHandler {
    private static final String TAG = IotdHandler.class.getSimpleName();

    private boolean inTitle = false;
    private boolean inDescription = false;
    private boolean inItem = false;
    private boolean inDate = false;

    private String url = null;
    private StringBuffer title = new StringBuffer();
    private StringBuffer description = new StringBuffer();
    private String date = null;

    public void startElement(String uri, String localName, String qName,
    Attributes attributes) throws SAXException {



    if (localName.equals("enclosure")) {
    url = attributes.getValue("url");
    }

    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 (inTitle) {
    title.append(chars);
    }

    if (inDescription) {
    description.append(chars);
    }

    if (inDate && date == null) {
    //Example: Tue, 21 Dec 2010 00:00:00 EST
    String rawDate = chars;
    try {
    SimpleDateFormat parseFormat = new SimpleDateFormat("EEE, dd MMM yyyy 

    HH:mm:ss");
    Date sourceDate = parseFormat.parse(rawDate);

    SimpleDateFormat outputFormat = new SimpleDateFormat("EEE, dd MMM yyyy");
    date = outputFormat.format(sourceDate);
    } catch (Exception e) {
    e.printStackTrace();
    }
    }

}

public void processFeed(Context context, URL url) {
        try {

            SAXParserFactory spf = SAXParserFactory.newInstance();
            SAXParser sp = spf.newSAXParser();
            XMLReader xr = sp.getXMLReader();
            xr.setContentHandler(this);
            xr.parse(new InputSource(url.openStream()));

        } catch (IOException e) {
            Log.e("", e.toString());
        } catch (SAXException e) {
            Log.e("", e.toString());
        } catch (ParserConfigurationException e) {
            Log.e("", e.toString());
        }
}

public String getUrl() {
return url;
}

public String getTitle() {
return title.toString();
}

public String getDescription() {
return description.toString();
}

public String getDate() {
return date;
}



}
于 2014-02-27T13:03:29.900 回答