0

I'm creating an alarm and using the WakeLock to wake the phone when asleep.

I use this code for the wakelock in my Activity:

public void onCreate(Bundle savedInstateState) {
    super.onCreate(savedInstateState);
    PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
    mWakeLock = pm.newWakeLock(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON | PowerManager.ACQUIRE_CAUSES_WAKEUP, "My Wake Log");
    mWakeLock.acquire();
    this.requestWindowFeature(Window.FEATURE_NO_TITLE);
    this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN |
                    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                    WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON,
            WindowManager.LayoutParams.FLAG_FULLSCREEN |
                    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                    WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    setContentView(R.layout.activity_screen);
}

But when time is met, my app crashes with this log cat error:

java.lang.IllegalArgumentException: Must specify a valid wake lock level.

I alreade added permission to AndroidManifest:

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

I thought i already specify the wakelock level. What can I do to fix this? please help me. Thank you

stanley santoso
  • 343
  • 1
  • 6
  • 19
  • on what version of android are you testing it ? – Blackbelt Jul 16 '15 at 18:50
  • I followed an answer here : http://stackoverflow.com/questions/23045883/powermanager-wakelock-on-android-devices using PROXIMITY_WAKE_LOCK, an int and it works. I have no idea what it is and why it works. and I don't know if this is the right way of doing it. – stanley santoso Jul 16 '15 at 19:07

2 Answers2

4

WindowManager.LaoutParams.FLAG_KEEP_SCREEN_ON is not a valid flag/level for PowerManager.newWakeLock(). You most likely intended it to be:

PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP.

Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33
  • PowerManager.FULL_WAKE_LOCK has been deprecated and the new one is WindowManager.LaoutParams.FLAG_KEEP_SCREEN_ON. – stanley santoso Jul 16 '15 at 19:08
  • I followed an answer here : http://stackoverflow.com/questions/23045883/powermanager-wakelock-on-android-devices using PROXIMITY_WAKE_LOCK, an int and it works. I have no idea what it is and why it works. and I don't know if this is the right way of doing it. – stanley santoso Jul 16 '15 at 19:12
  • 1
    NO. It is considered deprecated as of API17 (really just not preferred), but `WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON` is not a *replacement* to be used in `newWakeLock()`. It's a setting for your `Activity`'s window parameters. – Larry Schiefer Jul 16 '15 at 19:14
  • The use of `PROXIMITY_WAKE_LOCK` in that other post is using a hard-coded value which is the equivalent of `PowerManager. PROXIMITY_SCREEN_OFF_WAKE_LOCK`. Note that it will not prevent the device from going into low power. – Larry Schiefer Jul 16 '15 at 19:17
  • what will usually happen when device is going into low power when you don't hard-code the value? the wake lock doesn't work? I tried the PowerManager.FULL_WAKE_LOCK and it works. But everyone is telling to use the WindowManager.LaoutParams.FLAG_KEEP_SCREEN_ON. what is this weird confusion. Everyone saying it is deprecated. – stanley santoso Jul 16 '15 at 19:20
  • `FULL_WAKE_LOCK` is marked as deprecated simply because you can achieve the same behavior (preventing low power and screen dim) using the window parameters *and* using wakelocks is potentially dangerous because of power drain. But they are *window parameters* to be applied via `Window.setFlags()` and only usable by an `Activity`. If you have a `Service` which needs the device to stay on, it will not work. The hard-coded value works because it is exactly the same as the definition of `PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK`, so it is really just a hack. – Larry Schiefer Jul 16 '15 at 19:25
  • Thank you very much. now the screen is on forever. I heard there is a simple thing I can do to make the alarm turned off after like 1 minute or something. can you share that with me. thank you – stanley santoso Jul 16 '15 at 19:42
  • I'm not really sure what you mean by alarm in this case. But, all you need to do is release the wakelock when you have completed whatever you need and the system will automatically go to a low power state. If you are working with `AlarmManager` and truly using alarms, you may find this article and sample code helpful: http://po.st/7UpipA – Larry Schiefer Jul 16 '15 at 19:47
  • So I'm creating an alarm. when the time is met, wakelock activates, and the activity shows up. I need a way so the activity will collapse by itself after 1 minute if ignored. Other wise the wakelock will keep functioning. – stanley santoso Jul 16 '15 at 19:51
  • Have a look at that article, it'll walk you through the details. Essentially: alarm triggers `BroadcastReceiver` which takes `WakeLock`, BR triggers `Activity` (or `Service`) which then releases the `WakeLock` when it is done processing whatever it needs (or in your case, times out.) Once the wakelock has been released, the system will go to lower power as usual. – Larry Schiefer Jul 16 '15 at 19:53
0

The correct solution is as follows: use ACQUIRE_CAUSES_WAKEUP in conjunction with PARTIAL_WAKE_LOCK to wake the device up. Then use WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON to keep the screen on. PARTIAL_WAKE_LOCK has not been deprecated and is still valid to use. Here is some sample code where my service wakes the device up, starts the appropriate activity, and uses a wakelock to keep the device running until the activity has had time to set the necessary flags to keep the device and screen on.

         // start the activity, wake up the screen if required. This would typically
        // be done in an onReceive() method, or in my case it's when a Bluetooth device has been connected.

        PowerManager pm = (PowerManager) getApplicationContext().getSystemService(Context.POWER_SERVICE);
        final PowerManager.WakeLock wakeLock = pm.newWakeLock((PowerManager.PARTIAL_WAKE_LOCK|PowerManager.ACQUIRE_CAUSES_WAKEUP), "BlueMaxService");
        wakeLock.acquire();
        Intent intent = new Intent(this, EmaxActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
        handler.postDelayed(new Runnable() {
            @Override
            public void run() {
                wakeLock.release();
            }
        }, 10000L);

And in the activity, I set various flags to turn the screen on, dismiss the lock screen, and keep the screen on. These flags must be set very early so the best place is in onAttachedToWindow()

        @Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON |
        WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
        WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
        WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
}

If the activity is already started it will need to be recreated so these flags can be set. This can be done by calling recreate() in onNewIntent()

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    recreate();
}
Clyde
  • 7,389
  • 5
  • 31
  • 57