Jump to content
Registration disabled at the moment Read more... ×
alejandro.sawers

Android 15 and edge-to-edge enforcement

Recommended Posts

When targeting Android 15 (API level 35) the system now enforces edge-to-edge UI. As described in the documentation apps not designed to be edge-to-edge could expect issues with app content being hidden by the status bar, nav bar, etc.

FMX Android apps seem to be impacted. Here is a test on a blank Delphi 12.0 Android app: when targeting Android 14 (first image) the UI is ok, but when targeting Android 15 (second image) the sample button gets behind the status bar and is not clickable.

 

target_android14.thumb.png.a8de402d297c40c80817ece39ec79ea6.pngtarget_android15.thumb.png.7a6a03a2765d08ba3a59f872693b26d6.png

 

Effectively a breaking change. The official docs give instructions on how to make an app edge-to-edge compliant, however I'm not sure how these instructions could be applied to FMX apps (I'm not really well versed on native Android development) or if a workaround exists by patching .pas source files. I hope the latter is possible.

 

Share this post


Link to post

The Android version / SDK targeting requirements are a year behind releases. Only on 31 Aug 2024 are new apps and updates required to target Android 14 / API 34 (with extension to November on request). Delphi has often barely made this more relaxed requirement so I wouldn't expect Android 15 / API 35 support anytime soon.

 

Target API level requirements for Google Play apps - Play Console Help

Share this post


Link to post
8 hours ago, alejandro.sawers said:

Well, guess the best I can do for now is raise a ticket on the support portal and wait for the best.

You could just leave AndroidManifest.template.xml as it is (for now) - is there some reason you need to target API level 35? If you really need to, you could use code from Kastri to implement a workaround, thus:

uses
  DW.UIHelper, DW.Android.Helpers;

{ TForm1 }

procedure TForm1.FormResize(Sender: TObject);
begin
  // This method is used because the device might have Android 15, but the targetSdkVersion might be lower. Use conditionals if targeting other platforms
  if TAndroidHelperEx.CheckBuildAndTarget(35) then
  begin
    Padding.Top := TUIHelper.GetStatusBarOffset;
    // "Cheat" method for determining whether Portrait or Landscape
    if Screen.Width < Screen.Height then
      Padding.Bottom := TUIHelper.GetNavigationBarOffset
    else
      Padding.Bottom := 0;
  end;
end;

If you don't want to drag the dependent units from Kastri into your app, you could extract the parts of the code that you need.

  • Thanks 1

Share this post


Link to post
12 hours ago, Dave Nottage said:

is there some reason you need to target API level 35?

Not right now, but I know sometimes Embarcadero can miss things like these and put us in a hurry eventually.

12 hours ago, Dave Nottage said:

you could use code from Kastri to implement a workaround

I tried this with the same FMX app (I had to put a Client aligned TLayout for Padding to work and then the TButton inside it) and voila:

 

android15_padding.thumb.png.08c42ea72e932b51d50c3bb61cde1478.png

 

Thanks Dave. This should work until an official fix is given.

  • Like 2

Share this post


Link to post

<OT>
Thanks for pointing to this.

I did not stumble into this issue yet, buut .... maybe ....

It could explain the nasty misbehaviour I had recently with the GoogleMaps App herself.
The lower buttons didn't react and it was not possible to operae as it should.

I had the verdict that an recent update of the Samsung S23 Ultra caused this issue, but perhaps somehow remotely related to above behaviour.
At least no visual effect appears anyhow, as far I can say, only un-clickable in the footer row.

</OT>

Share this post


Link to post

Given your latest findings on this other thread looks like your problem is not related to Android 15 after all. That and also the fact that Samsung is the one who takes the most time to release Android upgrades (or at least it was that way a few years ago).

Share this post


Link to post

Has anybody already installed Android SDK 36 and run into the same topic again?

I did when a user with a Galaxy S25 Ultra reported cut off title and base in a beta.

 

Is there a new fix in the meantime?

Steffen

Share this post


Link to post

If you're targeting Android 16 and your user also has Android 16 running then this is expected, as the workaround for targeting Android 15 included in Delphi 12.3 no longer works under these conditions. You can:
- Lower your target to Android 15 (SDK 35) and continue using the 12.3 workaround, or
- Use the Kastri workaround as explained above, if it fits your needs, or
- Wait for the release of Delphi 13 and hope that it includes an official fix

Share this post


Link to post
Quote

- Use the Kastri workaround as explained above, if it fits your needs, or

Has anybody burned down the required Kastri files to the absolute minimum?

I don't want to bloat my code just because of a few lines of it.

Share this post


Link to post

You can include the Kastri workaround as-is and then ctrl-click on the procedures, copy them to your unit (along any uses from the Delphi RTL) and then remove the Kastri units from your uses. I did a quick test and its just around 30 lines of code to copy.

Share this post


Link to post

Hi Alejandro,

thanks but I have no idea what you mean. I haven't installed Kastri, I just copied DW.UIHelper and DW.Android.Helpers.pas to uses and to my library directory.

Due to internal dependencies, I had to copy also DW.UIHelper.Android and DW.Androidapi.JNI.DWUtility and more.

I decided this is getting too big, so I stopped.

Burning it down to 30 lines would be nice...

Share this post


Link to post
1 hour ago, Stewag said:

Burning it down to 30 lines would be nice...

uses
  Androidapi.Helpers, Androidapi.JNI.GraphicsContentViewText, Androidapi.JNI.Os;

function IsFullScreen: Boolean;
begin
  Result := (TAndroidHelper.Activity.getWindow.getAttributes.flags and TJWindowManager_LayoutParams.JavaClass.FLAG_LAYOUT_NO_LIMITS) > 0;
end;

function GetResourceHeight(const AResourceName: string): Single;
var
  LID: Integer;
  LResources: JResources;
begin
  Result := 0;
  LResources := TAndroidHelper.Context.getResources;
  LID := LResources.getIdentifier(StringToJString(AResourceName), StringToJString('dimen'), StringToJString('android'));
  if LID > 0 then
    Result := LResources.getDimensionPixelSize(LID) / TAndroidHelper.DisplayMetrics.density;
end;

function GetTargetSdkVersion: Integer;
var
  LApplicationInfo: JApplicationInfo;
begin
  LApplicationInfo := TAndroidHelper.Context.getPackageManager.getApplicationInfo(TAndroidHelper.Context.getPackageName, 0);
  Result := LApplicationInfo.targetSdkVersion;
end;

function CheckBuildAndTarget(const AValue: Integer): Boolean;
begin
  Result := (TJBuild_VERSION.JavaClass.SDK_INT >= AValue) and (GetTargetSdkVersion >= AValue);
end;

function GetNavigationBarOffset: Single;
begin
  if CheckBuildAndTarget(35) or IsFullScreen then
    Result := GetResourceHeight('navigation_bar_height')
  else
    Result := 0;
end;

function GetStatusBarOffset: Single;
begin
  Result := GetResourceHeight('status_bar_height');
end;

procedure TForm1.FormResize(Sender: TObject);
begin
  if CheckBuildAndTarget(35) then
  begin
    Padding.Top := GetStatusBarOffset;
    if Screen.Width < Screen.Height then
      Padding.Bottom := GetNavigationBarOffset
    else
      Padding.Bottom := 0;
  end;
end;

 

Share this post


Link to post

Thanks a lot David, unfortunately it doesn't work for me yet.

I get an "TAndroidHelpersEx undeclared" error. When I than add DW.Android.Helpers to uses, the circle starts again, asking for DW.Androidapi.JNI.App.pas, then 'DW.GlobalDefines.inc' and so on.

I probably need to install Kastri?

But If I do, will there be much more code added to my project then the few lines in your post?

Share this post


Link to post
Just now, Stewag said:

I get an "TAndroidHelpersEx undeclared" error.

I'm puzzled as to how you get such an error in the code I posted just above this reply of yours, since there is no such reference in it.

Share this post


Link to post

Stupid me! :classic_unsure:

I copied the OnResize Code from your initial post in 2024!

Now it works. Brilliant as always - thank you David!!!

Best regards

Steffen

  • Like 1

Share this post


Link to post

Sorry David, I was a little quick with stating that it works.

Compile runs smoothly, but now I get extra space also on my Android 15, which has no edge-to-edge display, wasting space.

 

It seems as if

CheckBuildAndTarget(35)

simply checks the Android version and not if display and Navigationbar collide?

Share this post


Link to post
2 minutes ago, Stewag said:

It seems as if


CheckBuildAndTarget(35)

simply checks the Android version...

Yes, it checks the Android version on the device, but also checks the targetSdkVersion value in the manifest. Check the AndroidManifest.xml file (i.e. not AndroidManifest.template.xml) in the project output folder to check what the value is for targetSdkVersion.

Share this post


Link to post

...okay, so no solution to the edge-to-edge problem, same as:

 

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

was for Android 15.

I'd like to reduce display size only if the smartphone is an edge-to-edge and not depending of its Android version in general.

We will probably need to wait for  D13 and hope that it brings a fix.

 

 

Edited by Stewag

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×