Search code examples
androidnotificationsalarmmanager

Android AlarmManager send notification every time app starts instead of only once


My app use an AlarmManager that start a BroadcastReceiver. The BroadcastReceiver generate a reminder notification to the user.

This is the MainActivity that start the Alarm

public class MainActivity extends ActionBarActivity {

    private PendingIntent pendingIntent;
    private AlarmManager alarmManager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Set the alarm to start at approximately 2:00 p.m.
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(System.currentTimeMillis());
        int curHr = calendar.get(Calendar.HOUR_OF_DAY);

// Checking whether current hour is over 14
        if (curHr >= 14)
        {
            // Since current hour is over 14, setting the date to the next day
            calendar.add(Calendar.DATE, 1);
        }

        calendar.set(Calendar.HOUR_OF_DAY, 14);
// Schedule alarm manager

        Intent myIntent = new Intent(MainActivity.this, MyBroadcastReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);

        alarmManager = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);

        // With setInexactRepeating(), you have to use one of the AlarmManager interval
        // constants--in this case, AlarmManager.INTERVAL_DAY.
        alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(),
                AlarmManager.INTERVAL_DAY, pendingIntent);


    }

And this is the BroadcastReceiver that generate the notification

public class MyBroadcastReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent)
    {
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);

        PowerManager.WakeLock wl = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "tag");

        //Acquire the lock
        wl.acquire();

        Log.v("ADebugTag", "It work!");

        int mId = 0;
        //Show the notification here.
        NotificationCompat.Builder mBuilder =
                new NotificationCompat.Builder(context)
                        .setSmallIcon(R.drawable.ic_action_edit)
                        .setContentTitle("Diario Scolastico")
                        .setContentText("You have homeworks for tomorrow!")
                        .setAutoCancel(true)
                        .setDefaults(-1);

// Creates an explicit intent for an Activity in your app
        Intent resultIntent = new Intent(context, MainActivity.class);

// The stack builder object will contain an artificial back stack for the
// started Activity.
// This ensures that navigating backward from the Activity leads out of
// your application to the Home screen.
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
// Adds the back stack for the Intent (but not the Intent itself)
        stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
        stackBuilder.addNextIntent(resultIntent);
        PendingIntent resultPendingIntent =
                stackBuilder.getPendingIntent(
                        0,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );
        mBuilder.setContentIntent(resultPendingIntent);

        NotificationManager mNotificationManager =
                (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
        mNotificationManager.notify(mId, mBuilder.build());

        //Release the lock
        wl.release();
    }
}

Manifest permissions:

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.INTERNET" />

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

<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />

As you can see the alarm must start at 14 PM, but i receive the notification every time that i start the app. There is something wrong in my code?

I use the Scheduling Repeating Alarms for setting the alarm every day at same hour, but don't work properly


Solution

  • The issue is you are setting the time to current day. So if you are opening your app after 14:00, your alarm manager will immediately fire.

    You need to check whether the time is over 14:00 for the current day, if yes you need to change the date to the next day:

    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    int curHr = calendar.get(Calendar.HOUR_OF_DAY);
    
    // Checking whether current hour is over 14
    if (curHr >= 14)
    {
       // Since current hour is over 14, setting the date to the next day
       calendar.add(Calendar.DATE, 1);
    }
    
    calendar.set(Calendar.HOUR_OF_DAY, 14);
    // Schedule alarm manager