├── .classpath ├── .project ├── AndroidManifest.xml ├── README.markdown ├── proguard.cfg ├── project.properties └── src └── nl └── matshofman └── saxrssreader ├── RssFeed.java ├── RssHandler.java ├── RssItem.java └── RssReader.java /.classpath: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /.project: -------------------------------------------------------------------------------- 1 | 2 | 3 | SAX-RSS-Reader 4 | 5 | 6 | 7 | 8 | 9 | com.android.ide.eclipse.adt.ResourceManagerBuilder 10 | 11 | 12 | 13 | 14 | com.android.ide.eclipse.adt.PreCompilerBuilder 15 | 16 | 17 | 18 | 19 | org.eclipse.jdt.core.javabuilder 20 | 21 | 22 | 23 | 24 | com.android.ide.eclipse.adt.ApkBuilder 25 | 26 | 27 | 28 | 29 | 30 | com.android.ide.eclipse.adt.AndroidNature 31 | org.eclipse.jdt.core.javanature 32 | 33 | 34 | -------------------------------------------------------------------------------- /AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /README.markdown: -------------------------------------------------------------------------------- 1 | With this library you can easily parse RSS feeds using the SAX APIs available in Android. 2 | 3 | Usage 4 | ----- 5 | You can use the API by simply calling `RssReader.read(URL url)`. This will make the request to the url provided and parse it to `RssFeed` and `RssItem` objects. It can't get any easier than this. 6 | 7 | Here is an example of how to fetch a RSS feed and iterate through every item: 8 | 9 | URL url = new URL("http://example.com/feed.rss"); 10 | RssFeed feed = RssReader.read(url); 11 | 12 | ArrayList rssItems = feed.getRssItems(); 13 | for(RssItem rssItem : rssItems) { 14 | Log.i("RSS Reader", rssItem.getTitle()); 15 | } 16 | 17 | License 18 | ----- 19 | Copyright (c) 2011 Mats Hofman 20 | 21 | Licensed under the Apache License, Version 2.0 -------------------------------------------------------------------------------- /proguard.cfg: -------------------------------------------------------------------------------- 1 | -optimizationpasses 5 2 | -dontusemixedcaseclassnames 3 | -dontskipnonpubliclibraryclasses 4 | -dontpreverify 5 | -verbose 6 | -optimizations !code/simplification/arithmetic,!field/*,!class/merging/* 7 | 8 | -keep public class * extends android.app.Activity 9 | -keep public class * extends android.app.Application 10 | -keep public class * extends android.app.Service 11 | -keep public class * extends android.content.BroadcastReceiver 12 | -keep public class * extends android.content.ContentProvider 13 | -keep public class * extends android.app.backup.BackupAgentHelper 14 | -keep public class * extends android.preference.Preference 15 | -keep public class com.android.vending.licensing.ILicensingService 16 | 17 | -keepclasseswithmembernames class * { 18 | native ; 19 | } 20 | 21 | -keepclasseswithmembers class * { 22 | public (android.content.Context, android.util.AttributeSet); 23 | } 24 | 25 | -keepclasseswithmembers class * { 26 | public (android.content.Context, android.util.AttributeSet, int); 27 | } 28 | 29 | -keepclassmembers class * extends android.app.Activity { 30 | public void *(android.view.View); 31 | } 32 | 33 | -keepclassmembers enum * { 34 | public static **[] values(); 35 | public static ** valueOf(java.lang.String); 36 | } 37 | 38 | -keep class * implements android.os.Parcelable { 39 | public static final android.os.Parcelable$Creator *; 40 | } 41 | -------------------------------------------------------------------------------- /project.properties: -------------------------------------------------------------------------------- 1 | # This file is automatically generated by Android Tools. 2 | # Do not modify this file -- YOUR CHANGES WILL BE ERASED! 3 | # 4 | # This file must be checked in Version Control Systems. 5 | # 6 | # To customize properties used by the Ant build system use, 7 | # "ant.properties", and override values to adapt the script to your 8 | # project structure. 9 | 10 | # Project target. 11 | target=android-8 12 | android.library=true 13 | -------------------------------------------------------------------------------- /src/nl/matshofman/saxrssreader/RssFeed.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Mats Hofman 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package nl.matshofman.saxrssreader; 18 | 19 | import java.util.ArrayList; 20 | 21 | import android.os.Bundle; 22 | import android.os.Parcel; 23 | import android.os.Parcelable; 24 | 25 | public class RssFeed implements Parcelable { 26 | 27 | private String title; 28 | private String link; 29 | private String description; 30 | private String language; 31 | private ArrayList rssItems; 32 | 33 | public RssFeed() { 34 | rssItems = new ArrayList(); 35 | } 36 | 37 | public RssFeed(Parcel source) { 38 | 39 | Bundle data = source.readBundle(); 40 | title = data.getString("title"); 41 | link = data.getString("link"); 42 | description = data.getString("description"); 43 | language = data.getString("language"); 44 | rssItems = data.getParcelableArrayList("rssItems"); 45 | 46 | } 47 | 48 | @Override 49 | public void writeToParcel(Parcel dest, int flags) { 50 | 51 | Bundle data = new Bundle(); 52 | data.putString("title", title); 53 | data.putString("link", link); 54 | data.putString("description", description); 55 | data.putString("language", language); 56 | data.putParcelableArrayList("rssItems", rssItems); 57 | dest.writeBundle(data); 58 | } 59 | 60 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 61 | public RssFeed createFromParcel(Parcel data) { 62 | return new RssFeed(data); 63 | } 64 | public RssFeed[] newArray(int size) { 65 | return new RssFeed[size]; 66 | } 67 | }; 68 | 69 | @Override 70 | public int describeContents() { 71 | return 0; 72 | } 73 | 74 | void addRssItem(RssItem rssItem) { 75 | rssItems.add(rssItem); 76 | } 77 | 78 | public String getTitle() { 79 | return title; 80 | } 81 | 82 | public void setTitle(String title) { 83 | this.title = title; 84 | } 85 | 86 | public String getLink() { 87 | return link; 88 | } 89 | 90 | public void setLink(String link) { 91 | this.link = link; 92 | } 93 | 94 | public String getDescription() { 95 | return description; 96 | } 97 | 98 | public void setDescription(String description) { 99 | this.description = description; 100 | } 101 | 102 | public String getLanguage() { 103 | return language; 104 | } 105 | 106 | public void setLanguage(String language) { 107 | this.language = language; 108 | } 109 | 110 | public ArrayList getRssItems() { 111 | return rssItems; 112 | } 113 | 114 | public void setRssItems(ArrayList rssItems) { 115 | this.rssItems = rssItems; 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /src/nl/matshofman/saxrssreader/RssHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Mats Hofman 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package nl.matshofman.saxrssreader; 18 | 19 | import java.lang.reflect.InvocationTargetException; 20 | import java.lang.reflect.Method; 21 | 22 | import org.xml.sax.Attributes; 23 | import org.xml.sax.helpers.DefaultHandler; 24 | 25 | public class RssHandler extends DefaultHandler { 26 | 27 | private RssFeed rssFeed; 28 | private RssItem rssItem; 29 | private StringBuilder stringBuilder; 30 | 31 | @Override 32 | public void startDocument() { 33 | rssFeed = new RssFeed(); 34 | } 35 | 36 | /** 37 | * Return the parsed RssFeed with it's RssItems 38 | * @return 39 | */ 40 | public RssFeed getResult() { 41 | return rssFeed; 42 | } 43 | 44 | @Override 45 | public void startElement(String uri, String localName, String qName, Attributes attributes) { 46 | stringBuilder = new StringBuilder(); 47 | 48 | if(qName.equals("item") && rssFeed != null) { 49 | rssItem = new RssItem(); 50 | rssItem.setFeed(rssFeed); 51 | rssFeed.addRssItem(rssItem); 52 | } 53 | } 54 | 55 | @Override 56 | public void characters(char[] ch, int start, int length) { 57 | stringBuilder.append(ch, start, length); 58 | } 59 | 60 | @Override 61 | public void endElement(String uri, String localName, String qName) { 62 | 63 | if(rssFeed != null && rssItem == null) { 64 | // Parse feed properties 65 | 66 | try { 67 | if (qName != null && qName.length() > 0) { 68 | String methodName = "set" + qName.substring(0, 1).toUpperCase() + qName.substring(1); 69 | Method method = rssFeed.getClass().getMethod(methodName, String.class); 70 | method.invoke(rssFeed, stringBuilder.toString()); 71 | } 72 | } catch (SecurityException e) { 73 | } catch (NoSuchMethodException e) { 74 | } catch (IllegalArgumentException e) { 75 | } catch (IllegalAccessException e) { 76 | } catch (InvocationTargetException e) { 77 | } 78 | 79 | } else if (rssItem != null) { 80 | // Parse item properties 81 | 82 | try { 83 | if(qName.equals("content:encoded")) 84 | qName = "content"; 85 | String methodName = "set" + qName.substring(0, 1).toUpperCase() + qName.substring(1); 86 | Method method = rssItem.getClass().getMethod(methodName, String.class); 87 | method.invoke(rssItem, stringBuilder.toString()); 88 | } catch (SecurityException e) { 89 | } catch (NoSuchMethodException e) { 90 | } catch (IllegalArgumentException e) { 91 | } catch (IllegalAccessException e) { 92 | } catch (InvocationTargetException e) { 93 | } 94 | } 95 | 96 | } 97 | 98 | } 99 | -------------------------------------------------------------------------------- /src/nl/matshofman/saxrssreader/RssItem.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Mats Hofman 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package nl.matshofman.saxrssreader; 18 | 19 | import java.text.ParseException; 20 | import java.text.SimpleDateFormat; 21 | import java.util.Date; 22 | import java.util.Locale; 23 | 24 | import android.os.Bundle; 25 | import android.os.Parcel; 26 | import android.os.Parcelable; 27 | 28 | public class RssItem implements Comparable, Parcelable { 29 | 30 | private RssFeed feed; 31 | private String title; 32 | private String link; 33 | private Date pubDate; 34 | private String description; 35 | private String content; 36 | 37 | public RssItem() { 38 | 39 | } 40 | 41 | public RssItem(Parcel source) { 42 | 43 | Bundle data = source.readBundle(); 44 | title = data.getString("title"); 45 | link = data.getString("link"); 46 | pubDate = (Date) data.getSerializable("pubDate"); 47 | description = data.getString("description"); 48 | content = data.getString("content"); 49 | feed = data.getParcelable("feed"); 50 | 51 | } 52 | 53 | @Override 54 | public void writeToParcel(Parcel dest, int flags) { 55 | 56 | Bundle data = new Bundle(); 57 | data.putString("title", title); 58 | data.putString("link", link); 59 | data.putSerializable("pubDate", pubDate); 60 | data.putString("description", description); 61 | data.putString("content", content); 62 | data.putParcelable("feed", feed); 63 | dest.writeBundle(data); 64 | } 65 | 66 | public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { 67 | public RssItem createFromParcel(Parcel data) { 68 | return new RssItem(data); 69 | } 70 | public RssItem[] newArray(int size) { 71 | return new RssItem[size]; 72 | } 73 | }; 74 | 75 | @Override 76 | public int describeContents() { 77 | return 0; 78 | } 79 | 80 | public RssFeed getFeed() { 81 | return feed; 82 | } 83 | 84 | public void setFeed(RssFeed feed) { 85 | this.feed = feed; 86 | } 87 | 88 | public String getTitle() { 89 | return title; 90 | } 91 | 92 | public void setTitle(String title) { 93 | this.title = title; 94 | } 95 | 96 | public String getLink() { 97 | return link; 98 | } 99 | 100 | public void setLink(String link) { 101 | this.link = link; 102 | } 103 | 104 | public Date getPubDate() { 105 | return pubDate; 106 | } 107 | 108 | public void setPubDate(Date pubDate) { 109 | this.pubDate = pubDate; 110 | } 111 | 112 | public void setPubDate(String pubDate) { 113 | try { 114 | SimpleDateFormat dateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH); 115 | this.pubDate = dateFormat.parse(pubDate); 116 | } catch (ParseException e) { 117 | e.printStackTrace(); 118 | } 119 | } 120 | 121 | public String getDescription() { 122 | return description; 123 | } 124 | 125 | public void setDescription(String description) { 126 | this.description = description; 127 | } 128 | 129 | public String getContent() { 130 | return content; 131 | } 132 | 133 | public void setContent(String content) { 134 | this.content = content; 135 | } 136 | 137 | @Override 138 | public int compareTo(RssItem another) { 139 | if(getPubDate() != null && another.getPubDate() != null) { 140 | return getPubDate().compareTo(another.getPubDate()); 141 | } else { 142 | return 0; 143 | } 144 | } 145 | 146 | } 147 | -------------------------------------------------------------------------------- /src/nl/matshofman/saxrssreader/RssReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2011 Mats Hofman 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package nl.matshofman.saxrssreader; 18 | 19 | import java.io.ByteArrayInputStream; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | import java.net.URL; 23 | 24 | import javax.xml.parsers.ParserConfigurationException; 25 | import javax.xml.parsers.SAXParser; 26 | import javax.xml.parsers.SAXParserFactory; 27 | 28 | import org.xml.sax.InputSource; 29 | import org.xml.sax.SAXException; 30 | import org.xml.sax.XMLReader; 31 | 32 | public class RssReader { 33 | 34 | public static RssFeed read(URL url) throws SAXException, IOException { 35 | 36 | return read(url.openStream()); 37 | 38 | } 39 | 40 | public static RssFeed read(InputStream stream) throws SAXException, IOException { 41 | 42 | try { 43 | 44 | SAXParserFactory factory = SAXParserFactory.newInstance(); 45 | SAXParser parser = factory.newSAXParser(); 46 | XMLReader reader = parser.getXMLReader(); 47 | RssHandler handler = new RssHandler(); 48 | InputSource input = new InputSource(stream); 49 | 50 | reader.setContentHandler(handler); 51 | reader.parse(input); 52 | 53 | return handler.getResult(); 54 | 55 | } catch (ParserConfigurationException e) { 56 | throw new SAXException(); 57 | } 58 | 59 | } 60 | 61 | public static RssFeed read(String source) throws SAXException, IOException { 62 | return read(new ByteArrayInputStream(source.getBytes())); 63 | } 64 | 65 | } 66 | --------------------------------------------------------------------------------