• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2012 The Android Open Source Project
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 com.example.android.threadsample;
18 
19 import org.xml.sax.helpers.DefaultHandler;
20 import org.xmlpull.v1.XmlPullParser;
21 import org.xmlpull.v1.XmlPullParserException;
22 import org.xmlpull.v1.XmlPullParserFactory;
23 
24 import android.content.ContentValues;
25 import android.net.Uri;
26 
27 import java.io.IOException;
28 import java.io.InputStream;
29 import java.util.Vector;
30 
31 /**
32  * RSSPullParser reads an RSS feed from the Picasa featured pictures site. It uses
33  * several packages from the widely-known XMLPull API.
34  *
35  */
36 public class RSSPullParser extends DefaultHandler {
37     // Global constants
38 
39     // An attribute value indicating that the element contains media content
40     private static final String CONTENT = "media:content";
41 
42     // An attribute value indicating that the element contains a thumbnail
43     private static final String THUMBNAIL = "media:thumbnail";
44 
45     // An attribute value indicating that the element contains an item
46     private static final String ITEM = "item";
47 
48     // Sets the initial size of the vector that stores data.
49     private static final int VECTOR_INITIAL_SIZE = 500;
50 
51     // Storage for a single ContentValues for image data
52     private static ContentValues mImage;
53 
54     // A vector that will contain all of the images
55     private Vector<ContentValues> mImages;
56 
57     /**
58      * A getter that returns the image data Vector
59      * @return A Vector containing all of the image data retrieved by the parser
60      */
getImages()61     public Vector<ContentValues> getImages() {
62         return mImages;
63     }
64     /**
65      * This method parses XML in an input stream and stores parts of the data in memory
66      *
67      * @param inputStream a stream of data containing XML elements, usually a RSS feed
68      * @param progressNotifier a helper class for sending status and logs
69      * @throws XmlPullParserException defined by XMLPullParser; thrown if the thread is cancelled.
70      * @throws IOException thrown if an IO error occurs during parsing
71      */
parseXml(InputStream inputStream, BroadcastNotifier progressNotifier)72     public void parseXml(InputStream inputStream,
73             BroadcastNotifier progressNotifier)
74             throws XmlPullParserException, IOException {
75 
76         // Instantiates a parser factory
77         XmlPullParserFactory localXmlPullParserFactory = XmlPullParserFactory
78                 .newInstance();
79 
80         // Turns off namespace handling for the XML input
81         localXmlPullParserFactory.setNamespaceAware(false);
82 
83         // Instantiates a new pull parser
84         XmlPullParser localXmlPullParser = localXmlPullParserFactory
85                 .newPullParser();
86 
87         // Sets the parser's input stream
88         localXmlPullParser.setInput(inputStream, null);
89 
90         // Gets the first event in the input sream
91         int eventType = localXmlPullParser.getEventType();
92 
93         // Sets the number of images read to 1
94         int imageCount = 1;
95 
96         // Returns if the current event (state) is not START_DOCUMENT
97         if (eventType != XmlPullParser.START_DOCUMENT) {
98 
99             throw new XmlPullParserException("Invalid RSS");
100 
101         }
102 
103         // Creates a new store for image URL data
104         mImages = new Vector<ContentValues>(VECTOR_INITIAL_SIZE);
105 
106         // Loops indefinitely. The exit occurs if there are no more URLs to process
107         while (true) {
108 
109             // Gets the next event in the input stream
110             int nextEvent = localXmlPullParser.next();
111 
112             // If the current thread is interrupted, throws an exception and returns
113             if (Thread.currentThread().isInterrupted()) {
114 
115                 throw new XmlPullParserException("Cancelled");
116 
117             // At the end of the feed, exits the loop
118             } else if (nextEvent == XmlPullParser.END_DOCUMENT) {
119                 break;
120 
121             // At the beginning of the feed, skips the event and continues
122             } else if (nextEvent == XmlPullParser.START_DOCUMENT) {
123                 continue;
124 
125             // At the start of a tag, gets the tag's name
126             } else if (nextEvent == XmlPullParser.START_TAG) {
127                 String eventName = localXmlPullParser.getName();
128 
129                 /*
130                  * If this is the start of an individual item, logs it and creates a new
131                  * ContentValues
132                  */
133                 if (eventName.equalsIgnoreCase(ITEM)) {
134 
135                     mImage = new ContentValues();
136 
137                 // If this isn't an item, then checks for other options
138                 } else {
139 
140                     // Defines keys to store the column names
141                     String imageUrlKey;
142                     String imageNameKey;
143 
144                     // Defines a place to store the filename of a URL,
145                     String fileName;
146 
147                     // If it's CONTENT
148                     if (eventName.equalsIgnoreCase(CONTENT)) {
149 
150                         // Stores the image URL and image name column names as keys
151                         imageUrlKey = DataProviderContract.IMAGE_URL_COLUMN;
152                         imageNameKey = DataProviderContract.IMAGE_PICTURENAME_COLUMN;
153 
154                     // If it's a THUMBNAIL
155                     } else if (eventName.equalsIgnoreCase(THUMBNAIL)) {
156 
157                         // Stores the thumbnail URL and thumbnail name column names as keys
158                         imageUrlKey = DataProviderContract.IMAGE_THUMBURL_COLUMN;
159                         imageNameKey = DataProviderContract.IMAGE_THUMBNAME_COLUMN;
160 
161                     // Otherwise it's some other event that isn't important
162                     } else {
163                         continue;
164                     }
165 
166                     // It's not an ITEM. Gets the URL attribute from the event
167                     String urlValue = localXmlPullParser.getAttributeValue(null, "url");
168 
169                     // If the value is null, exits
170                     if (urlValue == null)
171                         break;
172 
173                     // Puts the URL and the key into the ContentValues
174                     mImage.put(imageUrlKey, urlValue);
175 
176                     // Gets the filename of the URL and puts it into the ContentValues
177                     fileName = Uri.parse(urlValue).getLastPathSegment();
178                     mImage.put(imageNameKey, fileName);
179                 }
180             }
181             /*
182              * If it's not an ITEM, and it is an END_TAG, and the current event is an ITEM, and
183              * there is data in the current ContentValues
184              */
185             else if ((nextEvent == XmlPullParser.END_TAG)
186                     && (localXmlPullParser.getName().equalsIgnoreCase(ITEM))
187                     && (mImage != null)) {
188 
189                 // Adds the current ContentValues to the ContentValues storage
190                 mImages.add(mImage);
191 
192                 // Logs progress
193                 progressNotifier.notifyProgress("Parsed Image[" + imageCount + "]:"
194                         + mImage.getAsString(DataProviderContract.IMAGE_URL_COLUMN));
195 
196                 // Clears out the current ContentValues
197                 mImage = null;
198 
199                 // Increments the count of the number of images stored.
200                 imageCount++;
201             }
202         }
203     }
204 }
205