Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Android] Apps compiled for 15.0 / 35 default displaying as Edge to Edge #24742

Closed
Redth opened this issue Sep 12, 2024 · 9 comments
Closed

[Android] Apps compiled for 15.0 / 35 default displaying as Edge to Edge #24742

Redth opened this issue Sep 12, 2024 · 9 comments
Labels
area-core-platform Integration with platforms platform/android 🤖 s/triaged Issue has been reviewed t/bug Something isn't working
Milestone

Comments

@Redth
Copy link
Member

Redth commented Sep 12, 2024

Description

Starting with Android 15.0 (API 35) apps are displayed 'Edge to Edge' by default. https://developer.android.com/about/versions/15/behavior-changes-15#window-insets

It seems that .NET MAUI still adds content insets when using Shell but when using normal pages it does not. The result is that page content extends underneath the system bars (status and navigation) where it previously did not on older android versions.

There is a way to opting out of the new behaviour:
https://medium.com/androiddevelopers/insets-handling-tips-for-android-15s-edge-to-edge-enforcement-872774e8839b

First, you need to add values-v35/styles.xml and values/styles.xml files:
android-35-edge-to-edge-opt-out-resources

In the values-v35/styles.xml declare a style:

<?xml version="1.0" encoding="utf-8" ?> 
<resources>
    <style name="OptOutEdgeToEdgeEnforcement">
        <item name="android:windowOptOutEdgeToEdgeEnforcement">true</item>
    </style>
</resources>

You need to add a style with the same name in the values/styles.xml file (without the attribute):

<?xml version="1.0" encoding="utf-8" ?> 
<resources>
    <style name="OptOutEdgeToEdgeEnforcement">
    </style>
</resources>

Now in your MainActivity.cs override the OnCreate(Bundle? savedInstanceState) and apply the style you created:

[Activity(Theme = "@style/Maui.SplashTheme", MainLauncher = true, LaunchMode = LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize | ConfigChanges.Density)]
public class MainActivity : MauiAppCompatActivity
{
    protected override void OnCreate(Bundle? savedInstanceState)
    {
        // Must apply the style before the DecorView setup
        Theme?.ApplyStyle(Resource.Style.OptOutEdgeToEdgeEnforcement, force: false);

        base.OnCreate(savedInstanceState);
    }
}

Version with bug

9.0.0-rc.1.24453.9

Is this a regression from previous behavior?

No, this is something new

Last version that worked well

Android 14.0 and older

Affected platforms

Android

Affected platform versions

Android 15.0 / API 35

@Redth Redth added the t/bug Something isn't working label Sep 12, 2024
@dotnet-policy-service dotnet-policy-service bot added the s/triaged Issue has been reviewed label Sep 12, 2024
Copy link
Contributor

Hi I'm an AI powered bot that finds similar issues based off the issue title.

Please view the issues below to see if they solve your problem, and if the issue describes your problem please consider closing this one and thumbs upping the other issue to help us prioritize it. Thank you!

Open similar issues:

Closed similar issues:

Note: You can give me feedback by thumbs upping or thumbs downing this comment.

@Redth Redth added the area-core-platform Integration with platforms label Sep 12, 2024
@mattleibow mattleibow added this to the Backlog milestone Sep 13, 2024
@last-Programmer
Copy link

Thanks for the quick solution. @Redth

@PureWeen PureWeen modified the milestones: Backlog, .NET 9 SR1 Oct 24, 2024
Redth added a commit that referenced this issue Oct 24, 2024
See #24742 for details.

It seems to be a better compromise to disable this by default in MAUI apps.  You can still opt out by including a similar style:

```xml
<style name="DisableOptOutEdgeToEdgeEnforcement">
   <item name="android:windowOptOutEdgeToEdgeEnforcement">false</item>
</style>
```

And then applying it in a similar way, either by calling it before the `base.OnCreate(..)` in your activity subclass (in the OnCreate method override), or by registering for the ActivityOnCreate lifecycle callback.

Eg:

```csharp
protected override void OnCreate(Bundle? savedInstanceState)
{
    // Disable Edge to Edge opt out by calling this before base.OnCreate()
    Theme?.ApplyStyle(Resource.Style.DisableOptOutEdgeToEdgeEnforcement, force: true);

    base.OnCreate(savedInstanceState);
}
```
@eddieyanez
Copy link

Hi @Redth, thanks for sharing this workaround. I'm on net8.0-android and I have the same issue.

When trying to apply the workaround suggested above, the app won't compile with the following error message: 0>styles.xml(2): Error APT2260 : style attribute 'android:attr/windowOptOutEdgeToEdgeEnforcement' not found.

Is the workaround net9.0-android only?

Thanks

@PureWeen PureWeen moved this from Todo to In Progress in MAUI SDK Ongoing Oct 30, 2024
@Redth
Copy link
Member Author

Redth commented Oct 30, 2024

Hi @Redth, thanks for sharing this workaround. I'm on net8.0-android and I have the same issue.

When trying to apply the workaround suggested above, the app won't compile with the following error message: 0>styles.xml(2): Error APT2260 : style attribute 'android:attr/windowOptOutEdgeToEdgeEnforcement' not found.

Is the workaround net9.0-android only?

Thanks

It's Android API 35 only, which is technically only supported in .NET 9, however in .NET 8 you could technically still try to target API 35 by adding this to your AndroidManifest.xml file:

<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="35" />

This goes inside the <manifest /> element.

NOTE: This won't allow you to use new API's in your app that are Android 35+ only, but it should make the tooling recognize the new attribute you're trying to use in the style.

@eddieyanez
Copy link

Thank you!

Redth added a commit that referenced this issue Nov 1, 2024
Android 35+ enforces apps extending "Edge to Edge" by default. See
#24742 for details.

For now, a better compromise is to disable this by default in MAUI apps,
until we can provide better support for edge to edge within .NET MAUI
itself as well as better safe area insets on Android.

If you still want to manually make your app more compatible with edge to
edge, you can disable this implicit opt out by overriding the default
theme, changing the `maui_edgetoedge_optout` attribute to `false` and
the theme yourself:

```xml
<style name="MainThemeEdgeToEdge" parent="Maui.MainTheme.NoActionBar">
   <item name="maui_edgetoedge_optout">false</item>
</style>
```

And then applying the theme by calling it before the `base.OnCreate(..)`
in your activity subclass (in the OnCreate method override):

```csharp
protected override void OnCreate(Bundle? savedInstanceState)
{
    SetTheme(Resource.Style.MainThemeEdgeToEdge);

    base.OnCreate(savedInstanceState);
}
```

This also fixes a previous bug where we were always switching the theme
based on the presence of the `maui_splash` attribute, not the actual
value of the attribute.

Finally, it moves more calls into native android and reduces the
boundary crossing for this specific method.



The new "Default" of opting out of the Edge to Edge enforcement on an
Android 35+ device looks now like this:

![Screenshot_1729819287](https://github.com/user-attachments/assets/15ddc7fc-9334-4f92-82de-c0b7e19921db)

If you revert to the old behaviour by disabling the opt out, it will
look like this:

![Screenshot_1729819354](https://github.com/user-attachments/assets/1770259e-0a9e-49ea-860e-37e6131a09c4)
@jveltd
Copy link

jveltd commented Nov 4, 2024

Thank you for the work-around @Redth.

I've noticed the following error in my code for MainActivity however, the app still compiles, builds and runs in both debug and release. Not sure why this isn't found. I am on .NET9 so thought this would be supported.

Image

@Redth
Copy link
Member Author

Redth commented Nov 5, 2024

We can use #2342 to track improvements to Safe Area support in .NET MAUI.

@Redth Redth closed this as completed Nov 5, 2024
@github-project-automation github-project-automation bot moved this from In Progress to Done in MAUI SDK Ongoing Nov 5, 2024
@Gekidoku
Copy link

For someone looking to fix the same issue as me that doesnt have a values-v35 folder yet and no styles file in there.
Reminder that Visual studio doesnt set it as an AndroidResource by default if you add an xml file using New Item.

@acaliaro
Copy link

acaliaro commented Dec 5, 2024

Hi @Redth, thanks for sharing this workaround. I'm on net8.0-android and I have the same issue.
When trying to apply the workaround suggested above, the app won't compile with the following error message: 0>styles.xml(2): Error APT2260 : style attribute 'android:attr/windowOptOutEdgeToEdgeEnforcement' not found.
Is the workaround net9.0-android only?
Thanks

It's Android API 35 only, which is technically only supported in .NET 9, however in .NET 8 you could technically still try to target API 35 by adding this to your AndroidManifest.xml file:

This goes inside the `` element.

NOTE: This won't allow you to use new API's in your app that are Android 35+ only, but it should make the tooling recognize the new attribute you're trying to use in the style.

Hi @Redth I have tried to add android:targetSdkVersion="35". It, with .NET8, compiles and I can produce an APK. When I go to install and run it on a device < 35, the app crashes with a log similar to this:
Assertion at /__w/1/s/src/mono/mono/metadata/object.c:4410, condition is_ok (error)' not met, function:mono_unhandled_exception_internal, (null) assembly:System.Private.CoreLib.dll type:AggregateException member:(null)
12-04 11:30:15.543 15378 15415 F libc : Fatal signal 6 (SIGABRT), code -1 (SI_QUEUE) in tid 15415 (Finalizer), pid 15378

Going back to android:targetSdkVersion="34", the app does not crash. Is it absolutely necessary to switch to .NET9 to use android:targetSdkVersion="35"?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-core-platform Integration with platforms platform/android 🤖 s/triaged Issue has been reviewed t/bug Something isn't working
Projects
Status: Done
Development

No branches or pull requests

9 participants