2012-07-29 72 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; 
} 



}