package com.darkrockstudios.apps.tminus; import android.annotation.TargetApi; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.os.Build; import android.preference.PreferenceManager; import android.util.Log; import com.commonsware.cwac.wakeful.WakefulIntentService; import com.darkrockstudios.apps.tminus.database.DatabaseHelper; import com.darkrockstudios.apps.tminus.launchlibrary.Launch; import com.darkrockstudios.apps.tminus.misc.OsUtil; import com.darkrockstudios.apps.tminus.misc.Preferences; import com.darkrockstudios.apps.tminus.misc.TminusUri; import com.j256.ormlite.android.apptools.OpenHelperManager; import com.j256.ormlite.dao.Dao; import com.j256.ormlite.stmt.PreparedQuery; import com.j256.ormlite.stmt.QueryBuilder; import org.joda.time.DateTime; import java.sql.SQLException; import java.util.Date; import java.util.List; import java.util.concurrent.TimeUnit; /** * Created by adam on 7/10/13. * Dark Rock Studios * darkrockstudios.com */ public class UpdateAlarmsService extends WakefulIntentService { private static final String TAG = UpdateAlarmsService.class.getSimpleName(); public UpdateAlarmsService() { super( UpdateAlarmsService.class.getSimpleName() ); } public static void cancelAlarmsForLaunch( final Launch launch, final Context context ) { final AlarmManager alarmManager = (AlarmManager) context.getSystemService( Context.ALARM_SERVICE ); final Intent reminderIntent = new Intent( context, NotificationService.class ); reminderIntent.setData( TminusUri.buildLaunchReminderNotification( launch.id ) ); final Intent imminentIntent = new Intent( context, NotificationService.class ); reminderIntent.setData( TminusUri.buildLaunchImminentNotification( launch.id ) ); final PendingIntent pendingIntentReminder = PendingIntent .getService( context, 0, reminderIntent, 0 ); final PendingIntent pendingIntentLaunchImminent = PendingIntent .getService( context, 0, imminentIntent, 0 ); alarmManager.cancel( pendingIntentReminder ); alarmManager.cancel( pendingIntentLaunchImminent ); } public static void cancelAutoUpdateAlarm( final Context context ) { final AlarmManager alarmManager = (AlarmManager) context.getSystemService( Context.ALARM_SERVICE ); alarmManager.cancel( createLaunchUpdateIntent( context ) ); } @Override protected void doWakefulWork( final Intent intent ) { final AlarmManager alarmManager = (AlarmManager) getSystemService( Context.ALARM_SERVICE ); final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences( this ); final boolean showReminderNotifications = preferences.getBoolean( Preferences.KEY_REMINDER_NOTIFICATION, true ); final boolean showImminentLaunchNotifications = preferences .getBoolean( Preferences.KEY_IMMINENT_LAUNCH_NOTIFICATION, true ); final boolean automaticUpdating = preferences.getBoolean( Preferences.KEY_AUTOMATIC_UPDATING, true ); if( automaticUpdating ) { long updateFrequency = Long.parseLong( preferences .getString( Preferences.KEY_AUTOMATIC_UPDATING_FREQUENCY, "24" ) ); updateFrequency = TimeUnit.HOURS.toMillis( updateFrequency ); setLaunchUpdateAlarm( alarmManager, updateFrequency ); } Log.i( TAG, "Updating Alarms for upcoming Launches..." ); final DatabaseHelper databaseHelper = OpenHelperManager.getHelper( this, DatabaseHelper.class ); if( databaseHelper != null ) { try { final Dao<Launch, Integer> launchDao = databaseHelper.getDao( Launch.class ); final QueryBuilder<Launch, Integer> queryBuilder = launchDao.queryBuilder(); final PreparedQuery<Launch> query = queryBuilder.orderBy( "net", true ).prepare(); final DateTime cutOffDate = DateTime.now().plusDays( 2 ); final List<Launch> results = launchDao.query( query ); for( final Launch launch : results ) { if( launch.net.isBefore( cutOffDate ) ) { Log.d( TAG, "Setting alarms for Launch id: " + launch.id ); if( showReminderNotifications ) { setReminderAlarm( launch, alarmManager ); } if( showImminentLaunchNotifications ) { setImminentLaunchAlarm( launch, alarmManager ); } } else { Log.d( TAG, "No more alarms to set." ); break; } } } catch( final SQLException e ) { e.printStackTrace(); } OpenHelperManager.releaseHelper(); } } private static PendingIntent createLaunchUpdateIntent( final Context context ) { final Intent serviceIntent = new Intent( context, LaunchUpdateService.class ); return PendingIntent.getService( context, 0, serviceIntent, PendingIntent.FLAG_UPDATE_CURRENT ); } private void setLaunchUpdateAlarm( final AlarmManager alarmManager, final long updateFrequency ) { Log.d( TAG, "Setting the auto-update alarm for Launches every " + TimeUnit.MILLISECONDS .toHours( updateFrequency ) + " hours" ); final long now = new Date().getTime(); alarmManager .setInexactRepeating( AlarmManager.RTC, now + updateFrequency, updateFrequency, createLaunchUpdateIntent( this ) ); } private void setReminderAlarm( final Launch launch, final AlarmManager alarmManager ) { Intent serviceIntent = new Intent( this, NotificationService.class ); serviceIntent.setData( TminusUri.buildLaunchReminderNotification( launch.id ) ); serviceIntent.putExtra( NotificationService.EXTRA_LAUNCH_ID, launch.id ); serviceIntent .putExtra( NotificationService.EXTRA_NOTIFICATION_TYPE, NotificationService.EXTRA_NOTIFICATION_TYPE_REMINDER ); PendingIntent pendingIntent = PendingIntent .getService( this, 0, serviceIntent, 0 ); final DateTime dayBefore = launch.net.minusDays( 1 ); // Don't set alarms for the past if( dayBefore.isAfter( DateTime.now() ) ) { alarmManager.set( AlarmManager.RTC, dayBefore.getMillis(), pendingIntent ); } else { Log.d( TAG, "Not setting reminder alarm for launch id " + launch.id + " because it has already passed." ); } } @TargetApi(Build.VERSION_CODES.KITKAT) private void setImminentLaunchAlarm( final Launch launch, final AlarmManager alarmManager ) { Intent serviceIntent = new Intent( this, NotificationService.class ); serviceIntent.setData( TminusUri.buildLaunchImminentNotification( launch.id ) ); serviceIntent.putExtra( NotificationService.EXTRA_LAUNCH_ID, launch.id ); serviceIntent .putExtra( NotificationService.EXTRA_NOTIFICATION_TYPE, NotificationService.EXTRA_NOTIFICATION_TYPE_LAUNCH_IMMINENT ); PendingIntent pendingIntent = PendingIntent .getService( this, 0, serviceIntent, 0 ); DateTime triggerTime = launch.net.minusMinutes( 10 ); if( triggerTime.isAfter( DateTime.now() ) ) { // The behavior of alarmManager.set() changed in 4.4, it is now inexact, thus for // 4.4 and above we must use this new API call if( OsUtil.HAS_4_4_KITKAT ) { alarmManager.setExact( AlarmManager.RTC_WAKEUP, triggerTime.getMillis(), pendingIntent ); } else { alarmManager.set( AlarmManager.RTC_WAKEUP, triggerTime.getMillis(), pendingIntent ); } } else { Log.d( TAG, "Not setting imminent launch alarm for launch id " + launch.id + " because it has already passed." ); } } }