Search code examples
javaandroidalarmmanager

Alarm setExact() stops executing


Currently I have a problem with the alarmManager on Android.

When i start my app, i call the method "startReminderAlarm". Now the alarm is triggered on the upcoming hour and minute 1. The alarm triggers the AppReceiver. The AppReceiver starts the alarm again for the next hour and minute 1 and after that does some code in the "doInBackground" method.

With this pattern the AppReceiver should be called exactly on each hour ( minute 1 ). But it seems to work for only a few intervals. I started the alarm yesterday and checked it today with adb shell dumpsys alarm. The alarm was not mentioned on the output ?

I have the following situation :

  1. I can't reproduce this problem in the emulator
  2. When i change the alarm to trigger each minute, it seems to work.

My Questions are :

  1. Any problems with my code ?
  2. Is there a logfile where i can see Exception that may occure during the background execution ?

My Code :

// Class AlarmStarter
public static void startReminderAlarm(Context context){
    Calendar calendar = Calendar.getInstance();
    calendar.setTimeInMillis(System.currentTimeMillis());
    calendar.add(Calendar.HOUR, 1);
    calendar.set(Calendar.MINUTE, 1);
    calendar.set(Calendar.SECOND, 0);
    Log.i(TAG,"Start reminder alarm on " +sdf.format(new Date(calendar.getTimeInMillis())));

    AlarmManager alarmMgr = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
    Intent reminderIntent = new Intent(context, AppReceiver.class);
    PendingIntent reminderPendingIntent = PendingIntent.getBroadcast(context, 0, reminderIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    alarmMgr.setExact(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), reminderPendingIntent);
}

// Class AppReceiver
public class AppReceiver extends BroadcastReceiver {

    private static final String TAG = "AppReceiver";

    @Override
    public void onReceive(Context context, Intent intent) {
        AlarmStarter.startReminderAlarm(context);
        new notifyAsyncTask().execute(context);
    }

    private static class notifyAsyncTask extends AsyncTask<Context, Void, Void> {

        private String CHANNEL_ID = "1a2b3c4d";

        private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

        @Override
        protected Void doInBackground(Context... params) {
            // DO SOME CODE
        }
    }
}

Solution

  • There was no problem at all with the code. The problem was the power management software of my Huawei smartphone.

    As I found out, some Android versions from several companys ( Huawei, Samsung, Xiaomi ... ) have stricter powermanagement rules.

    If an app is forced quit by the user, the alarm will work for a few more hours. Then comes the powermenagement software from the device and kills every background service for apps that are not running.

    That's why it was always working in the emulator and not on my smartphone.

    Solution for my situation :

    1. Deactivate the powermanagement for my app
    2. Start the alarm again

    IF SOMEONE ELSE RUNS INTO THIS PROBLEM, CHECK YOUR POWERMANAGEMENT SETTING!

    Some helpfull adb commands in this case :

    Finding out if your app is stopped. The value should be false. That means the background tasks a running and it was not killed by the powermanagement software.

    adb shell dumpsys package $packageName |grep stopped
    

    Display the running alarms for your package and some additional information like how much time passed since the last run:

    adb shell dumpsys alarm |grep -C4 $packageName