我正在关注本教程(http://techiedreams.com/android-rss-reader-part-two-offline-reading-swipe-through-detail-views/)and尝试实现rss提要阅读器
我使用
时工作正常String RSSFEEDURL = "http://feeds.feedburner.com/androidcentral?format=xml";
而不是使用
String RSSFEEDURL = "http://www.livescience.com/home/feed/health.xml";
这是我的启动活动
package com.healthyhub.nadeesha.rsssave;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.os.AsyncTask;
import android.os.Bundle;
import android.widget.Toast;
import com.healthyhub.nadeesha.rsssave.parser.DOMParser;
import com.healthyhub.nadeesha.rsssave.parser.RSSFeed;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
public class SplashActivity extends Activity {
String RSSFEEDURL = "http://www.livescience.com/home/feed/health.xml";
// String RSSFEEDURL = "http://feeds.feedburner.com/androidcentral?format=xml";
RSSFeed feed;
String fileName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.splash);
fileName = "TDRSSFeed.td";
File feedFile = getBaseContext().getFileStreamPath(fileName);
ConnectivityManager conMgr = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
if (conMgr.getActiveNetworkInfo() == null) {
// No connectivity. Check if feed File exists
if (!feedFile.exists()) {
// No connectivity & Feed file doesn't exist: Show alert to exit
// & check for connectivity
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setMessage(
"Unable to reach server, \nPlease check your connectivity.")
.setTitle("TD RSS Reader")
.setCancelable(false)
.setPositiveButton("Exit",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int id) {
finish();
}
});
AlertDialog alert = builder.create();
alert.show();
} else {
// No connectivty and file exists: Read feed from the File
Toast toast = Toast.makeText(this,
"No connectivity! Reading last update...",
Toast.LENGTH_LONG);
toast.show();
feed = ReadFeed(fileName);
startLisActivity(feed);
}
} else {
// Connected - Start parsing
new AsyncLoadXMLFeed().execute();
}
}
private void startLisActivity(RSSFeed feed) {
Bundle bundle = new Bundle();
bundle.putSerializable("feed", feed);
// launch List activity
Intent intent = new Intent(SplashActivity.this, ListActivity.class);
intent.putExtras(bundle);
startActivity(intent);
// kill this activity
finish();
}
private class AsyncLoadXMLFeed extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... params) {
// Obtain feed
DOMParser myParser = new DOMParser();
feed = myParser.parseXml(RSSFEEDURL);
if (feed != null && feed.getItemCount() > 0)
WriteFeed(feed);
return null;
}
@Override
protected void onPostExecute(Void result) {
super.onPostExecute(result);
startLisActivity(feed);
}
}
// Method to write the feed to the File
private void WriteFeed(RSSFeed data) {
FileOutputStream fOut = null;
ObjectOutputStream osw = null;
try {
fOut = openFileOutput(fileName, MODE_PRIVATE);
osw = new ObjectOutputStream(fOut);
osw.writeObject(data);
osw.flush();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fOut.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
// Method to read the feed from the File
private RSSFeed ReadFeed(String fName) {
FileInputStream fIn = null;
ObjectInputStream isr = null;
RSSFeed _feed = null;
File feedFile = getBaseContext().getFileStreamPath(fileName);
if (!feedFile.exists())
return null;
try {
fIn = openFileInput(fName);
isr = new ObjectInputStream(fIn);
_feed = (RSSFeed) isr.readObject();
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
fIn.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return _feed;
}
}
这是我的DOMParser.java
package com.healthyhub.nadeesha.rsssave.parser;
import java.net.MalformedURLException;
import java.net.URL;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import org.jsoup.Jsoup;
import org.jsoup.select.Elements;
import org.w3c.dom.Document;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;
public class DOMParser {
private RSSFeed _feed = new RSSFeed();
public RSSFeed parseXml(String xml) {
// _feed.clearList();
URL url = null;
try {
url = new URL(xml);
} catch (MalformedURLException e1) {
e1.printStackTrace();
}
try {
// Create required instances
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
DocumentBuilder db = dbf.newDocumentBuilder();
// Parse the xml
Document doc = db.parse(new InputSource(url.openStream()));
doc.getDocumentElement().normalize();
// Get all <item> tags.
NodeList nl = doc.getElementsByTagName("item");
int length = nl.getLength();
for (int i = 0; i < length; i++) {
Node currentNode = nl.item(i);
RSSItem _item = new RSSItem();
NodeList nchild = currentNode.getChildNodes();
int clength = nchild.getLength();
// Get the required elements from each Item
for (int j = 0; j < clength; j = j + 1) {
Node thisNode = nchild.item(j);
String theString = null;
String nodeName = thisNode.getNodeName();
/*newly added*/
/*here it returns NullPointer exception for theString*/
System.out.println( nchild.item(j).getFirstChild().getNodeValue());
/*end*/
theString = nchild.item(j).getFirstChild().getNodeValue();
if (theString != null) {
if ("title".equals(nodeName)) {
// Node name is equals to 'title' so set the Node
// value to the Title in the RSSItem.
_item.setTitle(theString);
} else if ("description".equals(nodeName)) {
_item.setDescription(theString);
// Parse the html description to get the image url
String html = theString;
org.jsoup.nodes.Document docHtml = Jsoup
.parse(html);
Elements imgEle = docHtml.select("img");
_item.setImage(imgEle.attr("src"));
} else if ("pubDate".equals(nodeName)) {
// We replace the plus and zero's in the date with
// empty string
String formatedDate = theString.replace(" +0000",
"");
_item.setDate(formatedDate);
}
}
}
// add item to the list
_feed.addItem(_item);
}
} catch (Exception e) {
e.printStackTrace();
}
// Return the final feed once all the Items are added to the RSSFeed
// Object(_feed).
return _feed;
}
}
以上部分代码给出了空指针异常
for (int j = 0; j < clength; j = j + 1) {
Node thisNode = nchild.item(j);
String theString = null;
String nodeName = thisNode.getNodeName();
/*newly added*/
/*here it returns NullPointer exception for theString*/
System.out.println( nchild.item(j).getFirstChild().getNodeValue());
/*end*/
这是我的DetailFragment.java
package com.healthyhub.nadeesha.rsssave;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.Display;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.view.WindowManager;
import android.webkit.WebSettings;
import android.webkit.WebSettings.LayoutAlgorithm;
import android.webkit.WebSettings.PluginState;
import android.webkit.WebView;
import android.widget.ScrollView;
import android.widget.TextView;
import com.healthyhub.nadeesha.rsssave.parser.RSSFeed;
public class DetailFragment extends Fragment {
private int fPos;
RSSFeed fFeed;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
fFeed = (RSSFeed) getArguments().getSerializable("feed");
fPos = getArguments().getInt("pos");
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
View view = inflater
.inflate(R.layout.detail_fragment, container, false);
// Initializr views
TextView title = (TextView) view.findViewById(R.id.title);
WebView desc = (WebView) view.findViewById(R.id.desc);
// Enable the vertical fading edge (by default it is disabled)
ScrollView sv = (ScrollView) view.findViewById(R.id.sv);
sv.setVerticalFadingEdgeEnabled(true);
// Set webview properties
WebSettings ws = desc.getSettings();
ws.setLayoutAlgorithm(LayoutAlgorithm.SINGLE_COLUMN);
ws.setLightTouchEnabled(false);
ws.setPluginState(PluginState.ON);
ws.setJavaScriptEnabled(true);
// Set the views
title.setText(fFeed.getItem(fPos).getTitle());
desc.loadDataWithBaseURL("http://www.livescience.com/health/", fFeed
.getItem(fPos).getDescription(), "text/html", "UTF-8", null);
return view;
}
}
以上代码的作用是
DOM解析器解析XML数据。 方法返回feed(RSSFeed)对象:
Splash Activity我们现在从DOMParser类调用方法parseXml(String xml)
已经在onPostExecute()方法中获取了feed我们需要启动ListActivity并将它传递给我们 得到了,我们通过捆绑feed对象并将其附加到Intent
来实现