我正在关注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;
}
}
我必须诚实地说,我复制了大部分代码而没有检查它,解析器是“准备好的烘焙代码”,所以它本身并不是本章所应该的:)
答案 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代码有两个问题
网络连接来自主UI线程。() How to fix android.os.NetworkOnMainThreadException?
在示例中未正确地从XML中检索图像 所以只需为imageUrl添加一个成员变量,然后通过先读取enclosure然后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; }
}
答案 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;
}
}