Search code examples
androidpermissionsalarmmanagerandroid-pendingintent

AlarmManager does not work when the app is closed. Why is that?


Good day, I've built a timer into my Android app that sends a message after a certain time. To do this, I added an AlarmManager with a pending intent. Everything works as it should when I have the app open. It also works in the lock screen. But when I close the app, the pending intent is no longer activated and no message appears at the given time. This is my Alarm Manager:

Intent notifyIntent = new Intent(getContext(), MyReceiver.class);
 alarmManager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
        pendingIntent = PendingIntent.getBroadcast
                (getContext(), NOTIFICATION_ID, notifyIntent, PendingIntent.FLAG_UPDATE_CURRENT);

//when the alarm gets activated:

 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
                            alarmManager.setExact(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+delta_time2, pendingIntent);

                        }
 else {
                            alarmManager.set(AlarmManager.RTC_WAKEUP,System.currentTimeMillis()+delta_time2, pendingIntent);

                        }

In the IntentService-Class (where the notification is declared and called):


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

      
        notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);

        PendingIntent notifyPendingIntent =
                PendingIntent.getActivity(
                        this,
                        0,
                        notifyIntent,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );



       
        Intent snoozeIntent = new Intent(this, BigTextIntentService.class);
        snoozeIntent.setAction(BigTextIntentService.ACTION_SNOOZE);

        PendingIntent snoozePendingIntent = PendingIntent.getService(this, 0, snoozeIntent, 0);
        NotificationCompat.Action snoozeAction =
                new NotificationCompat.Action.Builder(
                        R.drawable.ic_alarm_white_48dp,
                        "Snooze",
                        snoozePendingIntent)
                        .build();

        Intent dismissIntent = new Intent(this, BigTextIntentService.class);
        dismissIntent.setAction(BigTextIntentService.ACTION_DISMISS);

        PendingIntent dismissPendingIntent = PendingIntent.getService(this, 0, dismissIntent, 0);
        NotificationCompat.Action dismissAction =
                new NotificationCompat.Action.Builder(
                        R.drawable.ic_cancel_white_48dp,
                        "Dismiss",
                        dismissPendingIntent)
                        .build();

        NotificationCompat.Builder notificationCompatBuilder =
                new NotificationCompat.Builder(
                        getApplicationContext(), notificationChannelId);

        GlobalNotificationBuilder.setNotificationCompatBuilderInstance(notificationCompatBuilder);

        Notification notification = notificationCompatBuilder
                .setStyle(bigTextStyle)
                .setContentTitle(bigTextStyleReminderAppData.getContentTitle())
                .setContentText(bigTextStyleReminderAppData.getContentText())
                .setSmallIcon(R.drawable.ic_launcher)
                .setLargeIcon(BitmapFactory.decodeResource(
                        getResources(),
                        R.drawable.ic_alarm_white_48dp))
                .setContentIntent(notifyPendingIntent)
                .setDefaults(NotificationCompat.DEFAULT_ALL)
    
                .setColor(ContextCompat.getColor(getApplicationContext(), R.color.colorPrimary))


                .setCategory(Notification.CATEGORY_REMINDER)

                .setPriority(bigTextStyleReminderAppData.getPriority())

                .setVisibility(bigTextStyleReminderAppData.getChannelLockscreenVisibility())

             
                .addAction(snoozeAction)
                .addAction(dismissAction)

                .build();
//I am not quite shure, if I declared the foregroundservice for the notification at the right place
 
        startForeground(NOTIFICATION_ID, notification);
        mNotificationManagerCompat.notify(NOTIFICATION_ID, notification);
        Vibrator vibrator = (Vibrator) getApplication().getSystemService(Context.VIBRATOR_SERVICE);
        vibrator.vibrate(2 * 1000);

These are my permissions:

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

Thank you for your help! (btw if this question is stupid or something it's because I didn't really deal with the topic and just wanted to quickly set off an alarm for my app sorry in advance)


Solution

  • Based on your comments it looks like the alarm is triggering as it should, but your BroadcastReceiver is failing when trying to start your Service. The most likely reason is that your device has additional restrictions on background processing. Some devices, mostly low-end and Chinese manufacture, have restrictions on what apps are allowed to run "in the background". If your app isn't on a "white list" of allowed apps, Android won't allow components of the app to be launched in the background.

    See https://developer.android.com/about/versions/oreo/background to read about background Service limitations and see https://stackoverflow.com/a/45482394/769265 as an example of an answer where I discuss the problem of certain manufacturers limiting background processing.


    Note: Since you cannot start a background Service on Android 8 and above (due to the limitations), you can start your Service as a foreground Service, like this:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(intent)
    } else {
        context.startService(intent)
    }