Adobe-Runtime-Support icon indicating copy to clipboard operation
Adobe-Runtime-Support copied to clipboard

Screen.safeArea is incorrect on Android 35

Open marchbold opened this issue 4 months ago • 9 comments

Problem Description

Android 15 (API 35) enforces edge-to-edge rendering on apps which means your application is supposed to account for edge insets etc. https://developer.android.com/about/versions/15/behavior-changes-15#ux

However currently Screen.safeArea only returns the cutouts, not the area that the system bars are contained in.

Steps to Reproduce

var safeArea:Rectangle = Screen.mainScreen.safeArea;

Here safeArea appears to return the Android values of View.getRootWindowInsets().getDisplayCutout() which doesn't account for the system bars that are now rendered over the top of the content.

We need to use the newer approach using getInsets eg

View.getRootWindowInsets().getInsets( WindowInsets.Type.systemBars() )

Known Workarounds

You can use the Application ANE, I've updated this to return these values.

marchbold avatar Aug 08 '25 02:08 marchbold

Sorry, for my GalaxyS23 it appears that 51.2.2.3 in fact, correctly handled safe area, and the newest update 51.2.2.4 does not.

Please, check these 2 screenshots where I post to console the screen dimensions and safe area

Image This is for the game build with 51.2.2.3. There was one inconsistency with that version: the console shows 51.2.2.2, while I double-checked that the AIR SDK used for it was 51.2.2.3 Image This one for 51.2.2.4

The Galaxy S23 phone has a camera in the middle of the top short side of the screen. And AIR 51.2.2.3 correctly defined that safeArea.y = 75 While the newest 51.2.2.4 defines safeArea.y = 0

So, for the new version this should be taken into account.

The game (built with 51.2.2.3) is here: https://play.google.com/store/apps/details?id=com.airapport.idletowerbuilder

GeneralVimes avatar Sep 07 '25 12:09 GeneralVimes

About the width and x of the safe area: in 51.2.2.4 Safe area correctly takes into account curved edges of GalaxyS23 and provides a safe area of width 1005 instead of 1080. But as both long sides of S23 are curved, shouldn't is x be something around 36, too?

To, summarize, we have 51.2.2.3: (x=0, y=75, w=1080, h=2241) 51.2.2.4: (x=0, y=0, w=1005, h=2316)

So, safe area in 51.2.2.5 should be: (x=36, y=75, w=1005, h=2241)

GeneralVimes avatar Sep 07 '25 18:09 GeneralVimes

Is your app in landscape there? Seems like the width and height are swapped, and the difference in the width is probably the navigation controls at the bottom of the screen?

Not sure how AIR is going to address this but with Android now, the "safe area" does include the area around cutouts from camera's etc, the safe area is more about edge ui components (like status and navigation bars + corner curves). The information for these cutouts is retrieved separately from the "safe area".

In my extension you get these cutouts via the bounding rectangle info:

https://docs.airnativeextensions.com/docs/application/display/cutouts#bounding-rectangles

marchbold avatar Sep 08 '25 02:09 marchbold

No, it is in portrait mode, width is smaller than height, I'm holding the phone vertically.

The game takes all the screen, just as S23 has rounded long sides of the screen, smaller width is logical (but looks like it should have a shift from 0

Thank you, I thought that cutouts should be accounted into the safe area. I'll take a look

GeneralVimes avatar Sep 08 '25 05:09 GeneralVimes

I just updated to targetSdk 35 and my app's header on real devices are almost doubled but works fine on simulators. (I am using below code @marchbold) which has been working great for iOS for years.

if(Application.service.display.willCutoutAffectView)
{
    var cutout:DisplayCutout = Application.service.display.getDisplayCutout();

    _runtime.topMargin = cutout.safeInsetTop / _scaleFactor;
    _runtime.bottomMargin = cutout.safeInsetBottom / _scaleFactor;
}

After searching and trying all different things, I am giving up and am opting out of edge-to-edge by adding this to my styles.xml

<item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>

I'll worry about this edge-to-edge thing next year when we are forced to increase targetSdk to 36 :D

myflashlab avatar Sep 08 '25 21:09 myflashlab

@myflashlab Did you update the Application extension? There were some updates for API 35 around the insets.

marchbold avatar Sep 08 '25 23:09 marchbold

Yes, I updated to 8.1.0

myflashlab avatar Sep 09 '25 08:09 myflashlab

The release notes say that it has been fixed.

The Android APIs for providing cut-out information had been updated to no longer include banner areas, so a new Android API has been used to check for the ‘unsafe’ area of an application which takes into account both the rounded corners and notch cut-outs as well as the banner areas. No changes are needed in ActionScript, these areas are already aggregated to provide the safe area rectangle for the screen.

But I understand then that this is not true and the only alternative is a paid ANE?

quanticoder avatar Dec 02 '25 01:12 quanticoder

There were a few changes in this, the above is from an earlier release note but there was a bug in that which was fixed in 51.2.2.5. But there do seem to be a variety of outcomes that depend upon various different factors, so if you're seeing something that doesn't seem right, please can you confirm:

  • application descriptor settings for 'fullscreen' and 'displayCutoutMode'
  • target SDK version for the application
  • OS version running on the device
  • device name (and ideally a link to a photo?)
  • what values you see in Screen.mainScreen.bounds, visibleBounds and safeArea
  • what values you think these should be set to

thanks

ajwfrost avatar Dec 02 '25 10:12 ajwfrost