setAlarmClock BroadcastReceiver does not reach onResume sometimes

187 Views Asked by At

I have created an alarm clock app using setAlarmClock. For some people the alarm does not start properly. I know you must disable all kind of energy saving modes on devices otherwise it could by that the alarm does not fire. But I have some rare cases where the alarm starts on time but it has time gaps until it finishes alls steps of onCreate and onPostCreate of my activity.

It could be related with the fact that my wakelock is activated very late. When the Broadcastreceiver is called with an alarm event it starts my main activity. The activity starts a thread which must run at least once. It checks if the alarm should fire. If yes then it creates a wakelock to keep the device awake.

I could try to create the wakelock ealier but I have seen log files where onResume has not been even called, only onStart. There is a gap of 5 minutes between onStart and onResume. So there is no chance to make it early enough.

Is there something wrong with my alarm and wakelock concept? Is it possible/wise to start the wakelock in the BroadcastReceiver and stop it in the Activity?

public class AlarmManagement extends BroadcastReceiver implements Serializable
{
    @Override
    public void onReceive (Context context, Intent intent)
    {
        Intent i = new Intent(context, FullscreenActivity.class);
        i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
        context.startActivity(i);
    }

    public void scheduleSystemAlarmApi21(Context context,long alarmTime, PendingIntent pi) {
        AlarmManager am =( AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent i2=new Intent(context, FullscreenActivity.class);
        PendingIntent pi2=PendingIntent.getActivity(context, 0, i2, 0);
        am.setAlarmClock(new AlarmManager.AlarmClockInfo(alarmTime,pi2),pi);
    }

    public void scheduleSystemAlarm(Context context,int id, long alarmTime) {
        Intent i = new Intent(context, AlarmManagement.class);
        PendingIntent pi = PendingIntent.getBroadcast(context, id, i, 0);

        scheduleSystemAlarmApi21(context,alarmTime,pi);
    }
}

public class FullscreenActivity extends AppCompatActivity {
    Thread thread;

    @Override
    protected void onResume() {
        super.onResume();
        if (threadStopped)
            alarmServiceThread();
    }

    void alarmServiceThread() {
        thread = new Thread() {
            @Override
            public void run() {
            ...
                if (needToStartWakeup(currentTime))
                     startWakeup();
            ...
            }
        }
        thread.start(); 
    }

    PowerManager powerManager;
    PowerManager.WakeLock wake;

    public void startWakeup() {
        powerManager = ((PowerManager) getSystemService(Context.POWER_SERVICE));
        int levelAndFlags=PowerManager.ACQUIRE_CAUSES_WAKEUP;
        levelAndFlags |= PowerManager.SCREEN_BRIGHT_WAKE_LOCK;
        wake = powerManager.newWakeLock( levelAndFlags , WAKE_LOCK_TAG);
        wake.acquire();
    }   
}
1

There are 1 best solutions below

4
On

You are trying to start an activity from the receiver in the onReceive method, that is problematic if your app is in the background.

Please read the following documentation on the subject:
https://developer.android.com/guide/components/activities/background-starts

You should present a notification for the user and open the activity on user action.