Android Question Problem with Android version 15 and higher

Filippo

Expert
Licensed User
Longtime User
Hi,

There is this warning in the Play Console:

2 actions recommended

Your app no longer uses supported APIs or parameters for borderless display

At least one of the APIs or parameters you are using and for which you have specified the use of borderless and window display has been discontinued in Android 15. Your app uses the following APIs or parameters that are no longer supported:

  • androidx.core.view.WindowCompat.setDecorFitsSystemWindows
  • android.view.Window.setDecorFitsSystemWindows
  • androidx.core.view.WindowCompat$Api30Impl.setDecorFitsSystemWindows
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES

    They start at the following points:
  • androidx.compose.ui.window.DialogWrapper.<init>
  • androidx.core.view.WindowCompat$Api30Impl.setDecorFitsSystemWindows
  • androidx.core.view.WindowCompat.setDecorFitsSystemWindows
  • androidx.activity.EdgeToEdgeApi28.adjustLayoutInDisplayCutoutMode

    Migrate away from these APIs or parameters in preparation for the switch to Android 15.

Now I have to check where I need to change something.
 

MarcoRome

Expert
Licensed User
Longtime User
Do you use something like this ?

Manifest:
B4X:
SetApplicationAttribute(android:windowLayoutInDisplayCutoutMode, ...)

or code:

B4X:
....
jo.RunMethod("getWindow", Null)
....
 
Upvote 0

Filippo

Expert
Licensed User
Longtime User
Do you use something like this ?

Manifest:
B4X:
SetApplicationAttribute(android:windowLayoutInDisplayCutoutMode, ...)

or code:

B4X:
....
jo.RunMethod("getWindow", Null)
....
Ciao Marco,

No, I don't use this kind of code in any of my apps.

I have the same Google recommendation for almost all other apps.
 
Upvote 0

Filippo

Expert
Licensed User
Longtime User
Hi,

the function “setDecorFitsSystemWindows” comes from this library, but as far as I know, I don't use this library in any of my apps.

Library-Link= WindowCompat
B4X:
/*
 * Copyright 2018 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package androidx.core.view;

import android.app.Activity;
import android.graphics.Rect;
import android.os.Build;
import android.view.View;
import android.view.Window;

import androidx.annotation.IdRes;
import androidx.annotation.RequiresApi;

import org.jspecify.annotations.NonNull;

/**
 * Helper for accessing features in {@link Window}.
 */
public final class WindowCompat {
    /**
     * Flag for enabling the Action Bar.
     * This is enabled by default for some devices. The Action Bar
     * replaces the title bar and provides an alternate location
     * for an on-screen menu button on some devices.
     */
    public static final int FEATURE_ACTION_BAR = 8;

    /**
     * Flag for requesting an Action Bar that overlays window content.
     * Normally an Action Bar will sit in the space above window content, but if this
     * feature is requested along with {@link #FEATURE_ACTION_BAR} it will be layered over
     * the window content itself. This is useful if you would like your app to have more control
     * over how the Action Bar is displayed, such as letting application content scroll beneath
     * an Action Bar with a transparent background or otherwise displaying a transparent/translucent
     * Action Bar over application content.
     *
     * <p>This mode is especially useful with {@link View#SYSTEM_UI_FLAG_FULLSCREEN
     * View.SYSTEM_UI_FLAG_FULLSCREEN}, which allows you to seamlessly hide the
     * action bar in conjunction with other screen decorations.
     *
     * <p>As of {@link Build.VERSION_CODES#JELLY_BEAN}, when an
     * ActionBar is in this mode it will adjust the insets provided to
     * {@link View#fitSystemWindows(Rect) View.fitSystemWindows(Rect)}
     * to include the content covered by the action bar, so you can do layout within
     * that space.
     */
    public static final int FEATURE_ACTION_BAR_OVERLAY = 9;

    /**
     * Flag for specifying the behavior of action modes when an Action Bar is not present.
     * If overlay is enabled, the action mode UI will be allowed to cover existing window content.
     */
    public static final int FEATURE_ACTION_MODE_OVERLAY = 10;

    private WindowCompat() {}

    /**
     * Finds a view that was identified by the {@code android:id} XML attribute
     * that was processed in {@link Activity#onCreate}, or throws an
     * IllegalArgumentException if the ID is invalid, or there is no matching view in the hierarchy.
     * <p>
     * <strong>Note:</strong> In most cases -- depending on compiler support --
     * the resulting view is automatically cast to the target class type. If
     * the target class type is unconstrained, an explicit cast may be
     * necessary.
     *
     * @param window window in which to find the view.
     * @param id the ID to search for
     * @return a view with given ID
     * @see ViewCompat#requireViewById(View, int)
     * @see Window#findViewById(int)
     */
    @SuppressWarnings("TypeParameterUnusedInFormals")
    public static <T extends View> @NonNull T requireViewById(@NonNull Window window,
            @IdRes int id) {
        if (Build.VERSION.SDK_INT >= 28) {
            return Api28Impl.requireViewById(window, id);
        }

        T view = window.findViewById(id);
        if (view == null) {
            throw new IllegalArgumentException("ID does not reference a View inside this Window");
        }
        return view;
    }

    /**
     * Sets whether the decor view should fit root-level content views for
     * {@link WindowInsetsCompat}.
     * <p>
     * If set to {@code false}, the framework will not fit the content view to the insets and will
     * just pass through the {@link WindowInsetsCompat} to the content view.
     * </p>
     * <p>
     * Please note: using the {@link View#setSystemUiVisibility(int)} API in your app can
     * conflict with this method. Please discontinue use of {@link View#setSystemUiVisibility(int)}.
     * </p>
     *
     * @param window                 The current window.
     * @param decorFitsSystemWindows Whether the decor view should fit root-level content views for
     *                               insets.
     */
    public static void setDecorFitsSystemWindows(@NonNull Window window,
            final boolean decorFitsSystemWindows) {
        if (Build.VERSION.SDK_INT >= 35) {
            Api35Impl.setDecorFitsSystemWindows(window, decorFitsSystemWindows);
        } else if (Build.VERSION.SDK_INT >= 30) {
            Api30Impl.setDecorFitsSystemWindows(window, decorFitsSystemWindows);
        } else {
            Api16Impl.setDecorFitsSystemWindows(window, decorFitsSystemWindows);
        }
    }

    /**
     * Retrieves the single {@link WindowInsetsControllerCompat} of the window this view is attached
     * to.
     *
     * @return The {@link WindowInsetsControllerCompat} for the window.
     * @see Window#getInsetsController()
     */
    public static @NonNull WindowInsetsControllerCompat getInsetsController(@NonNull Window window,
            @NonNull View view) {
        return new WindowInsetsControllerCompat(window, view);
    }

    static class Api16Impl {
        private Api16Impl() {
            // This class is not instantiable.
        }

        static void setDecorFitsSystemWindows(@NonNull Window window,
                final boolean decorFitsSystemWindows) {
            final int decorFitsFlags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN;

            final View decorView = window.getDecorView();
            final int sysUiVis = decorView.getSystemUiVisibility();
            decorView.setSystemUiVisibility(decorFitsSystemWindows
                    ? sysUiVis & ~decorFitsFlags
                    : sysUiVis | decorFitsFlags);
        }
    }

    @RequiresApi(30)
    static class Api30Impl {
        private Api30Impl() {
            // This class is not instantiable.
        }

        static void setDecorFitsSystemWindows(@NonNull Window window,
                final boolean decorFitsSystemWindows) {
            final int stableFlag = View.SYSTEM_UI_FLAG_LAYOUT_STABLE;

            final View decorView = window.getDecorView();
            final int sysUiVis = decorView.getSystemUiVisibility();
            decorView.setSystemUiVisibility(decorFitsSystemWindows
                    ? sysUiVis & ~stableFlag
                    : sysUiVis | stableFlag);
            window.setDecorFitsSystemWindows(decorFitsSystemWindows);
        }
    }

    @RequiresApi(35)
    static class Api35Impl {
        private Api35Impl() {
            // This class is not instantiable.
        }

        static void setDecorFitsSystemWindows(@NonNull Window window,
                final boolean decorFitsSystemWindows) {
            window.setDecorFitsSystemWindows(decorFitsSystemWindows);
        }
    }

    @RequiresApi(28)
    static class Api28Impl {
        private Api28Impl() {
            // This class is not instantiable.
        }

        @SuppressWarnings({"unchecked", "TypeParameterUnusedInFormals"})
        static <T> T requireViewById(Window window, int id) {
            return (T) window.requireViewById(id);
        }
    }
}
 
Upvote 0

agraham

Expert
Licensed User
Longtime User
These continual breaking changes to Android are ridiculous. On Windows I can still run 25 year old plus complex applications from the Windows XP era (Office XP among them) without problems - but not so for a few year old apps on Android :(
 
Upvote 0

Filippo

Expert
Licensed User
Longtime User
Hi,

I bought a new phone with Android 15 today to test the new SDK-35, here is my first test result.

The App-settings are as follows:
B4X:
#Region  Activity Attributes
    #FullScreen: True
    #IncludeTitle: false
#End Region

How can I use these settings in B4x?
 

Attachments

  • Test_with_SDK-35.jpg
    Test_with_SDK-35.jpg
    150.7 KB · Views: 92
Last edited:
Upvote 0

hung

Active Member
Licensed User
Longtime User
Hi,

I bought a new phone with Android 15 today to test the new SDK-35, here is my first test result.

The App-settings are as follows:
B4X:
#Region  Activity Attributes
    #FullScreen: True
    #IncludeTitle: false
#End Region

How can I use these settings in B4x?
Will #FullScreen: False work?
 
Upvote 0

Mr.Coder

Member
Licensed User
Longtime User
Hi,

My apps work without problems in android 15 and later, I use this code to know where the correct or safe area :

B4X:
Private Sub GetSystemWindowInsets(gInsetsType As String) As Int()
    
    Dim gWindowInsets(4) As Int
    
    Try

        '[Insets Types] :
        
        '[captionBar]
        'An insets type representing the window of a caption bar.
        
        '[displayCutout]
        'Returns an insets type representing the area that used by DisplayCutout.
        
        '[ime]
        'An insets type representing the window of an InputMethod.
        
        '[mandatorySystemGestures]
        
        '[navigationBars]
        'An insets type representing any system bars for navigation.
        
        '[statusBars]
        'An insets type representing any system bars for displaying status.
        
        '[systemBars]
        'All system bars. Includes statusBars(), captionBar() as well as navigationBars(), systemOverlays(), but not ime().
        
        '[systemGestures]
        'Returns an insets type representing the system gesture insets.
        'The system gesture insets represent the area of a window where system gestures have priority And may consume some Or
        'all touch input, e.g. due To the a system bar occupying it, Or it being reserved For touch-only gestures.
        'Simple taps are guaranteed To reach the window even within the system gesture insets, As Long As they are outside the
        'system window insets.
        'When View#SYSTEM_UI_FLAG_LAYOUT_STABLE Is requested, an inset will be returned even when the system gestures are
        'inactive due To View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN Or View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION.
        
        '[systemOverlays]
        'System overlays represent the insets caused by the system visible elements. Unlike navigationBars() or statusBars(),
        'system overlays might not be hidden by the client. For compatibility reasons, this type is included in systemBars().
        'In this way, views which fit systemBars() fit systemOverlays(). Examples include climate controls, multi-tasking
        'affordances, etc.
        
        '[tappableElement]

        'Once you target SDK 35 or higher on a device running Android 15 or higher, your app is displayed edge-to-edge.
        'The window spans the entire width and height of the display by drawing behind the system bars. System bars include
        'the status bar, caption bar, and navigation bar.
                
        If uPhone.SdkVersion >= 35 Then
            
           Dim oContext As JavaObject
           Dim oWindowInsets As JavaObject
           Dim oWindowInsetsType As JavaObject
           Dim oInsets As JavaObject
           Dim InsetsID As Int
          
           oContext.InitializeContext
          
           'Activity Window Insets
           oWindowInsets = oContext.RunMethodJO("getWindow", Null).RunMethodJO("getDecorView", Null).RunMethod("getRootWindowInsets", Null)
          
           oWindowInsetsType.InitializeStatic("android.view.WindowInsets.Type")
          
           InsetsID = oWindowInsetsType.RunMethod(gInsetsType, Null).As(Int)
          
           'Log("InsetsID=" & InsetsID)
          
           oInsets = oWindowInsets.RunMethod("getInsetsIgnoringVisibility", Array(InsetsID))

'           Log(gInsetsType & ".Left=" & oInsets.GetField("left").As(Int))
'           Log(gInsetsType & ".top=" & oInsets.GetField("top").As(Int))
'           Log(gInsetsType & ".right=" & oInsets.GetField("right").As(Int))
'           Log(gInsetsType & ".bottom=" & oInsets.GetField("bottom").As(Int))
          
           gWindowInsets(0) = oInsets.GetField("left").As(Int)
           gWindowInsets(1) = oInsets.GetField("top").As(Int)
           gWindowInsets(2) = oInsets.GetField("right").As(Int)
           gWindowInsets(3) = oInsets.GetField("bottom").As(Int)   
              
        End If
          
        Return gWindowInsets
        
    Catch

        Log(LastException)
                  
        Return gWindowInsets
        
    End Try
    
End Sub

Then in Activity_Create event :

B4X:
gStatusBarsInset = GetSystemWindowInsets("statusBars")
gNavigationBarsInset = GetSystemWindowInsets("navigationBars")

CorrectScreenHeight = Activity.Height - gStatusBarsInset(1) - gNavigationBarsInset(3)
CorrectScreenWidth = Activity.Width   
CorrectScreenTop = gStatusBarsInset(1)
CorrectScreenBottom = gNavigationBarsInset(3)

- I hope this is useful to you.
 
Upvote 0

Filippo

Expert
Licensed User
Longtime User
- I hope this is useful to you.
Thank you very much for your help.
Unfortunately it does not work for me.
I have done the following:
B4X:
    Dim gStatusBarsInset(4), gNavigationBarsInset(4) As Int
    Dim CorrectScreenHeight, CorrectScreenWidth, CorrectScreenTop, CorrectScreenBottom, CorrectScreenLeft As Int
    gStatusBarsInset = GetSystemWindowInsets("statusBars")
    gNavigationBarsInset = GetSystemWindowInsets("navigationBars")

    CorrectScreenHeight = Activity.Height - gStatusBarsInset(1) - gNavigationBarsInset(3)
    CorrectScreenWidth = Activity.Width
    CorrectScreenTop = gStatusBarsInset(1)
    CorrectScreenBottom = gNavigationBarsInset(3)
    CorrectScreenLeft = gNavigationBarsInset(0)

    Activity.LoadLayout("frmmain")
   Activity.SetLayoutAnimated(0, CorrectScreenLeft, CorrectScreenTop, CorrectScreenWidth, CorrectScreenHeight)

Then I get this error message:
Error occurred on line: 1042 (Main)
java.lang.ClassCastException: android.widget.FrameLayout$LayoutParams cannot be cast to anywheresoftware.b4a.BALayout$LayoutParams
at anywheresoftware.b4a.objects.ViewWrapper.SetLayoutAnimated(ViewWrapper.java:337)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.shell.Shell.runVoidMethod(Shell.java:777)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:354)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:255)
at java.lang.reflect.Method.invoke(Native Method)
at anywheresoftware.b4a.ShellBA.raiseEvent2(ShellBA.java:157)
at fg.cronomillemiglia.main.afterFirstLayout(main.java:105)
at fg.cronomillemiglia.main.access$000(main.java:17)
at fg.cronomillemiglia.main$WaitForLayout.run(main.java:83)
at android.os.Handler.handleCallback(Handler.java:959)
at android.os.Handler.dispatchMessage(Handler.java:100)
at android.os.Looper.loopOnce(Looper.java:234)
at android.os.Looper.loop(Looper.java:319)
at android.app.ActivityThread.main(ActivityThread.java:8754)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:602)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:962)
 
Upvote 0

Mr.Coder

Member
Licensed User
Longtime User
I do not change the activity Layout position, but I change the views position that loaded inside the activity to make it visible. and I use this App-settings :

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

try to not use SetLayoutAnimated for activity and use it for views inside activity.
 
Upvote 0

Filippo

Expert
Licensed User
Longtime User
I do not change the activity Layout position, but I change the views position that loaded inside the activity to make it visible. and I use this App-settings :

B4X:
#Region  Activity Attributes
    #FullScreen: False
    #IncludeTitle: False
#End Region

try to not use SetLayoutAnimated for activity and use it for views inside activity.
After your settings is even worse.

1748630921249.png
 
Upvote 0
Top