gt: 		if (nifc == null) {
context: package com.wanikani.androidnotifier.notification;
  
  import java.io.IOException;
  import java.util.Calendar;
  import java.util.Date;
  
  import android.app.AlarmManager;
  import android.app.IntentService;
  import android.app.PendingIntent;
  import android.content.BroadcastReceiver;
  import android.content.Context;
  import android.content.Intent;
  import android.content.SharedPreferences;
  import android.database.SQLException;
  import android.net.ConnectivityManager;
  import android.net.Uri;
  import android.os.Bundle;
  
  import com.wanikani.androidnotifier.DashboardData;
  import com.wanikani.androidnotifier.DashboardData.OptionalDataStatus;
  import com.wanikani.androidnotifier.MainActivity;
  import com.wanikani.androidnotifier.MeterSpec;
  import com.wanikani.androidnotifier.SettingsActivity;
  import com.wanikani.androidnotifier.WebReviewActivity;
  import com.wanikani.androidnotifier.db.HistoryDatabase;
  import com.wanikani.androidnotifier.notification.NotificationInterface.ChangeType;
  import com.wanikani.androidnotifier.notification.NotifierStateMachine.Event;
  import com.wanikani.wklib.Connection;
  import com.wanikani.wklib.ExtendedLevelProgression;
  import com.wanikani.wklib.ItemLibrary;
  import com.wanikani.wklib.Kanji;
  import com.wanikani.wklib.Radical;
  import com.wanikani.wklib.SRSDistribution;
  import com.wanikani.wklib.StudyQueue;
  import com.wanikani.wklib.UserInformation;
  
  /* 
   *  Copyright (c) 2013 Alberto Cuda
   *
   *  This program is free software: you can redistribute it and/or modify
   *  it under the terms of the GNU General Public License as published by
   *  the Free Software Foundation, either version 3 of the License, or
   *  (at your option) any later version.
   *
   *  This program 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 this program.  If not, see <http://www.gnu.org/licenses/>.
   */
  
  /**
   * This service that show and hides the notification icon.
   * In other words, this class implements the main object of this app.
   * This service is started on boot by {@see NotificationService.BootReceiver} or
   * by {@link DashboardActivity} when notifications are enabled.
   * Conversely, it is stopped by {@link DashboardActivity} when 
   * notifications are disabled.
   * Since the notification logic is not straightforward,
   * we implement it in a separate class ({@link NotifierStateMachine})
   * while here is just the glue code that interacts with the operating system. 
   */
  public class NotificationService 
  	extends IntentService implements NotifierStateMachine.Interface {
  	
  	public class StateData {
  		
  		public boolean hasReviews;
  		
  		public boolean hasLessons;
  		
  		public boolean thisLevel;
  		
  		public int reviews;
  		
  		public int lessons;
  		
  		public DashboardData dd;
  		
  		public ExtendedLevelProgression elp;
  		
  		private static final String PREF_REVIEWS = PREFIX + "sd.reviews";
  		
  		private static final String PREF_LESSONS = PREFIX + "sd.lessons";
  
  		private static final String PREF_THIS_LEVEL = PREFIX + "sd.thisLevel";
  
  		private StateData (SharedPreferences prefs)
  		{
  			reviews = prefs.getInt (PREF_REVIEWS, 0);
  			lessons = prefs.getInt (PREF_LESSONS, 0);
  			thisLevel = prefs.getBoolean (PREF_THIS_LEVEL, false);
  			hasReviews = reviews > 0;
  			hasLessons = lessons > 0;
  		}
  		
  		private void serialize (SharedPreferences prefs)
  		{
  			prefs.edit ().
  				putInt (PREF_REVIEWS, hasReviews ? reviews : 0).
  				putInt (PREF_LESSONS, hasLessons ? lessons : 0).
  				putBoolean (PREF_THIS_LEVEL, thisLevel).commit ();
  		}
  		
  		private void setExtendedLevelProgression (ExtendedLevelProgression elp)
  		{
  			this.elp = elp;
  
  			thisLevel =
  					elp != null && 
  					// reviewsAvailable = 0 && currentLevelXXX > 0 is possible
  					// if the local clock is noy in sync with WK 
  					dd.reviewsAvailable > 0 && 
  					(elp.currentLevelKanjiAvailable + 
  					 elp.currentLevelRadicalsAvailable) > 0 &&
  					SettingsActivity.getThisLevel (NotificationService.this);			
  		}
  		
  		public int cap (int timeout)
  		{
  			int ans;
  			
  			if (elp == null || elp.currentLevelAvailable == null || 
  				!SettingsActivity.getThisLevel (NotificationService.this))
  				return timeout;
  			
  			ans = (int) ((elp.currentLevelAvailable.getTime () - System.currentTimeMillis ()) / 1000 / 60);
  			if (ans < 0)
  				ans = timeout;
  
  			ans = Math.min (ans, 4 * 60);	/* In case of new lessons  -> first SRS time out */
  			
  			return Math.min (ans, timeout);
  		}
  	}
  	
  	/**
  	 * This event receiver gets all the notifications needed by
  	 * this class. Currently they are:
  	 * <ul>
  	 * 	<li><code>BOOT_COMPLETED</code> to start the notification
  	 * 			state machine.
  	 *  <li><code>CONNECTIVITY_ACTION</code> when the connectivity
  	 * 			state changes.  This is useful to quickly fix IO errors,
  	 * 			bypassing the exponential backoff algorithm the FSM would
  	 * 			use.
  	 *  <li><code>PACKAGE_REPLACED</code> to restart the notifier after
  	 *  		our package gets updated
  	 */
  	public static class Receiver extends BroadcastReceiver {
  	 
  		/**
  		 * Starts the {@link NotificationService} service.
  		 *	@param context the context on which to send notifications
  		 *	@param intent the <code>BOOT_COMPLETED</code> intent  
  		 */
  	    @Override
  	    public void onReceive (Context context, Intent intent) 
  	    {
  			String action, sAction;
  			Intent sIntent;
  						
  			action = intent.getAction ();
  			if (action.equals (Intent.ACTION_BOOT_COMPLETED))
  				sAction = ACTION_BOOT_COMPLETED;
  			else if (action.equals (ConnectivityManager.CONNECTIVITY_ACTION))
  				sAction = ACTION_CONNECTIVITY_CHANGE;
  			else if (action.equals (Intent.ACTION_PACKAGE_REPLACED))
  				sAction = ACTION_BOOT_COMPLETED;
  			else
  				return;
  			
  			sIntent = new Intent (context, NotificationService.class);
  			sIntent.setAction (sAction);
  			context.startService (sIntent);
  	    }
  	}
  	
  	/// Local prefix
  	private static final String PREFIX = "com.wanikani.wanikaninotifier.NotificationService.";
  	
  	/// FSM bundle key
  	private static final String KEY_FSM = PREFIX + "fsm";
  	
  	/// Dashboard data key
  	public static final String KEY_DD = PREFIX + "dd";
  	
  	/// Current Notification Interface
  	private NotificationInterface nifc;
  	
  	/// The autocancel notification implementation
  	private AutoCancelNotification acn;
  	
  	/// The persistent notification implementation
  	private PersistentNotification pn;
  	
  	/// The current data
  	private StateData sd;
  
  	/* The actions this class supports. We keep the same name of
  	 * the standard actions, when a mapping is possible. However we
  	 * don't use the official name because data is different */
  
  	/** Boot action, called at boot time or when notifications are enabled */
  	public static final String ACTION_BOOT_COMPLETED = 
  			PREFIX + "BOOT_COMPLETED";
  	
  	/** Called when network connectivity changes. Used to try and fix 
  	 * connection errors */
  	public static final String ACTION_CONNECTIVITY_CHANGE = 
  			PREFIX + "CONNECTIVITY_CHANGE";
  
  	/** Called when a state machine or the cron alarm goes off.
  	 *  The state machine is reconstructed from intent extra data
  	 *  and we proceed to the next step */
  	public static final String ACTION_ALARM = 
  			PREFIX + "ALARM";
  
  	/** Called when the user taps the reviews notification.
  	 *  We start an external browser, but also reset the state machine
  	 *  that may be polling with large intervals */
  	public static final String ACTION_TAP = 
  			PREFIX + "TAP";
  
  	/** Called when the user taps the persistent notification and there are no reviews nor lessons. */
  	public static final String ACTION_NULL_TAP = 
  			PREFIX + "NULL_TAP";
  
  	/** Called when the user taps the lessons notification.
  	 *  We start an external browser, but also reset the state machine
  	 *  that may be polling with large intervals */
  	public static final String ACTION_LESSONS_TAP = 
  			PREFIX + "LESSONS_TAP";
  	
  	/** Called by @link DashboardActivity when the notification icon needs to
  	 *  be hidden. It is similar to @link {@link #ACTION_TAP}, however it
  	 *  does not start the browser, because this is done at activity level  */
  	public static final String ACTION_HIDE_NOTIFICATION = 
  			PREFIX + "HIDE_NOTIFICATION";
  
  	/** Called by @link DashboardActivity when it has obtained some fresh
  	 *  dashboard data. This avoids having the dashboard displaying different
  	 *  information from notification bar. 
  	 */
  	public static final String ACTION_NEW_DATA = 
  			PREFIX + "NEW_DATA";
  	
  	/** The preferences file */
  	private static final String PREFERENCES_FILE = "notification.xml";
  	
  	/** The cron schedule alarm time shared preferences key */
  	private static final String PREFS_CRON_NEXT = PREFIX + "CRON_NEXT";
  	
  	/** Last known vacation day. Defaults to -1 */
  	public static final String PREFS_LAST_VACATION = PREFIX + "LAST_VACATION";
  	
  	/** The cron interval. Default is one day */
  	private static final long CRON_INTERVAL = 24 * 3600 * 1000;
  	
  	/** The cron retry interval. Default is half an hour */
  	private static final long CRON_RETRY = 1800 * 1000;	
  	
  	/**
  	 * Constructor. 
  	 */
  	public NotificationService () 
  	{
  		super("NotificationService");
  	}
  	
  	private SharedPreferences prefs ()
  	{
  		int flags;
  		
  		flags = Context.MODE_PRIVATE;
  
  		return getSharedPreferences (PREFERENCES_FILE, flags);		
  	}
  	
  	private void updateNotificationInterface ()
  	{
  		NotificationInterface nnifc;
  		
  		nnifc = SettingsActivity.getPersistent (this) ? pn : acn;
  		if (nifc != nnifc) {
  			if (nifc != null)
  				nifc.disable ();
  			nifc = nnifc;
  			nifc.enable (sd);
  		}
  	}
  	
  	/**
  	 * Handles incoming intents, dispatching them to the appropriate methods.
  	 * Before doing this, we check whether notifications are enabled; if they
  	 * are not, this methods returns. This provides a simple method to
  	 * stop notifications without explicitly canceling pending alarms.
  	 * @see #bootCompleted(Intent)
  	 * @see #connectivityChange(Intent)
  	 * @see #alarm(Intent)
  	 * 	@param intent the intent
  	 */
  	@Override
  	public void onHandleIntent (Intent intent)
  	{
  		String action;
  		boolean enabled;
  		
  		sd = new StateData (prefs ());
  
  		enabled = SettingsActivity.getEnabled (this);
  		action = intent.getAction ();
  				
  