2012-07-29 110 views
0

我遵循Head First Android Development的指导,我似乎无法得到这个部分的正确。该代码应该从Nasa RSS提要中获得标题和描述的图像,但它不会检索图像。任何帮助将是真棒:)SAX解析器不会从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; 
    } 



} 

我必须诚实地说,我复制大多数代码不检查它,解析器是“准备好烤码”,所以它不是真的是应该在这个被因子评分章:) :)

+0

对于初学者,谁写,你应该抓获被打** **无情地用棍子解析器 - 将“方法“它”使用“来查找URL是唯一的。 if(localName.endsWith(“。jpg”))'不太可能在RSS feed中获得匹配 - 其次,图像URL作为属性包含在内,而不是CDATA。 – Jens 2012-07-29 21:06:18

回答

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

非常感谢你,你的代码绝对清洁得多。很难弄清楚它在分析类中期望什么类型的参数。 “InputStream”,我没有帮助,因为它传递的像一个字符串,已经尝试了流的URL。 我是否必须先将rss保存为.xml文件? :) – Mixy 2012-07-30 16:20:16

+0

这部分来自原始代码的'InputStream inputStream = new URL(url).openStream();'适合传递给'parse'方法。 – Jens 2012-07-30 19:47:03

0

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

+0

是的,当我开始时,这实际上并不存在。忘了再次编辑它。这只是我绝望的尝试之一。感谢tho :) – Mixy 2012-07-29 23:22:36

2

此准备烘烤代码有两个问题

  1. 所述网络连接从所述主UI线程制备。() How to fix android.os.NetworkOnMainThreadException?

  2. 的图像不是在例如从XML检索适当 所以只需为imageUrl添加一个成员变量并通过首先读取机箱然后url来访问它。

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

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

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



}