15

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

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
micadelli
  • 2,482
  • 6
  • 26
  • 38

3 Answers3

41

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
    }
}
Warpzit
  • 27,966
  • 19
  • 103
  • 155
  • 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 (https://github.com/commonsguy/cwac-wakeful), but from different receiver...? Without app running, how to run the service daily and/or on every boot. – micadelli Oct 21 '11 at 08:14
  • Read about alarmmanagerits very simple. or google it :) can give some code tonight if your still stuck – Warpzit Oct 21 '11 at 08:29
  • have been stuck for few days already :) so yes, code examples will be highly appreciated. – micadelli Oct 21 '11 at 08:46
  • 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? – micadelli Oct 24 '11 at 11:42
  • 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. – Warpzit Oct 24 '11 at 16:49
  • @Warpzit this is a great example. Just got one question. The `AlarmSetter` class, which resets alarms. Is that a completely seperate class? – Andy Jul 06 '12 at 03:37
  • @Andy Added the alarmsetter with empty implementation :) the answer is yes separate class. – Warpzit Jul 06 '12 at 07:05
  • @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. – iTurki Aug 17 '13 at 06:43
  • @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. – Warpzit Aug 17 '13 at 11:39
5

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

Ankit
  • 901
  • 8
  • 6
2

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.

CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491