Search code examples
androidandroid-studioandroid-serviceandroid-notificationsandroid-alarms

Android Developing: notifications don't show when app is closed


How can I send scheduled notifications in Android Studio? I got this task: I want to get notifications at the some chosen time of the day every day. I can easily get them when app is alive, but when its closed notifications don't come up.

I've already tried JobScheduler, AlarmManager and WorkManager and none of these didn't work well. My project runs at minimum SDK 26 (Android Oreo). Target SDK is 30. Last code version looks like that:

AlertReceiver.java

public class AlertReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        intent = new Intent(context, NotificationService.class);
        context.startService(intent);
    }
}

NotificationService.java

public class NotificationService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        showNotifications();

        return Service.START_STICKY;
    }

    private void showNotifications(){
        NotificationHelper notificationHelper = new NotificationHelper(getApplicationContext());

        NotificationCompat.Builder nb;

        nb = notificationHelper.getChannelNotification("Title", "Description");
        notificationHelper.getManager().notify(123, nb.build());
    }

    @Override
    public IBinder onBind(Intent intent) {
        throw new UnsupportedOperationException("Not yet implemented");
    }
}

I schedule the alert like so:

        ...
        Calendar calendar = Calendar.getInstance();

        calendar.set(Calendar.HOUR_OF_DAY, hours);
        calendar.set(Calendar.MINUTE, minutes);

        AlarmManager alarm_manager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(this, AlertReceiver.class);
        PendingIntent pending_intent = PendingIntent.getBroadcast(this, 0, intent, 0);

        alarm_manager.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pending_intent);
```

Solution

  • The problem is that from Android 8 calling startService from the background is not allowed:

    In this code:

    public class AlertReceiver extends BroadcastReceiver {
        @Override
        public void onReceive(Context context, Intent intent) {
            intent = new Intent(context, NotificationService.class);
            context.startService(intent);
        }
    }
    

    You can change from:

    context.startService(intent);
    

    To:

    ContextCompat.startForegroundService(getApplicationContext(), intent)
    

    And put this in your Manifest:

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

    This will at least allow your service to run from the background in your current implementation.

    You then have 5 seconds to call startForeground() in your Service and post a Notification that lets the user know that your service is running or it will be terminated.

    Also for what you are trying to do, I think you will get a better result with:

    setExactAndAllowWhileIdle
    

    Or

    setAlarmClock
    

    setExact does not work as the name implies. All the AlarmManager documentation needs to be read carefully and I would suggest studying "doze" in detail before attempting any Service implementations that rely on timing.