93

My app uses AlarmManager and it has been working since 4 years ago. But I noticed it started failing in some devices.

I'm pretty sure code is right (I'm using WakefulBroadcastReceiver, and setExactAndAllowWhileIdle for devices with Doze) because it's working perfectly on Nexus devices, but it fails in devices of some manufacturers (Huawei, Xiaomi...).

Huawei devices, for example, have a kind of battery manager that kill apps, and when an app is killed, scheduled alarms are cancelled. So setting an app as "protected" in Huawei battery manager solves the problem.

But recently I noticed it's not working with more devices: Xiaomi, Samsung (maybe it's related to the new "Smart Manager"?)... It seems that this behavior is becoming a standard: to kill background apps.

Anyone know anything about it? Any way to ensure alarm is fired?

EDIT: This problem is caused by "battery savers" added by different manufacturers. More info here: https://dontkillmyapp.com/

Sergio Viudes
  • 2,714
  • 5
  • 26
  • 44
  • Sergio you are right, I had the same issue with an recurring weekly alarm, it did not work. I was unable to make it work. This new trend will kill all cool apps on Android. I hope the manufacturers realize that. – Erdinc Ay Jan 13 '16 at 20:40
  • 9
    Manufacturers blame apps for power consumption, and they keeps marketing the Octa-cores which eats more battery compared to the CPU with less cores. Do they think that simply adding a core would speed-up their phones? – FrozenFire Jan 19 '16 at 07:59
  • So... we can't use AlarmManager with reliability anymore? – Sergio Viudes Jan 19 '16 at 17:26
  • Hi @SergioViudes have you tried GCM Network Manager? I'm not sure for what you're using the AM but please read this: https://developers.google.com/cloud-messaging/network-manager This is the closest approximation for a backport of the JobSchedulers API. – Avi Levin Jan 19 '16 at 22:09
  • Thanks @AviLevinshtein. I would like to do without a server. I need that the alarm goes off at exact time, every day. Using GCM may cause delays, or the user may not have Internet connection. – Sergio Viudes Jan 20 '16 at 07:52
  • Hi @SergioViudes ,just curious, are you trying to set the AM from a service bind to the application or with a different process? – Avi Levin Jan 20 '16 at 12:38
  • @AviLevinshtein I'm setting the AM from an Activity – Sergio Viudes Jan 20 '16 at 15:53
  • @SergioViudes, since activity is destroyed or the configuration changes it's a bad practice to enable for long operation such as alarm manager on top of it. a service is geared towards longer running tasks that should run in the background. try read about a good IntentService with AM implementation that is set first inside an activity. If you want I can always write you a good example below. Just let me know. – Avi Levin Jan 20 '16 at 21:13
  • 1
    @AviLevinshtein Maybe I misunderstood your question. I'm creating the alarms in my activity. Then, when the alarm goes off, a broadcast receiver is executed, and finally, a WakefulIntentService (class from @commonsware) is executed. – Sergio Viudes Jan 21 '16 at 08:24
  • From one alarm maker to another, please try my new answer below, setAlarmClock(). – Tyler Pfaff Jan 28 '16 at 08:01
  • I'm having the same exact issue. Did you finally manage to solve it? I'm desperated now. Why then they create AlarmManager class if you can't use it reliably. – JFValdes Mar 31 '16 at 07:58
  • 2
    @JFValdes I'm still looking for a solution. AlarmManager is working perfectly on devices with Vanilla Android. The problem is that manufacturers are trying to "enhance" Android features, and they broke AlarmManager... Manufacturers shouldn't implement their own "battery savers", if they use standard Doze mode, then AlarmManager would work perfectly... Still looking for a solution... – Sergio Viudes Mar 31 '16 at 18:09
  • 1
    Is there any solution yet? How does other apps like reminders or something do that? There have to be another option than setAlarm, which is for alarms, not for reminders – kv1dr Jun 06 '16 at 20:15
  • Hey @Sergio Viudes finally how did you resolved your problem? There are many people in android world who suffering this issue....please tell as did you get any solution for this or not? – Himanshu Dec 06 '16 at 12:01
  • 1
    @SergioViudes i am also facing same problem with Xiomi devices for tracking. and if i keep out my app from battery saving restriction than its working correctly in 3 out of 4 devices by doing following settings-- --> Go to the battery -> Power --> App battery saver --> your app Now select No restrictions( for Background settings) then Allow option for Background location – Imran Khan Saifi Dec 07 '16 at 12:15
  • Thanks for your comment @ImranKhanSaifi, as far I know, this is the only solution to this problem. – Sergio Viudes Dec 07 '16 at 15:26
  • I have the same issue on Huawei, it just kill my planned Alarms. I tried to put my app to the protected app and it does't help. It will not stop the app itself, but still killing my planned alarm which doesn't fire. I tried install many application which for example use alarms for update widget and some of them are working correctly, also when I don't set them as protected. So there must be some reason why Huwei kill my alarms but no for others apps. – ATom Jan 29 '17 at 23:10
  • had the same problem. This was my workaround: https://stackoverflow.com/questions/52991241/alarmmanager-does-not-wakeup-at-right-time-on-samsung-phone/53097267#53097267 – Gatschet Nov 16 '18 at 09:59
  • @Gatschet I tried it with no luck :( – Sergio Viudes Nov 16 '18 at 10:56
  • 1
    There is a website that explains how to deal with this problem with different manufacturers: https://dontkillmyapp.com – Sergio Viudes Mar 04 '19 at 09:39

14 Answers14

24

I'm trying to solve it several weeks already. I found nothing. Huawei just kill all the alarms after some time. If I put the app to the protected app in their battery saver it does't help. But If I change package name of my app to contain words like alarm, clock or calendar, it works absolutely normal like on any other devices. I don't understand how Google can give certification for this crap. I think that OEM should not modify core platform in such way. I understand that they have own batter saver which kill the app after some time, when user don't use it. But this killing alarms also of protected apps.

Also setAlarmClock() for exact timing alarms helps. But it is not possible to use this for thinks like widget update.

Update: Protection by package name keywords is already not working on current Huawei devices, it was true in 2017.

ATom
  • 15,960
  • 6
  • 46
  • 50
  • Same as me, I also try it but nothing way to solve this problem on some brand Xiaomi, Oppo, Huawei. They sometimes kill background process and alarm to save battery. – Andi Susilo Mar 15 '17 at 14:01
  • 1
    I have huawei phone, changing package name to alarm/calendar does nothing. Only way to bypass this add your app in protected app list from phone manager – Ashish Pardhiye Aug 24 '17 at 07:15
10

The issue is Smart Manager. Samsung has a battery manager which at times disables certain apps from running in background. It tried to "resume" when going back to the app but completely disables the application or may resume every 5 mins or so (depending how Samsung has it).

This would work on stock versions of android as there is no Samsung Manager. You can also install custom version of android which has some features to enable SM (depending on the rom).

S A
  • 827
  • 10
  • 23
  • I'm getting crazy because I have no Samsung device to test it. I only know what users of my app are telling me. Do you know if the problem is that AlarmManager is not working because app gets killed? Or the problem is that device can't wake when alarm goes off because of that manager? – Sergio Viudes Jan 20 '16 at 07:59
  • @SergioViudes Recently a lot of companies have been implementing their own. Such as LG has one which works similar to samsung, maybe your phone has one? The problem isn't the alarm, the alarm app is pushed to a state where it is inactive completely. Smart Manager thinks its just a random app that you don't need. I noticed certain apps can get past it, maybe some apps are accepted by the smart manager. – S A Jan 20 '16 at 11:58
  • 1
    @SergioViudes I have a samsung to test and I can tell you there is not a lot you can get from it. When the smart manager optimizes your app there is no error or anything, it just dies, similar to force stopping. It's still in the list of recent apps though – Tim Feb 24 '16 at 13:24
  • Thanks Tim. Would be great to solve this problem without having to exclude apps from "Smart" Manager. – Sergio Viudes Feb 24 '16 at 16:34
  • 1
    devices like xiaomi(miui), vivo and htc set a whole bunch of permissions as false by default, unless it is an app in the list of "trusted" apps which they seem to determine themselves(whatsapp,truecaller,etc are trusted by default). This is becoming a coders nightmare – desidigitalnomad Aug 14 '17 at 15:54
4

Most of modern Android devices come with an app or mechanism, which automagically tries to figure out how to save battery and as a result might kill certain 3rd party apps. This might result in removing scheduled tasks and jobs, (e.g. alarms not going off, push notification not working, etc.). In many cases this happens completely independent from battery saving mechanisms of Android, in my case i couldn't make more battery optimization when i detect some devices model, i redirect user to the start up manager to whitelist my application

You found in this link for every model the intent that you should invoke https://android-arsenal.com/details/1/6771

baderkhane
  • 307
  • 2
  • 10
3

This might be late but I hope it helps someone.

I was stuck on the same problem for so long. But now I konw how to solve this problem. This is for anyone who might have the same problem. People keep saying that you have to enable AutoStart but I managed to it with out using auto start.

First of all, WakeFullBroadcastaReceiver is now deprecated and you should use BroadcastReceiver. Second of all, you have to use the ForegroudService instead of BackgroundService.

I will give you the example in the following:

IntentService.class

public class NotificationService extends IntentService {


//In order to send notification when the app is close
//we use a foreground service, background service doesn't do the work.



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

@Override
public void onCreate() {
    super.onCreate();

}

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);

    //There is no difference in the result between start_sticky or start_not_sticky at the moment
    return START_NOT_STICKY;
}

@Override
protected void onHandleIntent(@Nullable Intent intent) {

    //TODO check if the app is in foreground or not, we can use activity lifecyclecallbacks for this

    startForegroundServiceT();
    sendNotification(intent);
    stopSelf();
}


/***
 * you have to show the notification to the user when running foreground service
 * otherwise it will throw an exception
 */
private void startForegroundServiceT(){

    if (Build.VERSION.SDK_INT >= 26) {
        String CHANNEL_ID = "my_channel_01";
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                "Channel human readable title",
                NotificationManager.IMPORTANCE_DEFAULT);

        ((NotificationManager) 
   getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);

        Notification notification = new Notification.Builder(this, CHANNEL_ID)
                .setContentTitle("")
                .setContentText("").build();

        startForeground(1, notification);
    }
}

private void sendNotification(Intent intent){

    //Send notification
    //Use notification channle for android O+
}
}

start the foreground service in BroadcastReceiver.class

public class AlarmReceiver extends BroadcastReceiver {


@Override
public void onReceive(Context context, Intent intent) {


    Intent service = new Intent(context, NotificationService.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(service);
    } else {
        context.startService(service);
    }

}
}

And the setAlarms like this:

 public static void setAlarm(Context context, int requestCode, int hour, int minute){


    AlarmManager alarmManager =( AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context//same activity should be used when canceling the alarm
            , AlarmReceiver.class);
    intent.setAction("android.intent.action.NOTIFY");

    //setting FLAG_CANCEL_CURRENT makes some problems. and doest allow the cancelAlarm to work properly
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1001, intent, 0);

    Calendar time = getTime(hour, minute);

    //set Alarm for different API levels
    if (Build.VERSION.SDK_INT >= 23){
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent);
    }
    else{
        alarmManager.set(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent);
    }

Then you have to declare the receiver and the foregroundservice in the manifest.

       <receiver android:name=".AlarmReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.NOTIFY">

            </action>
        </intent-filter>
    </receiver>
    <service
        android:name=".NotificationService"
        android:enabled="true"
        android:exported="true"></service>

I hope this helps some one.

Keivan.k
  • 548
  • 6
  • 21
2

I also have an app that sets alarms.The solution is to use AlarmManager.setAlarmClock() on api >= 21. This is unaffected by doze afaik and has the added bonus of putting an alarm clock icon in the system tray.

Tyler Pfaff
  • 4,900
  • 9
  • 47
  • 62
2

Use AlarmManager for <5.0 devices, and JobScheduler for 5.0+ devices. I can't say for sure that JobScheduler will be unaffected by manufacturer shenanigans, but it would seem much less likely to me, given that Android is trying to move people away from AlarmManager and onto JobScheduler.

EDIT: Google has come out with a first-party solution to this problem called WorkManager. It abstracts multiple scheduling frameworks and uses the most appropriate one for the device.

Tom
  • 6,946
  • 2
  • 47
  • 63
  • 4
    Unfortunately, unlike the AlarmManager class, the timing isn't exact when using JobScheduler. In my app, timing should be exact :( – Sergio Viudes Jun 17 '16 at 10:19
  • I gave it a try and some optimizators (samsung at least) kill all pending tasks in JobScheduler when the screen goes off. So it's also broken. This happens on 5.0. After updating to 6.0 it works fine, I guess they fixed that. I couldn't test it with other manufacturers yet. – Sloy Sep 29 '16 at 07:52
  • 1
    For exact timing you cannot use a background service or scheduled service. You might try a foreground service, but this will create a persistent notification for the user (probably undesirable) and some phones have task killers built in which will automatically destroy the foreground service. WorkManager is the best solution but unfortunately will not give you exact timings. – Tom Aug 05 '18 at 21:22
0

most new phones nowadays are bundled with some kind of battery/power saving manager which do same thing you described. not counting duboosters and clean masters.

I think you need to put a disclaimer or faq in your app / play store listing stating that this app needs to be put into exception of your battery manager app in order to work properly.

eriuzo
  • 1,687
  • 1
  • 14
  • 16
  • There should be another way to do it... Users won't read the disclaimer. I can't think that Samsung phones don't allow apps to use AlarmManager... – Sergio Viudes Jan 18 '16 at 14:16
  • The alarms won't fire "on time", but they will eventuially – Gavriel Jan 19 '16 at 20:42
  • This is (sadly) the most helpful answer, I'd say. I wish there was a better solution, but hardware manufacturers are damaging the perfectly working vanilla Android. – caw Mar 04 '16 at 01:33
0

I don't think killing the app will prevent the alarm manager from waking your app.

Its only when you "force stop" or disable the app you don't receive call backs from alarm manager.

The root cause might be something else.

Also on M... setExactAndAllowWhileIdle does throttling...that is if u schedule an alarm every 2 mins it won't be triggered. ..There needs to be 15 mins window. .

rupesh jain
  • 3,410
  • 1
  • 14
  • 22
  • 1
    Thanks for your answer. But, if not, why the app is working perfectly when "battery optimization" is disabled in Smart Manager? – Sergio Viudes Jan 20 '16 at 08:02
  • are you running the app on rooted device..if yes the app manager can disable the app too.. – rupesh jain Jan 20 '16 at 19:12
  • No, I'm not running it on a rooted device. – Sergio Viudes Jan 20 '16 at 19:19
  • @rupeshjain "that is if u schedule an alarm every 2 mins it won't be triggered. ..There needs to be 15 mins window." this isn't completely true, it's a real problem if it was true. You can read exactly what the time limit for scheduling inside the Android Docs for setExactAndAllowWhileIdle method. There are restrictions on how frequently these alarms will go off for a particular application. Under normal system operation, it will not dispatch these alarms more than about every minute when in low-power idle modes this duration may be significantly longer 15 minutes. – eyadMhanna May 06 '19 at 13:03
0

i stopped using AlarmManager a while ago... a better and more stable alternative

  1. create a service
  2. register a BroadcastReceiver for BOOT_COMPLETED
  3. fire your service from the receiver
  4. start a new Handler inside your service that loop itself every X minutes (Android - running a method periodically using postDelayed() call)
  5. check if time to execute the task has come: now - execution time > 0 (How to find the duration of difference between two dates in java?)
  6. if so.. execute the task and stop the handler

yes.. it's a pain..but the job get done NO MATTER WHAT

Community
  • 1
  • 1
ymz
  • 6,602
  • 1
  • 20
  • 39
  • 4
    Thanks for your suggestion, but I would like to avoid that approach, because using AlarmManager won't consume RAM or any resource. And, if your app is killed, the service would stop, right? – Sergio Viudes Jan 20 '16 at 07:57
  • i didn't say that this approach is BOOLETPROOF, but at least it's consist over different api versions :) – ymz Jan 20 '16 at 18:27
  • 4
    To work reliably this solution would probably need also to use wake locks and that would eat massive amounts of battery. – Paweł Nadolski Aug 29 '16 at 13:09
  • i guess that you are right on this one.. the only question is: what would be worst - unreliable code or bad performance? anyhow, i personally think that there are **alternative ways for lock** that may be suitable in some cases (for instance: http://stackoverflow.com/questions/5346694/how-to-implement-a-lock-in-javascript) – ymz Aug 29 '16 at 19:29
  • but, the main mechanism - Broadcas reciever - is not called \ – Noor Hossain Dec 30 '20 at 02:16
0

Are you listening for BOOT_COMPLETED? You need to set alarms again when a device is rebooted.

Tyler Pfaff
  • 4,900
  • 9
  • 47
  • 62
  • Yes. As I said, alarms were working since 2012, until now. When device is rebooted I re-schedule alarms in BOOT_COMPLETED broadcast receiver. – Sergio Viudes Jan 20 '16 at 07:53
  • 1
    Requiring a reboot for your app to work again is not even half a solution – Tim Feb 24 '16 at 13:20
  • 1
    @TimCastelijns that's not at all what I'm saying. IF the device is rebooted, all alarms set with alarm manager must be set again. – Tyler Pfaff Feb 25 '16 at 20:33
  • @TylerPfaff yes but restart of the device is not related to the issue in this question – Tim Feb 25 '16 at 21:19
0

What version of Android are these devices running?

As of API 23, the OS itself will go into a low-power idle mode when it's been unused for a while, and in that mode alarms will not be delivered. There is a way for apps to explicitly say "I need this alarm to go off at this time regardless of battery usage," however; the new AlarmManager methods called setAndAllowWhileIdle() and setExactAndAllowWhileIdle().

From your description it sounds like this might not be the particular cause of your issues on certain OEMs' devices, but this is something that all developers using the Alarm Manager ought to be aware of.

Finally, many usages of the Alarm Manager are better addressed using the Job Scheduler's mechanisms. For backwards compatibility the Play Services "GCM Network Manager" is actually very close to the Job Scheduler in functionality -- it uses the Job Scheduler internally on newer versions of Android -- and is not necessarily about networking, despite the class's name.

ctate
  • 1,379
  • 10
  • 11
  • Samsung devices with Smart Manager are running Lollipop. I'm already using setExactAndAllowWhileIdle for Marshmallow devices. I'll take a look to JobScheduler and GCM. Anyway, I don't know if the problem is that alarm won't go off, or if that device is not awaken when alarm goes off. – Sergio Viudes Jan 21 '16 at 08:20
0

For Xiaomi you may need to enable AutoStart for your app. I am trying do to a list of Android modifications(usually from phone's manufacturer) that may effect a background process. If you have something new please add an answer here List of Android task killers

Community
  • 1
  • 1
Andrei Ciuca
  • 165
  • 1
  • 3
  • 17
0

We need to enable our app in autostart manager in app manager, some handsets like vivo v5,

In vivo v5, We can find out this menu in iManager-->App Manager--> Auto Start Manager. Enable our app here.

Then your alarm/ alarmmanager will trigger alarm if the app is killed or closed.

Aneesh NN
  • 113
  • 1
  • 9
0

I were looking for an answer and after several hours I found this:

https://stackoverflow.com/a/35220476/3174791

In resume is way to know if your app was killed by 'Protected apps' and this only works on Huawei devices. let me know if there is any solution for other devices (Samsung,Sony,Xiaomi, etc).

Community
  • 1
  • 1
Edgar
  • 43
  • 1
  • 6