11

I'm building an app that will trigger notifications at specific time-intervals during the users waking hours.

I have an alarmManager running inside of a service. The service is explicitly started via button click on the main activity and has the alarmManager executing notifications during specific time invervals. How would I go about stopping the notifications during certain hours of the day? I do not want these notification to be fired, for instance, while the user is sleeping.

My code that is currently firing notifications at user-set intervals is below (imports removed....this is long enough already):

public class FartSmackinChunks extends Service {
    public Notification scheduleNotification;
    public AlarmManager alarmScheduleManager;
    public PendingIntent alarmScheduleIntent;
    private Boolean autoUpdateBoolean = true;
    private int intervalsGoneByInt = 0;
    private Notification notification;
    public static final int NOTIFICATION_ID = 1;

    @Override
    public void onCreate() {
        // TODO: Actions to perform when service is created.
        int icon = R.drawable.icon;
        String tickerText = "INTERVAL FIRED";
        long when = System.currentTimeMillis();
        scheduleNotification = new Notification(icon, tickerText, when);

        alarmScheduleManager = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

        String ALARM_ACTION;
        ALARM_ACTION = ScheduleAlarmReceiver.ACTION_REFRESH_SCHEDULE_ALARM;
        Intent intentToFire = new Intent(ALARM_ACTION);
        alarmScheduleIntent = PendingIntent.getBroadcast(this, 0, intentToFire,
        0);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        SharedPreferences mySharedPreferences =
        PreferenceManager.getDefaultSharedPreferences(getApplicationContext());
        boolean autoUpdateBoolean =
        mySharedPreferences.getBoolean("storedAutoUpdateBoolean", false);
        String updateFreq =
        mySharedPreferences.getString("storedInitialAverageTimeInterval", "00:00:00");

        SimpleDateFormat dfInterval = new SimpleDateFormat("hh:mm:ss");

        Date intervalTimeAsDateObject = null;
        long updateFreqMilliLong;
        try {
            intervalTimeAsDateObject = dfInterval.parse(updateFreq);
        } catch (ParseException e) {
            e.printStackTrace();
        }

        updateFreqMilliLong = intervalTimeAsDateObject.getTime() - 18000000;

        if (autoUpdateBoolean) {
            int alarmType = AlarmManager.ELAPSED_REALTIME_WAKEUP;
            long timetoRefresh = SystemClock.elapsedRealtime() +
            updateFreqMilliLong;
            alarmScheduleManager.setInexactRepeating(alarmType,
            timetoRefresh, updateFreqMilliLong, alarmScheduleIntent);
            notifications();
        } else alarmScheduleManager.cancel(alarmScheduleIntent);

        return Service.START_NOT_STICKY;
    };

    private void notifications() {
        **notification stuff in here***
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Replace with service binding implementation.
        return null;
    }

    @Override
    public void onDestroy() {
        this.alarmScheduleManager.cancel(alarmScheduleIntent);
    }
}

.....and my broadcast receiver implementation here:

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

public class ScheduleAlarmReceiver extends BroadcastReceiver {

    public static final String ACTION_REFRESH_SCHEDULE_ALARM
    = "com.application.ACTION_REFRESH_SCHEDULE_ALARM";

    @Override
    public void onReceive(Context context, Intent intent) {
        Intent startIntent = new Intent(context, SmokerReducerService.class);
        context.startService(startIntent);
    }
}

I'm having a little difficulty wrapping my brain around how this should be implemented.

I was thinking to rework this code so that the alarmManager is fired at waketime and stopped at sleepTime, all while inside the service is a Timer that fires the notification method at specific intervals? Is there a better way to go about doing this?

Any input would be appreciated. I've been trying to work this out in my head for days now.

Thanks

EDIT: @anyone who comes across this intending to use a Timer for daily notifications:

A timer which runs inside of a service will be paused by the runtime when the device is put to sleep (ie...the user puts the phone in standby). Therefor, using a Timer to fire notifications at specific time intervals won't work correctly within a service because when Android pauses the service, it also pauses the timer, which throws off the interval.

The correct way to do this is to use AlarmManager with an array of pending intents to set alarms at specific times during the day. This ensures that even if the phone is put in standby, the notifications (or whatever you want to happen at that time) will still be executed.

Mr_and_Mrs_D
  • 32,208
  • 39
  • 178
  • 361
dell116
  • 5,835
  • 9
  • 52
  • 70
  • `mySharedPreferences.getBoolean` was missing - the `// TODO: Actions to perform when service is created`is needed ? (in question at least - the other TODO is Ok) Also why use a (long running) service ? – Mr_and_Mrs_D Mar 16 '13 at 18:02
  • 1
    @Mr_and_Mrs_D - I ended up using the AlarmManager class with an array of pending intents to do this. – dell116 Mar 18 '13 at 16:48

1 Answers1

3

I was thinking to rework this code so that the alarmManager is fired at waketime and stopped at sleepTime, all while inside the service is a Timer that fires the notification method at specific intervals? Is there a better way to go about doing this?

To my mind, forget thinking of a 'better' way, it seems the only way. Using a timer to control (enable/disable) another timer isn't so strange and makes complete sense to me.

Squonk
  • 48,735
  • 19
  • 103
  • 135
  • Thanks for the reply MisterSquonk. I haven't worked with the AlarmManager before, so this is new to me. Thanks for re-assuring my train of thought. I think you've replied to another thread of mine. Thanks for being helpful. Your input is much appreciated. – dell116 Jan 19 '11 at 23:16
  • @dell116: No problem, I try to help where I can. On this issue, to simplify things, you could simply extend (rather than rework) your code to use AlarmManager to both start/stop your service and also work as the internal 'timer'. AlarmManager is, after all, just an access point to the system/device alarm services - the same alarm services which wake people in the morning, provide birthday reminders etc – Squonk Jan 19 '11 at 23:52
  • I basically did what you said. Instead of having the alarmManager trigger notifications inside the service, I removed the AlarmManager from the service and used a Timer inside the service to fire notifications at the user-defined intervals. In my main settings activity, I use a button to fire the service AND the start of the AlarmManager. Then, with the help of the Calandar, I have the AlarmManager stop the service at the next Calandar day instance of the sleepHour and sleepMinute. It's working exactly as I would like it to. Once again, thank you for your help! – dell116 Jan 20 '11 at 20:35
  • @dell116: That's good to hear and I'm glad to have been some help. Cheers! – Squonk Jan 20 '11 at 22:29
  • 1
    After testing the app for a day I found that using a Timer to fire the notifications won't work because Android pauses services when the phone goes to sleep. Not to mention the battery drain by forcing the service to stay running. I found that setting alarms using AlarmManager for all notification events to be the best solution for this application. As always though, thank you for your input. – dell116 Jan 24 '11 at 06:15