Back to project page holoreader.
The source code is released under:
GNU General Public License
If you think the Android project holoreader listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.
package de.hdodenhof.holoreader.tasks; //from www .j a v a 2 s . c o m import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import java.net.URLConnection; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.xmlpull.v1.XmlPullParser; import org.xmlpull.v1.XmlPullParserException; import org.xmlpull.v1.XmlPullParserFactory; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.net.Uri; import android.os.AsyncTask; import android.os.Handler; import android.os.Message; import android.util.Patterns; import de.hdodenhof.holoreader.R; import de.hdodenhof.holoreader.provider.RSSContentProvider; import de.hdodenhof.holoreader.provider.SQLiteHelper.FeedDAO; public class AddFeedTask extends AsyncTask<URL, Void, Integer> { @SuppressWarnings("unused") private static final String TAG = AddFeedTask.class.getSimpleName(); public static final int SUCCESS = 0; public static final int ERROR_IOEXCEPTION = 1; public static final int ERROR_XMLPULLPARSEREXCEPTION = 2; public static final int ERROR_NOCONTENT = 3; public static final int ERROR_NOFEED = 4; private Handler mMainUIHandler; private Context mContext; private int mReturnCondition = SUCCESS; public AddFeedTask(Handler mainUIHandler, Context context) { mMainUIHandler = mainUIHandler; mContext = context; } protected Integer doInBackground(URL... params) { URL url = params[0]; String name; try { URLConnection connection = connect(url); HttpURLConnection httpConnection = (HttpURLConnection) connection; int httpResponse = httpConnection.getResponseCode(); if (httpResponse == HttpURLConnection.HTTP_MOVED_PERM) { String redir = connection.getHeaderField("Location"); url = new URL(redir); connection = connect(url); } String contentType = connection.getContentType(); if (contentType != null && contentType.contains("xml")) { InputStream inputStream = connection.getInputStream(); name = validateFeedAndExtractName(inputStream); inputStream.close(); if (mReturnCondition == SUCCESS && name != null) { return storeFeed(url.toString(), name); } } else { String alternateUrl = discoverFeed(url); if (alternateUrl == null) { mReturnCondition = ERROR_NOFEED; } else { URLConnection secondConnection = new URL(alternateUrl).openConnection(); secondConnection.setRequestProperty("User-agent", mContext.getResources().getString(R.string.AppName) + "/" + mContext.getResources().getString(R.string.AppVersionName)); secondConnection.setConnectTimeout(2000); secondConnection.setReadTimeout(2000); secondConnection.connect(); InputStream inputStream = secondConnection.getInputStream(); name = validateFeedAndExtractName(inputStream); inputStream.close(); if (mReturnCondition == SUCCESS && name != null) { return storeFeed(alternateUrl.toString(), name); } } } } catch (IOException e) { mReturnCondition = ERROR_IOEXCEPTION; } return null; } @Override protected void onPreExecute() { super.onPreExecute(); } @Override protected void onPostExecute(Integer result) { Message msg = Message.obtain(); if (mReturnCondition == SUCCESS) { msg.what = 1; msg.arg1 = result; } else { msg.what = 8; msg.arg1 = mReturnCondition; } mMainUIHandler.sendMessage(msg); } private URLConnection connect(URL url) throws IOException { URLConnection connection = url.openConnection(); connection.setRequestProperty("User-agent", mContext.getResources().getString(R.string.AppName) + "/" + mContext.getResources().getString(R.string.AppVersionName)); connection.connect(); return connection; } private int storeFeed(String url, String name) { ContentResolver contentResolver = mContext.getContentResolver(); ContentValues contentValues = new ContentValues(); contentValues.put(FeedDAO.NAME, name); contentValues.put(FeedDAO.URL, url.toString()); Uri newFeed = contentResolver.insert(RSSContentProvider.URI_FEEDS, contentValues); return Integer.parseInt(newFeed.getLastPathSegment()); } private String validateFeedAndExtractName(InputStream inputStream) { String name = null; boolean isFeed = false; boolean isArticle = false; boolean hasContent = false; boolean hasSummary = false; boolean foundName = false; try { XmlPullParserFactory parserFactory = XmlPullParserFactory.newInstance(); parserFactory.setNamespaceAware(true); XmlPullParser pullParser = parserFactory.newPullParser(); pullParser.setInput(inputStream, null); int eventType = pullParser.getEventType(); while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { String currentTag = pullParser.getName(); String currentPrefix = pullParser.getPrefix(); if (currentPrefix == null) { currentPrefix = ""; } if (currentTag.equalsIgnoreCase("rss") || currentTag.equalsIgnoreCase("feed") || currentTag.equalsIgnoreCase("rdf")) { isFeed = true; } else if (currentTag.equalsIgnoreCase("title") && isFeed && foundName == false) { name = pullParser.nextText(); foundName = true; } else if ((currentTag.equalsIgnoreCase("item") || currentTag.equalsIgnoreCase("entry")) && isFeed) { isArticle = true; } else if (((currentTag.equalsIgnoreCase("encoded") && currentPrefix.equalsIgnoreCase("content")) || (currentTag .equalsIgnoreCase("content") && currentPrefix.equalsIgnoreCase(""))) && isArticle == true) { hasContent = true; } else if ((currentTag.equalsIgnoreCase("summary") || currentTag.equalsIgnoreCase("description")) && isArticle == true && currentPrefix.equalsIgnoreCase("")) { hasSummary = true; } } else if (eventType == XmlPullParser.END_TAG) { String currentTag = pullParser.getName(); if ((currentTag.equalsIgnoreCase("item") || currentTag.equalsIgnoreCase("entry")) && isFeed) { break; } } eventType = pullParser.next(); } if (isFeed && (hasContent || hasSummary)) { return name; } else if (isFeed) { mReturnCondition = ERROR_NOCONTENT; } else { mReturnCondition = ERROR_NOFEED; } } catch (XmlPullParserException e) { mReturnCondition = ERROR_XMLPULLPARSEREXCEPTION; } catch (IOException e) { mReturnCondition = ERROR_IOEXCEPTION; } return null; } private String discoverFeed(URL url) { try { Document document = Jsoup.connect(url.toString()) .userAgent(mContext.getResources().getString(R.string.AppName) + "/" + mContext.getResources().getString(R.string.AppVersionName)) .timeout(2000).get(); String rssUrl = document.select("link[rel=alternate][type=application/rss+xml]").attr("href"); if (rssUrl == null || rssUrl == "") { rssUrl = document.select("link[rel=alternate][type=application/atom+xml]").attr("href"); } if (rssUrl == null || rssUrl == "") { return null; } else { if (rssUrl.length() <= 7 || (!rssUrl.substring(0, 7).equalsIgnoreCase("http://") && !rssUrl.substring(0, 8).equalsIgnoreCase("https://"))) { String protocol = url.getProtocol(); String host = url.getHost(); if (rssUrl.substring(0, 1).equalsIgnoreCase("/")) { rssUrl = protocol + "://" + host + rssUrl; } else { rssUrl = protocol + "://" + host + "/" + rssUrl; } } Pattern pattern = Patterns.WEB_URL; Matcher matcher = pattern.matcher(rssUrl); if (matcher.matches()) { return rssUrl; } else { return null; } } } catch (IOException e) { return null; } } }