gov.whitehouse.services.FeedService.java Source code

Java tutorial

Introduction

Here is the source code for gov.whitehouse.services.FeedService.java

Source

/*
 * This project constitutes a work of the United States Government and is
 * not subject to domestic copyright protection under 17 USC  105.
 * 
 * However, because the project utilizes code licensed from contributors
 * and other third parties, it therefore is licensed under the MIT
 * License.  http://opensource.org/licenses/mit-license.php.  Under that
 * license, permission is granted free of charge, to any person obtaining
 * a copy of this software and associated documentation files (the
 * "Software"), to deal in the Software without restriction, including
 * without limitation the rights to use, copy, modify, merge, publish,
 * distribute, sublicense, and/or sell copies of the Software, and to
 * permit persons to whom the Software is furnished to do so, subject to
 * the conditions that any appropriate copyright notices and this
 * permission notice are included in all copies or substantial portions
 * of the Software.
 * 
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

package gov.whitehouse.services;

import com.google.gson.JsonSyntaxException;
import com.google.gson.reflect.TypeToken;

import org.xml.sax.SAXException;

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.UnknownHostException;
import java.util.ArrayList;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import gov.whitehouse.R;
import gov.whitehouse.core.FeedHandler;
import gov.whitehouse.core.FeedItem;
import gov.whitehouse.utils.GsonUtils;

public class FeedService extends IntentService {

    public static final String GET_FEED_DATA_INTENT = "whitehouse:get_feed_data_intent";

    public static final String REFRESH_FEED_UI_INTENT = "whitehouse:refresh_feed_ui_intent";

    public static final String EXTRA_CACHED = "whitehouse:feed_data_cached";

    public static final String EXTRA_JSON = "whitehouse:feed_data_json";

    public static final String EXTRA_SERVER_ERROR = "whitehouse:server_error";

    public static final String ARG_FEED_URL = "whitehouse:feed_url";

    public static final String ARG_FEED_TITLE = "whitehouse:feed_title";

    private static final String TAG = "whitehouse:FeedService";

    public FeedService() {
        super("FeedService");
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        Log.d(TAG, ">> FeedService :: onHandleIntent()");
        if (intent.getAction().equals(GET_FEED_DATA_INTENT)) {
            String feedUrl = intent.getStringExtra(ARG_FEED_URL);
            String feedTitle = intent.getStringExtra(ARG_FEED_TITLE);

            if (feedUrl != null) {
                ArrayList<FeedItem> feedItems = new ArrayList<FeedItem>();

                /* Send any cached feed first */
                ArrayList<FeedItem> cachedItems = loadFeedFromCache(this, feedTitle);
                if (cachedItems != null) {
                    final Intent refreshIntent = new Intent(REFRESH_FEED_UI_INTENT);
                    refreshIntent.putExtra(EXTRA_CACHED, true);
                    sendBroadcast(refreshIntent);
                }

                /* ... then update the feed from the server */
                if (updateFeedFromServer(feedItems, feedUrl, feedTitle)) {
                    /*
                    * Send off a refresh broadcast to anything listening. Also
                    * includes the actual refreshed list of live events so
                    * BroadcastReceivers can handle the data straight away.
                    */
                    final Intent refreshIntent = new Intent(REFRESH_FEED_UI_INTENT);
                    refreshIntent.putExtra(EXTRA_CACHED, false);
                    sendBroadcast(refreshIntent);
                } else {
                    final Intent refreshIntent = new Intent(REFRESH_FEED_UI_INTENT);
                    refreshIntent.putExtra(EXTRA_SERVER_ERROR, true);
                    sendBroadcast(refreshIntent);
                }
            }
        }
    }

    public static ArrayList<FeedItem> loadFeedFromCache(final Context context, final String feedTitle) {
        File cacheFile = new File(context.getCacheDir(), "cached_" + feedTitle + "_feed.json");

        try {
            if (cacheFile == null || !cacheFile.exists() || !cacheFile.isFile()) {
                return null;
            } else {
                final ArrayList<FeedItem> feedItems = new ArrayList<FeedItem>();
                final FileInputStream fileIn = new FileInputStream(cacheFile);
                final InputStreamReader isr = new InputStreamReader(fileIn);
                TypeToken<ArrayList<FeedItem>> token = new TypeToken<ArrayList<FeedItem>>() {
                };
                ArrayList<FeedItem> list = GsonUtils.fromJson(isr, token.getType());
                if (list != null) {
                    feedItems.addAll(list);
                }
                return feedItems;
            }
        } catch (IOException e) {
            Log.d(TAG, "error reading feed");
            Log.d(TAG, Log.getStackTraceString(e));
        } catch (IllegalStateException e) {
            Log.d(TAG, "this should not happen");
            Log.d(TAG, Log.getStackTraceString(e));
        } catch (JsonSyntaxException e) {
            Log.d(TAG, "whoops, bad json");
            Log.d(TAG, Log.getStackTraceString(e));
        }

        return null;
    }

    private boolean updateFeedFromServer(final ArrayList<FeedItem> feedItems, final String url,
            final String title) {
        try {
            HttpURLConnection conn = (HttpURLConnection) new URL(url).openConnection();
            InputStream in;
            int status;

            conn.setDoInput(true);
            conn.setInstanceFollowRedirects(true);
            conn.setRequestProperty("User-Agent", getString(R.string.user_agent_string));

            in = conn.getInputStream();
            status = conn.getResponseCode();

            if (status < 400) {
                /* We should be good to go */
                SAXParser parser = SAXParserFactory.newInstance().newSAXParser();
                FeedHandler handler = new FeedHandler();

                parser.parse(in, handler);
                feedItems.addAll(handler.getFeedItems());

                for (FeedItem item : feedItems) {
                    if (item != null) {
                        item.setFeedTitle(title);
                    }
                }

                /* Now write the feed to cache */
                File cacheFile = new File(getCacheDir(), "cached_" + title + "_feed.json");
                if (cacheFile.exists() && cacheFile.isFile()) {
                    cacheFile.delete();
                }
                cacheFile.createNewFile();
                FileOutputStream cacheOutStream = new FileOutputStream(cacheFile);
                OutputStreamWriter streamWriter = new OutputStreamWriter(cacheOutStream);

                streamWriter.write(GsonUtils.toJson(feedItems));
                streamWriter.close();

                conn.disconnect();

                return true;
            }

            conn.disconnect();
        } catch (UnknownHostException e) {
        } catch (SAXException e) {
            Log.d(TAG, "failed to parse XML");
            Log.d(TAG, Log.getStackTraceString(e));
        } catch (IOException e) {
            Log.d(TAG, "error reading feed");
            Log.d(TAG, Log.getStackTraceString(e));
        } catch (IllegalStateException e) {
            Log.d(TAG, "this should not happen");
            Log.d(TAG, Log.getStackTraceString(e));
        } catch (ParserConfigurationException e) {
            Log.d(TAG, "this should not happen");
            Log.d(TAG, Log.getStackTraceString(e));
        }

        return false;
    }
}