Search code examples
javaandroidalarmmanagerandroid-notifications

Utilizing AlarmManager to trigger Notification


Im trying to create a part of a fitness application that will remind a user to do their daily exercises at a chosen time. This is utilising the AlarmManager to create a daily alarm which will create a notification that will appear at the chosen time.

When the alarm time comes, no notification comes through. I've tested the notification, and it will appear if placed on the action click of a button.

Should I be using extends BroadcastReceiver instead of extends Service?

Creating the alarm:

public void SaveAlarm(View V) {

    Intent myIntent = new Intent(SetAlarm.this, NotifyService.class);
    AlarmManager mAlarmManager = (AlarmManager) this.getSystemService(ALARM_SERVICE);
    mPendingIntent = PendingIntent.getService(this, 0, myIntent, 0);

    //Create Alarm Time in calendar
    Calendar mCalendar = Calendar.getInstance();
    mCalendar.setTimeInMillis(System.currentTimeMillis());
    mCalendar.set(Calendar.HOUR_OF_DAY, AlarmHour);
    mCalendar.set(Calendar.MINUTE, AlarmMinute);

    //Set alarm to repeat ever 24hrs
    mAlarmManager.setRepeating(AlarmManager.RTC_WAKEUP, mCalendar.getTimeInMillis(),
            AlarmManager.INTERVAL_DAY, mPendingIntent);

    //Save Alarm to shared preferences
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putInt("AlarmHour", AlarmHour);
    editor.putInt("AlarmMinute", AlarmMinute);
    editor.commit();

    //Notify user it's been saved
    Toast.makeText(this, "Alarm Saved", Toast.LENGTH_LONG).show();

    //Switch view
    Intent intent = new Intent(SetAlarm.this, Home.class);
    startActivity(intent);

}

Class to create notification:

public class NotifyService extends Service {
@Override
public IBinder onBind(Intent Intent) {
    return null;
}

@Override
public void onCreate() {

    createNotificationChannel();

    NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);

    NotificationCompat.Builder builder = new NotificationCompat.Builder(this, "Workout")
            .setSmallIcon(R.drawable.common_google_signin_btn_text_light)
            .setContentTitle("Workout Time!")
            .setContentText("Time to do your daily workout.")
            .setPriority(NotificationCompat.PRIORITY_DEFAULT);


    notificationManager.notify(1, builder.build());
}

private void createNotificationChannel() {
    // Create the NotificationChannel, but only on API 26+ because
    // the NotificationChannel class is new and not in the support library
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        CharSequence name = "Workout";
        String description = "Workout";
        int importance = NotificationManager.IMPORTANCE_DEFAULT;
        NotificationChannel channel = new NotificationChannel("Workout", name, importance);
        channel.setDescription(description);
        // Register the channel with the system; you can't change the importance
        // or other notification behaviors after this
        NotificationManager notificationManager = getSystemService(NotificationManager.class);
        notificationManager.createNotificationChannel(channel);
    }
}

}


Solution

  • According to official Android docs of Service component:

    A Service is an application component representing either an application's desire to perform a longer-running operation while not interacting with the user or to supply functionality for other applications to use.

    In your case, triggering a simple notification is not considered a long-running operation, so you should use BroadcastReceiver which is designed to run for a simple task at a specific conditions.

    To implement this using a BroadcastReceiver you should first change your service to a BroadcastReceiver:

    public class NotifyReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            // Notify user here
        }
    }
    

    Then pass your receiver to AlarmManager like this:

    public void SaveAlarm(View V) {
        Intent myIntent = new Intent(SetAlarm.this, NotifyReceiver.class);
        AlarmManager mAlarmManager = (AlarmManager) this.getSystemService(ALARM_SERVICE);
        mPendingIntent = PendingIntent.getBroadcast(SetAlarm.this, 0, myIntent, PendingIntent.FLAG_UPDATE_CURRENT);
       ...
    }
    

    Don't forget to declare your receiver in AndroidManifest.xml:

    <receiver android:name=".NotifyReceiver"/>