FLAG_TURN_SCREEN_ON does not always work
Asked Answered
C

6

12

i start an activity from a BroadcastReceiver, which is triggered by an alaram (RTC_WAKEUP type). in onCreate of that activity i add these flags

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
    WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
    WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON        
);

problem is that sometimes (approximately 10% cases) the screen does not turn on. the alarm is correctly triggered (i here the sound of a notification, which is also fired in the receiver's onReceive(). then, if i hit the phone's power button, the screen turns on, showing my activity, and instantly turns off. after that, the power button works good. this happen on android 2.3.7 and here is the onReceive() method

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

    Bundle extras = intent.getExtras();
    final int id = extras.getInt("timer_id");

    Intent activityIntent = new Intent(m_Context, MyActivity.class);
    activityIntent.putExtra("timer_id", id);
    activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    m_Context.startActivity(activityIntent);

    // and now load the alarm sound and play it for the desired time
    showFinishedNotification();
}

i would like to avoid using PowerManager, as it needs a permission, and the flags are the prefered way.

what could be a problem? logcat does not show any problems...

Calla answered 31/3, 2012 at 17:30 Comment(2)
Did you manage to circumvent the problem ?Manage
@Manage The only solution was to use a WAKE_LOCK permission and use a static lock. There is a new WakefulBroadcastReceiver in the support library, which handles the partial wake lock. It needs the permission of cource.Calla
I
12

From my experience and research on this topic:

  • The FLAG_TURN_SCREEN_ON can not be used to turn the screen ON and OFF multiple times in your application.

  • The FLAG_TURN_SCREEN_ON can only be used once to turn the screen ON when creating a new activity (preferably in the onCreate() method) or when re-creating a view.

Now, you can get around this limitation by:

  • Launching a new activity and setting the flag there, then finishing the activity (by the user or programmatically) to let the screen turn off.
  • Setting the params.screenBrightness parameters to as "dim" as possible, sometimes the screen "appears OFF". You can then increase the brightness to "turn ON" the screen. However, this often does not work as the screen is still dim but visible, also this doesn't work if the user locks the phone.
  • Using the Power Manager Wakelock (this still works but Android deprecated this functionality, so they are discouraging the use of this technique). However, as far as I can tell this is the only way I can get my application to turn the screen ON/OFF reliably.

None of these are ideal (in fact they feel like hacks) but just use the one that better suits your application needs.

You can read more here:

Idette answered 16/5, 2016 at 20:9 Comment(1)
Hi, what will happen if we use FLAG_TURN_SCREEN_ON multiple times? will it display a black screen for the acitvity?Denning
W
8

I'm a bit late to the party here but I've been fighting this for a while now and finally found a way to get the screen to unlock every time. I add the flags in the onAttachToWindow() event. Typically I do this from a WakefulBroadcastReceiver so the screen transitions smoothly but that's use-case dependent.

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

private void clearFlags() {
    //Don't forget to clear the flags at some point in time.
    getWindow().clearFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                        | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                        | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}
Wigging answered 30/4, 2015 at 2:55 Comment(0)
N
4

problem is that sometimes (approximately 10% cases) the screen does not turn on

If I had to guess, the device is falling back asleep before the activity starts up. Once onReceive() returns, the device can and will fall back asleep, and it will be some time after onReceive() returns before your activity will start.

This same scenario, but replacing startActivity() with startService(), is why I had to write WakefulIntentService, which uses a WakeLock to ensure that the device stays awake long enough for it to do its work, then releases the WakeLock.

Nisbet answered 31/3, 2012 at 17:35 Comment(6)
the device should be awake, because the notification's sound is playing. ...could i put the receiver to sleep with Thread.sleep(...) and the device will not fall asleep? or with a delayed message (new Handler()).postDelayed(...))?Calla
@shelll: "could i put the receiver to sleep with Thread.sleep(...) and the device will not fall asleep?" -- no. First, that will prevent your activity from starting until after sleep() completes, because onReceive() is called on the main application thread. Second, Android will kill off your BroadcastReceiver if you tie up the main application thread too long. "could i put the receiver to sleep with Thread.sleep(...) and the device will not fall asleep?" -- that will not stop the device from falling asleep. It would increase the frequency of this problem occurring by quite a bit.Nisbet
OK, so no sleep(), but how could I hear the notification sound (I repeat it until it is manually cancelled), but the screen does not turn on?Calla
@shelll: Beats me. I suggest you add an appropriate WakeLock and see if your problem goes away. If it does, you have a decision to make. If it does not, then there is some other problem that you are encountering.Nisbet
how can I correctly acquire a lock in a BroadcastReceiver and release it in my activity? is your WakefulIntentService a solution for my case?Calla
@shelll: No, WakefulIntentService is not suitable for your needs. However, you can examine it to see how I handle acquiring a static WakeLock in a BroadcastReceiver and releasing that static WakeLock in a service. You would do the same thing, except you would release it in your activity, after your `addFlags() call.Nisbet
R
4

Late answer But it will help for anyone.

For higher and lower versions use following code (it working fine)

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
        setShowWhenLocked(true);
        setTurnScreenOn(true);
        KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        keyguardManager.requestDismissKeyguard(this, null);
    }
    else{
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    }

 setContentView(R.layout.activity_incoming_call);
}

Important Note: you should place before setContentView()

Rattrap answered 1/4, 2020 at 6:13 Comment(0)
A
3

I use these three methods simultaneously which works at almost any device.

public static void turnScreenOnThroughKeyguard(@NonNull Activity activity) {
    userPowerManagerWakeup(activity);
    useWindowFlags(activity);
    useActivityScreenMethods(activity);
}

private static void useActivityScreenMethods(@NonNull Activity activity) {
    if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) {
        try {
            activity.setTurnScreenOn(true);
            activity.setShowWhenLocked(true);
        } catch (NoSuchMethodError e) {
            Log.e(e, "Enable setTurnScreenOn and setShowWhenLocked is not present on device!");
        }
    }
}

private static void useWindowFlags(@NonNull Activity activity) {
    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
            | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

private static void userPowerManagerWakeup(@NonNull Activity activity) {
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    WakeLock wakelock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, tag);
    wakeLock.acquire(TimeUnit.SECONDS.toMillis(5));
}
Anticoagulant answered 19/9, 2018 at 10:12 Comment(0)
R
1

Targeting sdk 30

Following code enables to open Activity from PendingIntent, even if application

  • was cleared from recent apps
  • and screen is dimmed
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(view)
        turnOnScreen()
    }

    private fun turnOnScreen() {
        window.addFlags(
            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
                    WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
        )
        setTurnScreenOn(true)
        setShowWhenLocked(true)

        val keyguardManager = getSystemService(KEYGUARD_SERVICE) as KeyguardManager
        keyguardManager.requestDismissKeyguard(this, null)
    }
Rhineland answered 11/1, 2021 at 20:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.