Android O - FLAG_SHOW_WHEN_LOCKED is deprecated
Asked Answered
C

6

21

I'm targetting my application to Android O. In my application I have a job service that shows a window over all other applications, so when it triggered it needs to show this window even when the screen is turned off & unlocked and turn it on. I've achieved this behaviour in preior Android versions, but in Android O it doesn't work as I expected.

I've read that I need to use the flag TYPE_APPLICATION_OVERLAY and added also the permission <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>in the manifest file.

So it works fine when the screen is on, but when the screen is off I've noticed that it doesn't turn the screen on, and when I turned the screen I saw that the window was created on top of other applications.

So my question is since the flags FLAG_TURN_SCREEN_ON and FLAG_SHOW_WHEN_LOCKED are deprecated in Android API 27, what are the alternatives way of doing that?

this is my current code:

private void showView()
{
    if (!wakeLockAcquired)
    {
        wakeLock.acquire();
        wakeLockAquired = true;
    }

    windowManager = (WindowManager)context.getSystemService(WINDOW_SERVICE);

    final WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams(
            ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, 0, 0,
            WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
            ,
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON ,
            PixelFormat.RGBA_8888);

    RelativeLayout layout = buildView();
    windowManager.addView(layout, layoutParams);
    windowManager.updateViewLayout(layout, layoutParams);
}

Notes:

  • buildView is a function that returns a relativeLayout, in this function I'm adding the content dynamically (TextView, ImageView, etc...).
  • wakeLockAcquired is a boolean member, and it sets to false when the view is destroyed.
Cristalcristate answered 16/1, 2018 at 8:53 Comment(0)
C
16

OK so I've managed to solved it with some workaround and the help from the answer of @Umair.

As I said I'm displaying a view that was created in a background service using the WindowManager and with the code I've added to my question above, the view is displayed above all the other applications but not turning the screen on when Android version is Android 8.

The methods that now replaceing the Flags: FLAG_SHOW_WHEN_LOCKED FLAG_TURN_SCREEN_ON are visible to activities and not for services or for the WindowManager, and casting the context to Activity is not a good idea and will not help you :)

So What I did for now (temporary solution) is to create a transparent activity and when I'm calling to showView() method from my background service, I'm also starting the transparent activity.

In the activity - inside the onCreate method, I'm calling to the methods:

setShowWhenLocked(true) 
setTurnScreenOn(true)

and when the view is destroyed, the activity will also get destroyed with the help of broadcast receiver :) so the screen is now turned on and the view is above all the other applications.

I know that you can tell me that I can move my code that inside my service into the new activity.

The reason I did it in that way:

I'm using speech recognizer.. and when I coded it in the activity, things didn't work. I mean when the screen is locked with pattern, the activity goes to pause state and I can't get the results. so the pattern dismissed my activity..

So I decided to create a view using the window manager and it worked fine until now - when Google (Android team) decided to deprecate these flags. So this is my solution for now.. and I hope that someone will find a better solution for this problem.

Cristalcristate answered 16/1, 2018 at 12:12 Comment(0)
L
29

KeyguardManager turn on screen if attr turnScreenOn is true, so order of methods and call requestDismissKeyguard is necessary. I use this code for activity, hope it'll help:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
        setShowWhenLocked(true)
        setTurnScreenOn(true)
        val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
        keyguardManager.requestDismissKeyguard(this, null)
    } else {
        this.window.addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
    }
}
Latreese answered 3/5, 2018 at 16:22 Comment(5)
Be careful, WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD was deprecated in API 26 not 27.Carrizales
what is window? under which class?Doge
this is Activity instanceLatreese
For me requestDismissKeyguard still keeps PIN input keyboard.Twelve
Same as above comment, this does not work on PIN lock screens (Tested on Android 11)Nolie
C
16

OK so I've managed to solved it with some workaround and the help from the answer of @Umair.

As I said I'm displaying a view that was created in a background service using the WindowManager and with the code I've added to my question above, the view is displayed above all the other applications but not turning the screen on when Android version is Android 8.

The methods that now replaceing the Flags: FLAG_SHOW_WHEN_LOCKED FLAG_TURN_SCREEN_ON are visible to activities and not for services or for the WindowManager, and casting the context to Activity is not a good idea and will not help you :)

So What I did for now (temporary solution) is to create a transparent activity and when I'm calling to showView() method from my background service, I'm also starting the transparent activity.

In the activity - inside the onCreate method, I'm calling to the methods:

setShowWhenLocked(true) 
setTurnScreenOn(true)

and when the view is destroyed, the activity will also get destroyed with the help of broadcast receiver :) so the screen is now turned on and the view is above all the other applications.

I know that you can tell me that I can move my code that inside my service into the new activity.

The reason I did it in that way:

I'm using speech recognizer.. and when I coded it in the activity, things didn't work. I mean when the screen is locked with pattern, the activity goes to pause state and I can't get the results. so the pattern dismissed my activity..

So I decided to create a view using the window manager and it worked fine until now - when Google (Android team) decided to deprecate these flags. So this is my solution for now.. and I hope that someone will find a better solution for this problem.

Cristalcristate answered 16/1, 2018 at 12:12 Comment(0)
S
8

So according to android documentation these methods were deprecated so you need to use showWhenLocked or setShowWhenLocked(boolean) instead.

FLAG_TURN_SCREEN_ON

int FLAG_TURN_SCREEN_ON This constant was deprecated in API level 27. Use turnScreenOn or setTurnScreenOn(boolean) instead to prevent an unintentional double life-cycle event.

Window flag: when set as a window is being added or made visible, once the window has been shown then the system will poke the power manager's user activity (as if the user had woken up the device) to turn the screen on.

And FLAG_SHOW_WHEN_LOCKED

int FLAG_SHOW_WHEN_LOCKED This constant was deprecated in API level 27. Use showWhenLocked or setShowWhenLocked(boolean) instead to prevent an unintentional double life-cycle event.

Window flag: special flag to let windows be shown when the screen is locked. This will let application windows take precedence over key guard or any other lock screens. Can be used with FLAG_KEEP_SCREEN_ON to turn screen on and display windows directly before showing the key guard window. Can be used with FLAG_DISMISS_KEYGUARD to automatically fully dismisss non-secure keyguards. This flag only applies to the top-most full-screen window.

So according to documentation the reason to deprecate these methods was to avoid an unintentional double life-cycle event. You can read more about them here. https://developer.android.com/reference/android/view/WindowManager.LayoutParams.html

Supportive answered 16/1, 2018 at 9:0 Comment(4)
Thanks I've read it too.. but it seems that these methods are visible only on activity.. I'm looking for solution when you create a view inside a background service.. +1 for your answer :)Cristalcristate
FLAG_TURN_SCREEN_ON also deprecatedYapon
@Yapon if you read the detail it is written that it was deprecated in API 27 :)Supportive
Does anyone able to find how to use this service in background service @CristalcristateGeomancer
E
2

Do you experience that

setShowWhenLocked(true)
setTurnScreenOn(true)

do not turn screen on any longer in Android 9? Or is it just my case?

Ethno answered 18/2, 2019 at 21:44 Comment(2)
@Cristalcristate I do not need to use your workaround because I want to turn on Activity. My issue is that it used to work on Android 8 but now stopped in Android 9. Is it just my case or you experenece the same?Ethno
sorry for the delay with the response, actually I didn't try on Android 9. do you want to turn the screen on and show the activity? do you have any keyguard set on your device? like pin code or pattern?Cristalcristate
H
1

Up to date Kotlin code with if-else for handling deprecation:

if (Build.VERSION.SDK_INT > Build.VERSION_CODES.O) {
    val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
    keyguardManager.requestDismissKeyguard(this, null)
    setShowWhenLocked(true)
} else {
    window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
            WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD)
}

More explanation can be found here here.

Holzman answered 30/7, 2022 at 18:46 Comment(0)
E
0

as Dmitry Ognyov posted above - besides these: setShowWhenLocked(true); setTurnScreenOn(true); you need to dismiss the keyguard too keyguardManager.requestDismissKeyguard(...

Ens answered 4/5, 2019 at 1:53 Comment(1)
This does not appear to be enough for Android 11Nolie

© 2022 - 2024 — McMap. All rights reserved.