4

I'm wanting to keep the screen on in my Delphi app for Android.

I know that there are two ways:

  1. with the window manager and FLAG_KEEP_SCREEN_ON

  2. with a "wake lock".

The problems I have are that I can't seem to get a WindowManager instance, let alone get the flag from a layouts class, and wake locks don't seem to be defined (at least in XE8).

The window flag seems like the best way to go, but there appears to be no way of success.

Does anyone know how to do this?

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
M3wP
  • 121
  • 1
  • 7
  • 1
    I have followed this in the past and it worked:http://stackoverflow.com/questions/19021647/delphi-xe5-android-how-to-use-powermanager-wakelock . Make sure to add the necessary bits in the project info (see few comments down in the link above) – Alain Thiffault Jan 15 '16 at 02:20

3 Answers3

9

The solution of calling addFlags() in FormCreate() with FLAG_KEEP_SCREEN_ON doesn't work in Delphi 10.1 Berlin in combination with Android 6 (and probably other combinations).

You will get the following exception:

exception class EJNIException with message 'android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.'.

Somehow the threading of Android/Delphi has changed because this used to work (according to lots of messages). The only way I got it to work (with that one line) was putting this line in the main project-code under Application.Initialize;.

uses
  Androidapi.Helpers,
  Androidapi.JNI.GraphicsContentViewText;

begin
  Application.Initialize;
  SharedActivity.getWindow.addFlags(TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON);
  Application.CreateForm(TMainForm, MainForm);
  Application.Run;
end.

But when you want to switch this flag on and off during your program you need to be able to execute it in your form-code. In that case you can use CallInUIThreadAndWaitFinishing() to let this command run in the UIThread. Then you don't get the mentioned exception and the flag works.

uses
  FMX.Helpers.Android,
  Androidapi.Helpers,
  Androidapi.JNI.GraphicsContentViewText;

procedure TMainForm.btnKeepScreenOnAddClick(Sender: TObject);
begin
  CallInUIThreadAndWaitFinishing(
    procedure
    begin
      SharedActivity.getWindow.addFlags(
        TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON);
    end);
end;

procedure TMainForm.btnKeepScreenOnClearClick(Sender: TObject);
begin
  CallInUIThreadAndWaitFinishing(
    procedure
    begin
      SharedActivity.getWindow.clearFlags(
        TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON);
    end);
end;
Rik
  • 1,982
  • 1
  • 17
  • 30
5

To use the FLAG_KEEP_SCREEN_ON flag in Delphi, try something like this:

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

procedure TMainForm.FormCreate(Sender: TObject);
begin
  SharedActivity.getWindow.addFlags(TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON);
end;
Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770
  • On the Dutch forum we found out that if you do this in FormCreate it doesn't work. Putting it in your main-project source just after Application.Initialize it does work. See http://www.nldelphi.com/showthread.php?42039-Scherm-beveiliging-uitschakelen-met-code&p=353992&viewfull=1#post353992 – Rik Oct 25 '16 at 08:35
  • @Rik that discussion does not say anything about it not working in OnCreate. And since it is a window-specific setting that can be set and cleared at any time, I don't see why it wouldn't work in OnCreate. Do you have any specific details as to why it wouldn't work in OnCreate? It is called in the main UI thread same as the DPR code – Remy Lebeau Oct 25 '16 at 15:31
  • The discussion that it didn't work in OnCreate is a few post before the one I pointed to. Here: http://www.nldelphi.com/showthread.php?42039-Scherm-beveiliging-uitschakelen-met-code&p=353985&viewfull=1#post353985. B.T.W. I'm rvk in that discussion and I tried it after I posted the suggestion to do this in OnCreate and it gave me a black screen in Android and the app hanged. Putting it under Application.Initialize it worked. Maybe it can also be put in a Button (and clearflags in another button) but I haven't tried that. I will try that tomorrow and report back with what exactly works and not. – Rik Oct 25 '16 at 18:34
  • Ok, tested it. In Delphi 10.1 Berlin I always get an exception with this `Project Project1.apk raised exception class EJNIException with message 'android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.'.` Either this is a bug in Berlin 10.1 (because Form thread and main thread are the same) or it's something strange with Android 6.0.1. If I don't catch the exception the app crashes. If I catch the exception with try/except all works correctly and screen stays on (which leads me to believe it's a Delphi issue). – Rik Oct 26 '16 at 08:38
  • it seems working good on 10.2.1 , but how can i manage it after form create?? so every time user checkbox a checkbox or something the screen dont turn off!! – peiman F. Aug 12 '18 at 09:14
  • Old but gold. Working with 10.3.3 CE version. Thanks! – Magno Jun 04 '20 at 14:09
1

As per the comment from lowrider, this answer worked well:

Delphi XE5 Android. How to use PowerManager.WakeLock?

I did require that no FMX framework be used (without mentioning), but I was able to achieve this in XE8 by replacing the FMX.Helpers.Android reference with Androidapi.helpers (only one, not both was required).

Community
  • 1
  • 1
M3wP
  • 121
  • 1
  • 7