How to run a service every day at noon, and on every boot

23,095

Solution 1

Android alarmmanager is your answer. use it with a broadcast receiver which also resets the alarms on phone wake.

Now with code example: Setting alarm inside a method:

Intent intent = new Intent(context, AlarmReceiver.class);
intent.setAction("packagename.ACTION");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
            0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
        AlarmManager alarm = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarm.cancel(pendingIntent);
alarm.setRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), AlarmManager.INTERVAL_DAY, pendingIntent);

Receiver for your interval:

public class AlarmReceiver extends BroadcastReceiver {
private final String SOMEACTION = "packagename.ACTION"; //packagename is com.whatever.www
@Override
public void onReceive(Context context, Intent intent) {
    Time now = new Time();
    now.setToNow();
    String time = FileHandler.timeFormat(now);

    String action = intent.getAction();
    if(SOMEACTION.equals(action)) {
        // here you call a service etc.
    }

Receiver for resetting alarms whenever phone has been shut down.

public class AlarmSetter extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // get preferences
        SharedPreferences preferences = context.getSharedPreferences("name_of_your_pref", 0);
        Map<String, ?> scheduleData = preferences.getAll();

        // set the schedule time
        if(scheduleData.containsKey("fromHour") && scheduleData.containsKey("toHour")) {
            int fromHour = (Integer) scheduleData.get("fromHour");
            int fromMinute = (Integer) scheduleData.get("fromMinute");

            int toHour = (Integer) scheduleData.get("toHour");
            int toMinute = (Integer) scheduleData.get("toMinute");

            //Do some action
        }
    }

}

Manifest very important, this is added under application:

        <receiver android:name="AlarmReceiver">
        <intent-filter>
            <action android:name="packagename.ACTION"/>
            <action android:name="packagename.ACTION2"/>
        </intent-filter>
    </receiver>

    <receiver android:name="AlarmSetter" >
        <intent-filter>
            <action
                android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>

Also in order for this to work you need to add permission to receive the boot Broadcast in the manifest with following line:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

Hope this cleared things up, if any errors plz tell.

Edit (added alarmsetter example):

public class AlarmSetter extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // Do your stuff
    }
}

Solution 2

This answer seems pretty old. Now, I would totally recommend people to check out SyncAdapter framework provided by Google. It is custom made for such things. Here's the link: https://developer.android.com/training/sync-adapters/index.html

Solution 3

In the demo it starts a service after 5 minutes since boot is complete which is just fine but what do I need to add to get it also start at every noon.

Change the initial time of the setRepeating() call. The example shows one minute from now -- you would need to do the calculations to determine when the next noon is.

You can see an example of that sort of calculation in this OnBootReceiver from a different sample project. Here, I am setting up the alarm to go off every day at a user-specified time.

Share:
23,095
micadelli
Author by

micadelli

Updated on January 09, 2020

Comments

  • micadelli
    micadelli over 4 years

    In my app I have SQLite database that has one table with date rows in milliseconds. I would like to have a notification shown every day IF 30 days has passed since the last date value stored in my database. A service seems to be a good way to accomplish this check up.

    I ran into Commonsware's WakefulIntentService and thought it could be the answer but I really don't know how should I implement it. In the demo it starts a service after 5 minutes since boot is complete which is just fine but what do I need to add to get it also start at every noon. (... but only to show one notification / day, not both, as from boot and regular daily check up)

    I know this could be solved using AlarmManager but really don't know how. So, the help I need is to give me some samples / key points to get the service start on every boot and/or every day without app running.

    thanks

  • micadelli
    micadelli over 12 years
    sorry for phrasing my question a bit bad but I already knew alarmmanager but not exactly how to use it to solve the problem... nor how to reset it on wake. So what I think I need is to start the same service as in commonsware WakeFulIntentService demo (github.com/commonsguy/cwac-wakeful), but from different receiver...? Without app running, how to run the service daily and/or on every boot.
  • Warpzit
    Warpzit over 12 years
    Read about alarmmanagerits very simple. or google it :) can give some code tonight if your still stuck
  • micadelli
    micadelli over 12 years
    have been stuck for few days already :) so yes, code examples will be highly appreciated.
  • micadelli
    micadelli over 12 years
    hi, I don't know why this is so hard for me to understand... but in your example, on AlarmReceiver class you're checking if ACTION.equals(action)... should it be "if (action.equals(SOMEACTION)"? And if it's true, should I call my service as "Intent i = new Intent(context, MyService.class); this.startService(i);"?... and what is that "sleepScheduler.ACTION2" you have declared in your manifest? Plus, howcome you're not calling the service in AlarmSetter?
  • Warpzit
    Warpzit over 12 years
    Updated code and fixed serveral errors. sorry about that was a little quick there. To your questions 1. Yes, 1a. Yes you could do that, 2. Sorry was an error, 3. My code was used for something different now added //Do some action there instead. You can do whatever you want there.
  • Andy
    Andy almost 12 years
    @Warpzit this is a great example. Just got one question. The AlarmSetter class, which resets alarms. Is that a completely seperate class?
  • Warpzit
    Warpzit almost 12 years
    @Andy Added the alarmsetter with empty implementation :) the answer is yes separate class.
  • iTurki
    iTurki over 10 years
    @Warpzit Thanks for this. Just a quick question: Should I put the first part (the Setting alarm inside a method's part) in my MainAtivity? I have it already in the AlarmSetter receiver.
  • Warpzit
    Warpzit over 10 years
    @iturki Wherever you want to set up the alarms you can put this code. It could be after a user interaction or it could be something you define for the user. But the MainActivity is a possible place yes.
  • SMBiggs
    SMBiggs about 8 years
    More people should be aware of this. Like me. Thanks!