android AlarmManager not waking phone up
Asked Answered
O

3

28

I want an activity to be displayed at a certain time. For this, I am using AlarmManager. It works fine when the device is awake, but it doesn't wake it up if it's asleep.

My code for setting the alarm:

Calendar alarmTime = Calendar.getInstance();
alarmTime.set(Calendar.HOUR_OF_DAY, alarm.hour);
alarmTime.set(Calendar.MINUTE, alarm.minute);
alarmTime.set(Calendar.SECOND, 0);

if (alarmTime.before(now))
    alarmTime.add(Calendar.DAY_OF_MONTH, 1);

Intent intent = new Intent(ctxt, AlarmReceiver.class);
intent.putExtra("alarm", alarm);
PendingIntent sender = PendingIntent.getBroadcast(ctxt, alarm.id, intent, PendingIntent.FLAG_UPDATE_CURRENT);
alarmManager.set(AlarmManager.RTC_WAKEUP, alarmTime.getTimeInMillis(), sender);

My broadcast receiver:

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

Bundle bundle = intent.getExtras();
final Alarm alarm = (Alarm) bundle.getSerializable("alarm");

Intent newIntent;
if (alarm.type.equals("regular")) {
    newIntent = new Intent(context, RegularAlarmActivity.class);
} else if (alarm.type.equals("password")) {
    newIntent = new Intent(context, PasswordAlarmActivity.class);
} else if (alarm.type.equals("movement")) {
    newIntent = new Intent(context, MovementAlarmActivity.class);
} else {
    throw new Exception("Unknown alarm type");
}
    newIntent.putExtra("alarm", alarm);
    newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    context.startActivity(newIntent);

} catch (Exception e) {
    Toast.makeText(context, "There was an error somewhere, but we still received an alarm", Toast.LENGTH_SHORT).show();
    Log.e("AlarmReceiver", Log.getStackTraceString(e));
}
}

This code doesn't wake the device on. However, when I turn it back again, they are displayed. I need to make them turn the screen on. Can you help me with this problem?

Oakes answered 28/7, 2011 at 19:43 Comment(1)
Go to the Activity which you want to start in onReceive(). Paste this in onCreate() of that Activity final Window win= getWindow(); win.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD); win.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);Gustav
G
58

I had a similar problem and the solution was to use WakeLocker. That should be done (preferably as the 1st thing in the receiver), or the device will wake up when the alarm is received, but will fall asleep again before context.startActivity(newIntent); is called. (I have also observed behavior when that does not happen, so it seems to be a bit arbitrary) So the easy and quick answer: Make a new class called WakeLocker with this source code:

package mypackage.test;

import android.content.Context;
import android.os.PowerManager;

public abstract class WakeLocker {
    private static PowerManager.WakeLock wakeLock;

    public static void acquire(Context ctx) {
        if (wakeLock != null) wakeLock.release();

        PowerManager pm = (PowerManager) ctx.getSystemService(Context.POWER_SERVICE);
        wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
                PowerManager.ACQUIRE_CAUSES_WAKEUP |
                PowerManager.ON_AFTER_RELEASE, MainActivity.APP_TAG);
        wakeLock.acquire();
    }

    public static void release() {
        if (wakeLock != null) wakeLock.release(); wakeLock = null;
    }
}

and in your receiver call WakeLocker.acquire(context); as the 1st thing. Extra: it would also be neat to call WakeLocker.release(); once your alarm has done its thing.

Gies answered 28/7, 2011 at 20:35 Comment(5)
Thank you very much. Now, the phone finally wakes up at the specified time. I also like a lot the static approach of the WakeLocker class.Oakes
requires permission <uses-permission android:name="android.permission.WAKE_LOCK" /> developer.android.com/reference/android/os/PowerManager.htmlReahard
Thank you, that's great. But it still didn't work until I found that my phone (Asus Zenfone Selfie) requires me to explicitly allow the app to be waken up.Eula
the alarm even does not call its receiver!!Raspings
would duplicate calls to acquire do any harm as your methods are static? lets say you acquire multiple times but only release 1 timeFestal
N
30

Most likely, the alarm is waking up the device. However, AlarmManager broadcasts won't turn the screen on, and the device may well fall back asleep before your activity starts up.

You will need to acquire a WakeLock in onReceive() before calling startActivity(), and release that WakeLock after the user responds to your activity.

Nylon answered 28/7, 2011 at 20:31 Comment(5)
have you tested this? The screen turns on as well without the need to acquire a WakeLockFestal
@2cupsOfTech: "have you tested this?" -- yes. "The screen turns on as well without the need to acquire a WakeLock" -- AlarmManager broadcasts do not turn on the screen. Without a WakeLock (e.g., using getService() as a PendingIntent, then grabbing a WakeLock in the service) is unreliable. It will work sometimes and not others. This is why I released the WakefulIntentService and why Google followed that up with the WakefulBroadcastReceiver.Nylon
@Nylon a clarification I'm talking in reference to starting an activity (not service) so perhaps your results are only applicable for service?Festal
@2cupsOfTech: Starting an activity directly from AlarmManager by way of setAlarmClock() might work, and I have no idea what behavior to expect there. Starting an activity directly from AlarmManager via other methods (e.g., set()) is not advisable. From the beginning, the only (undocumented) guarantee we had with AlarmManager was that if you used a broadcast PendingIntent, AlarmManager would keep the device awake long enough for onReceive() to process. Anything else, all bets are off. If they have modified their undocumented guarantee, I am not aware of it.Nylon
@Nylon I did a test with starting activity, I would say the results are unreliable at-least with deep doze modeFestal
W
8

For Services (maybe works for activity as well), extend your AlarmReceiver from WakefulBroadcastReceiver, it acquires WAKE_LOCK for you while intent is being processed.

WakefulBroadcastReceiver docs - https://developer.android.com/reference/android/support/v4/content/WakefulBroadcastReceiver.html

Keeping device awake guide - https://developer.android.com/training/scheduling/wakelock.html

Womanly answered 20/9, 2014 at 20:31 Comment(1)
deprecated on latest releaseTiedeman

© 2022 - 2024 — McMap. All rights reserved.