/*
* Copyright 2012 Brendan McCarthy (brendan@oddsoftware.net)
*
* This file is part of Feedscribe.
*
* Feedscribe is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3
* as published by the Free Software Foundation.
*
* Feedscribe is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Feedscribe. If not, see <http://www.gnu.org/licenses/>.
*/
package net.oddsoftware.android.feedscribe.service;
import java.util.Date;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.util.Log;
import net.oddsoftware.android.feedscribe.*;
import net.oddsoftware.android.feedscribe.Globals;
import net.oddsoftware.android.feedscribe.data.Downloader;
import net.oddsoftware.android.feedscribe.data.FeedManager;
import net.oddsoftware.android.feedscribe.data.FeedUpdateListener;
import net.oddsoftware.android.feedscribe.ui.FeedsActivity;
import net.oddsoftware.android.utils.WakefulIntentService;
public class FeedService extends WakefulIntentService implements FeedUpdateListener
{
public static final String STATUS_UPDATE = "net.oddsoftware.android.cricket.CricketService.STATUS_UPDATE";
public static final int CMD_NONE = 0;
public static final int CMD_UPDATE_FEEDS = 1;
public static final int CMD_DOWNLOAD_ADDED = 2;
public static final int CMD_UPDATE_FEED = 3;
public static final int CMD_CLEAR_NOTIFICATIONS = 4;
public static final int STATUS_NONE = 0;
public static final int STATUS_UPDATING = 1;
public static final int STATUS_UPDATE_COMPLETE = 2;
public static final int ERROR_NONE = 0;
public static final int ERROR_NETWORK = 1;
private NotificationManager mNotificationManager = null;
public static final String EXTRA_PROGRESS = "progress";
public static final String EXTRA_FORCE = "force";
public static final String EXTRA_ERROR = "error";
public static final String EXTRA_CMD = "cmd";
public static final String EXTRA_FEED_ID = "feed_id";
private boolean mNotificationsEnabled;
public FeedService()
{
super("FeedService");
// mWakeTimeout = 120 * 1000; // 2 minutes
mWakeTimeout = 0;
mNotificationsEnabled = false;
}
@Override
protected void doWakefulWork(Intent intent)
{
if (Globals.LOGGING) Log.d(Globals.LOG_TAG, "doWakefulWork begins at " + new Date().getTime() );
if( mNotificationManager == null)
{
mNotificationManager = (NotificationManager) getSystemService( Context.NOTIFICATION_SERVICE );
}
int cmd = intent.getIntExtra("cmd", CMD_NONE);
switch( cmd )
{
case CMD_UPDATE_FEEDS:
{
boolean forceUpdate = intent.getBooleanExtra(EXTRA_FORCE, false);
doUpdateFeeds(0, forceUpdate);
break;
}
case CMD_UPDATE_FEED:
{
long feedId = intent.getLongExtra(EXTRA_FEED_ID, 0);
doUpdateFeeds(feedId, true);
break;
}
case CMD_DOWNLOAD_ADDED:
{
Downloader.getInstance(this).processDownloads();
break;
}
case CMD_CLEAR_NOTIFICATIONS:
{
clearNewItemsNotification();
}
}
if (Globals.LOGGING) Log.d(Globals.LOG_TAG, "doWakefulWork ends at " + new Date().getTime() );
}
private void doUpdateFeeds(long feedId, boolean forceUpdate)
{
try
{
FeedManager feedManager = FeedManager.getInstance(this);
mNotificationsEnabled = feedManager.getFeedConfig().getNotificationsEnabled();
feedManager.setFeedUpdateListener(this);
int minIntervalMinutes = 0;
if( !forceUpdate )
{
minIntervalMinutes = 60;
}
boolean updateAttempted = feedManager.updateItems( feedId, forceUpdate, minIntervalMinutes );
if( updateAttempted )
{
checkNetwork();
}
/*
feedManager.deleteOldItems( feedManager.getKeepHours() );
feedManager.deleteOldImages();
*/
feedManager.getFeedConfig().syncComplete();
if( feedManager.getFeedConfig().getNotificationsEnabled() && !forceUpdate)
{
int newItemCount = feedManager.getFeedConfig().getNewItemCount();
if( newItemCount > 0)
{
showNewItemsNotification( newItemCount );
}
}
}
finally
{
broadcastStatus(STATUS_UPDATE_COMPLETE, 100, ERROR_NONE);
}
}
private void checkNetwork()
{
ConnectivityManager connectivityManager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
if( netInfo == null || !netInfo.isConnected() )
{
if (Globals.LOGGING) Log.w(Globals.LOG_TAG, "doUpdateFeeds - no network available");
broadcastStatus(STATUS_UPDATE_COMPLETE, 100, ERROR_NETWORK);
}
}
private void broadcastStatus(int status, int progress, int errorCode)
{
Intent intent = new Intent(STATUS_UPDATE);
intent.putExtra("status", status);
intent.putExtra(EXTRA_PROGRESS, progress);
intent.putExtra(EXTRA_ERROR, errorCode);
sendBroadcast(intent);
if( status == STATUS_UPDATING && mNotificationsEnabled)
{
showSyncingNotification();
}
else if( status == STATUS_UPDATE_COMPLETE )
{
closeSyncingNotification();
}
}
private void showSyncingNotification()
{
String tickerText = getResources().getString(R.string.notification_syncing_ticker);
String titleText = getResources().getString(R.string.notification_syncing_title);
String text = getResources().getString(R.string.notification_syncing_text);
Intent intent = new Intent(this, FeedsActivity.class);
intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
Notification notification = new Notification(R.drawable.feedscribe_status, tickerText, System.currentTimeMillis());
notification.setLatestEventInfo(this, titleText, text, contentIntent);
notification.flags |= Notification.FLAG_ONGOING_EVENT;
mNotificationManager.notify(Globals.NOTIFICATION_SYNCING, notification);
}
private void closeSyncingNotification()
{
mNotificationManager.cancel(Globals.NOTIFICATION_SYNCING);
}
private void showNewItemsNotification(int newItems)
{
String tickerText = getResources().getString(R.string.notification_new_items_ticker, Integer.valueOf(newItems));
String titleText = getResources().getString(R.string.notification_new_items_title);
String text = getResources().getString(R.string.notification_new_items_text, Integer.valueOf(newItems));
Intent intent = new Intent(this, FeedsActivity.class);
intent.setFlags( Intent.FLAG_ACTIVITY_CLEAR_TOP );
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, 0);
Notification notification = new Notification(R.drawable.feedscribe_status, tickerText, System.currentTimeMillis());
notification.setLatestEventInfo(this, titleText, text, contentIntent);
notification.flags |= Notification.FLAG_AUTO_CANCEL;
mNotificationManager.notify(Globals.NOTIFICATION_NEW_ITEMS, notification);
}
private void clearNewItemsNotification()
{
mNotificationManager.cancel(Globals.NOTIFICATION_NEW_ITEMS);
}
public void feedUpdateProgress(int stage, int numStages)
{
if (Globals.LOGGING) Log.e(Globals.LOG_TAG, "feedUpdateProgress " + stage + " of " + numStages);
int progress = 0;
if( numStages > 0)
{
progress = stage * 100/ numStages;
}
broadcastStatus(STATUS_UPDATING, progress, ERROR_NONE);
}
public static void downloadAdded(Context ctx)
{
Intent i = new Intent(ctx, FeedService.class);
i.putExtra(EXTRA_CMD, CMD_DOWNLOAD_ADDED);
sendWakefulWork(ctx, i);
}
public static void updateFeeds(Context ctx, boolean forceUpdate)
{
Intent i = new Intent(ctx, FeedService.class);
i.putExtra(EXTRA_CMD, CMD_UPDATE_FEEDS);
i.putExtra(EXTRA_FORCE, forceUpdate);
sendWakefulWork(ctx, i);
}
public static void updateFeed(Context ctx, long feedId)
{
Intent i = new Intent(ctx, FeedService.class);
i.putExtra(EXTRA_CMD, CMD_UPDATE_FEED);
i.putExtra(EXTRA_FEED_ID, feedId);
sendWakefulWork(ctx, i);
}
public static void clearNotifications(Context ctx)
{
Intent i = new Intent(ctx, FeedService.class);
i.putExtra(EXTRA_CMD, CMD_CLEAR_NOTIFICATIONS);
sendWakefulWork(ctx, i);
}
}