Search code examples
javaandroidandroid-studionotificationsalarmmanager

Creating an android notification that reoccurs every day at some time even when app is closed


A lot of questions on this topic have outdated answers (1-4 years old).

How To give notifications on android on specific time?

How To give notifications on android on specific time in Android Oreo?

Repeat notification every day 12h

The documentation for android did not lead me to specific solutions but helped me understand AlarmManager and the NotificationCompat. My code looks like this in my MainActivity

Intent notifyIntent = new Intent(this, MyReceiver.class);

PendingIntent pendingIntent = PendingIntent.getBroadcast(this, NOTIFICATION_REMINDER, 
notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);

Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.set(Calendar.HOUR_OF_DAY, hours);
calendar.set(Calendar.MINUTE, minutes);
calendar.set(Calendar.SECOND, seconds);

AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP,  calendar.getTimeInMillis(),
     AlarmManager.INTERVAL_DAY,
     pendingIntent); 

My BroadcastReceiver looks like this

public class MyReceiver extends BroadcastReceiver {
    public MyReceiver() {
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        Log.d("Test", "RAN");
        Intent intent1 = new Intent(context, MyNewIntentService.class);
        context.startService(intent1);
    }
}

My IntentService looks like this

public class MyNewIntentService extends IntentService {
    private static final int NOTIFICATION_ID = 3;

    public MyNewIntentService() {
        super("MyNewIntentService");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        NotificationManager mNotificationManager =
                (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);

        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            NotificationChannel channel = new NotificationChannel("SH",
                    "Simple",
                    NotificationManager.IMPORTANCE_DEFAULT);
            channel.setDescription("Notifs");
            mNotificationManager.createNotificationChannel(channel);
        }

        NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), "SH")
                .setSmallIcon(R.mipmap.ic_launcher) // notification icon
                .setContentTitle("Title") // title for notification
                .setContentText("Message")// message for notification
                .setAutoCancel(true); // clear notification after click
        Intent intent1 = new Intent(getApplicationContext(), MainActivity.class);
        PendingIntent pi = PendingIntent.getActivity(this, 0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);
        mBuilder.setContentIntent(pi);
        mNotificationManager.notify(0, mBuilder.build());

    }
}

I've added these to my AndroidManifest.xml right under my activity within the application tag

<receiver
    android:name=".MyReceiver"
    android:enabled="true"
    android:exported="true" >
</receiver>
<service
    android:name=".MyNewIntentService"
    android:exported="false" >
</service>

The notification fires for me but does not when the app is closed. In the android documentation, it seems like android has tried to limit the amount of background processing and timing of apps and the AlarmManager does not run at an accurate time because of this.

How do I make this into a reliable notification reminder for my app that runs at nearly the same time every day even when the app is closed?


Solution

  • You are almost there. Very close just one more thing. Instead of startService() you should use startForegrounService(). In that case your alarm will always fire. Just a few tips:

    1. you should declare the foreground service in your manifest
    2. You have to use alarmManager.setExactAndAllowWhileIdle for API level higher than 23

    You can also check this out for more information.

    Update: This method worked forme on Xiaomi Redme note 8, but the just suddenly stopped working! It may not be a very dependable solution for custom OS devices at the moment. Hope google come up with a solid solution.