SAX-parser不从rss feed中检索图像

时间:2012-07-29 20:54:37

标签: android eclipse sax

我正在关注Head First Android开发中的一个guid,我似乎无法使这一部分正确。代码应该从Nasa RSS提要中获取带有标题和描述的图像,但它不会检索图像。任何帮助都会很棒:)

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;
    }



}

我必须诚实地说,我复制了大部分代码而没有检查它,解析器是“准备好的烘焙代码”,所以它本身并不是本章所应该的:)

4 个答案:

答案 0 :(得分:2)

尝试使用框架 - 即使是简单的内置框架也比你找到的可怕的kludge更好。

此示例使用来自RootElement包的Element / android.sax和关联的侦听器。

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);
    }
}

答案 1 :(得分:2)

这个Ready Bake代码有两个问题

  1. 网络连接来自主UI线程。() How to fix android.os.NetworkOnMainThreadException?

  2. 在示例中未正确地从XML中检索图像 所以只需为imageUrl添加一个成员变量,然后通过先读取enclosure然后url来访问它。

  3. 所以最终的代码看起来像..

    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; }
    
    }
    

答案 2 :(得分:0)

似乎您的主要问题在于parse()方法。你永远不会通过使用这个条件得到图像:if (localName.endsWith(".jpg")),这永远不会是真的。相反,您希望确保自己位于enclosure标记内,然后想要读取属性,以便获得url个属性。因此,首先将您的子句更新为if (localName.endsWith("url")) { ... }。然后,要获取实际的URL属性,您可以从this link检查如何执行此操作。

答案 3 :(得分: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;
}



}