| /* |
| * Copyright (C) 2012 The Android Open Source Project |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package com.example.android.threadsample; |
| |
| import org.xml.sax.helpers.DefaultHandler; |
| import org.xmlpull.v1.XmlPullParser; |
| import org.xmlpull.v1.XmlPullParserException; |
| import org.xmlpull.v1.XmlPullParserFactory; |
| |
| import android.content.ContentValues; |
| import android.net.Uri; |
| |
| import java.io.IOException; |
| import java.io.InputStream; |
| import java.util.Vector; |
| |
| /** |
| * RSSPullParser reads an RSS feed from the Picasa featured pictures site. It uses |
| * several packages from the widely-known XMLPull API. |
| * |
| */ |
| public class RSSPullParser extends DefaultHandler { |
| // Global constants |
| |
| // An attribute value indicating that the element contains media content |
| private static final String CONTENT = "media:content"; |
| |
| // An attribute value indicating that the element contains a thumbnail |
| private static final String THUMBNAIL = "media:thumbnail"; |
| |
| // An attribute value indicating that the element contains an item |
| private static final String ITEM = "item"; |
| |
| // Sets the initial size of the vector that stores data. |
| private static final int VECTOR_INITIAL_SIZE = 500; |
| |
| // Storage for a single ContentValues for image data |
| private static ContentValues mImage; |
| |
| // A vector that will contain all of the images |
| private Vector<ContentValues> mImages; |
| |
| /** |
| * A getter that returns the image data Vector |
| * @return A Vector containing all of the image data retrieved by the parser |
| */ |
| public Vector<ContentValues> getImages() { |
| return mImages; |
| } |
| /** |
| * This method parses XML in an input stream and stores parts of the data in memory |
| * |
| * @param inputStream a stream of data containing XML elements, usually a RSS feed |
| * @param progressNotifier a helper class for sending status and logs |
| * @throws XmlPullParserException defined by XMLPullParser; thrown if the thread is cancelled. |
| * @throws IOException thrown if an IO error occurs during parsing |
| */ |
| public void parseXml(InputStream inputStream, |
| BroadcastNotifier progressNotifier) |
| throws XmlPullParserException, IOException { |
| |
| // Instantiates a parser factory |
| XmlPullParserFactory localXmlPullParserFactory = XmlPullParserFactory |
| .newInstance(); |
| |
| // Turns off namespace handling for the XML input |
| localXmlPullParserFactory.setNamespaceAware(false); |
| |
| // Instantiates a new pull parser |
| XmlPullParser localXmlPullParser = localXmlPullParserFactory |
| .newPullParser(); |
| |
| // Sets the parser's input stream |
| localXmlPullParser.setInput(inputStream, null); |
| |
| // Gets the first event in the input sream |
| int eventType = localXmlPullParser.getEventType(); |
| |
| // Sets the number of images read to 1 |
| int imageCount = 1; |
| |
| // Returns if the current event (state) is not START_DOCUMENT |
| if (eventType != XmlPullParser.START_DOCUMENT) { |
| |
| throw new XmlPullParserException("Invalid RSS"); |
| |
| } |
| |
| // Creates a new store for image URL data |
| mImages = new Vector<ContentValues>(VECTOR_INITIAL_SIZE); |
| |
| // Loops indefinitely. The exit occurs if there are no more URLs to process |
| while (true) { |
| |
| // Gets the next event in the input stream |
| int nextEvent = localXmlPullParser.next(); |
| |
| // If the current thread is interrupted, throws an exception and returns |
| if (Thread.currentThread().isInterrupted()) { |
| |
| throw new XmlPullParserException("Cancelled"); |
| |
| // At the end of the feed, exits the loop |
| } else if (nextEvent == XmlPullParser.END_DOCUMENT) { |
| break; |
| |
| // At the beginning of the feed, skips the event and continues |
| } else if (nextEvent == XmlPullParser.START_DOCUMENT) { |
| continue; |
| |
| // At the start of a tag, gets the tag's name |
| } else if (nextEvent == XmlPullParser.START_TAG) { |
| String eventName = localXmlPullParser.getName(); |
| |
| /* |
| * If this is the start of an individual item, logs it and creates a new |
| * ContentValues |
| */ |
| if (eventName.equalsIgnoreCase(ITEM)) { |
| |
| mImage = new ContentValues(); |
| |
| // If this isn't an item, then checks for other options |
| } else { |
| |
| // Defines keys to store the column names |
| String imageUrlKey; |
| String imageNameKey; |
| |
| // Defines a place to store the filename of a URL, |
| String fileName; |
| |
| // If it's CONTENT |
| if (eventName.equalsIgnoreCase(CONTENT)) { |
| |
| // Stores the image URL and image name column names as keys |
| imageUrlKey = DataProviderContract.IMAGE_URL_COLUMN; |
| imageNameKey = DataProviderContract.IMAGE_PICTURENAME_COLUMN; |
| |
| // If it's a THUMBNAIL |
| } else if (eventName.equalsIgnoreCase(THUMBNAIL)) { |
| |
| // Stores the thumbnail URL and thumbnail name column names as keys |
| imageUrlKey = DataProviderContract.IMAGE_THUMBURL_COLUMN; |
| imageNameKey = DataProviderContract.IMAGE_THUMBNAME_COLUMN; |
| |
| // Otherwise it's some other event that isn't important |
| } else { |
| continue; |
| } |
| |
| // It's not an ITEM. Gets the URL attribute from the event |
| String urlValue = localXmlPullParser.getAttributeValue(null, "url"); |
| |
| // If the value is null, exits |
| if (urlValue == null) |
| break; |
| |
| // Puts the URL and the key into the ContentValues |
| mImage.put(imageUrlKey, urlValue); |
| |
| // Gets the filename of the URL and puts it into the ContentValues |
| fileName = Uri.parse(urlValue).getLastPathSegment(); |
| mImage.put(imageNameKey, fileName); |
| } |
| } |
| /* |
| * If it's not an ITEM, and it is an END_TAG, and the current event is an ITEM, and |
| * there is data in the current ContentValues |
| */ |
| else if ((nextEvent == XmlPullParser.END_TAG) |
| && (localXmlPullParser.getName().equalsIgnoreCase(ITEM)) |
| && (mImage != null)) { |
| |
| // Adds the current ContentValues to the ContentValues storage |
| mImages.add(mImage); |
| |
| // Logs progress |
| progressNotifier.notifyProgress("Parsed Image[" + imageCount + "]:" |
| + mImage.getAsString(DataProviderContract.IMAGE_URL_COLUMN)); |
| |
| // Clears out the current ContentValues |
| mImage = null; |
| |
| // Increments the count of the number of images stored. |
| imageCount++; |
| } |
| } |
| } |
| } |