Einzelnen Beitrag anzeigen

knaeuel

Registriert seit: 2. Jul 2007
110 Beiträge
 
Delphi 10.3 Rio
 
#1

Powersave deaktivieren (Win: ok, Android: ok, iOS: ???)

  Alt 20. Mär 2018, 13:37
Hallo zusammen,

ich habe heute meine Zeit bisher damit verbracht, herauszufinden, wie ich auf den 3 genannten Plattformen den Powersave-Modus vorübergehend deaktivieren kann.

iOS: Für iOS hab ich noch keine Lösung gefunden. HILFE!
Android: kurz getestet, funzt (längerer Test folgt heute über Nacht)
Windows: Programm läuft und meckert nicht, echter Test folgt heute Abend

Ich habe jetzt noch nicht aufgeräumt und man könnte stilistisch sofort was verbessern, aber mir gehts erstmal um die Funktionalität.

hier schonmal der funktionierende Code:

Delphi-Quellcode:
unit Powermanagement;

interface

{$IFDEF ANDROID}
function Acquire_PARTIAL_WAKE_LOCK: Boolean;
function Acquire_SCREEN_DIM_WAKE_LOCK: Boolean;
function Acquire_SCREEN_BRIGHT_WAKE_LOCK: Boolean;
function Acquire_FULL_WAKE_LOCK: Boolean;
procedure ReleaseWakeLock;
{$ENDIF}

{$IFDEF MSWINDOWS}
type EXECUTION_STATE = UINT32;//System.DWORD; 4 byte unsigned int


//If the function succeeds, the return value is the previous thread execution state.
//If the function fails, the return value is NULL.
function SetThreadExecutionState(esFlags: EXECUTION_STATE): EXECUTION_STATE; stdcall; external 'kernel32.dll';


const
  //Away mode should be used only by media-recording and media-distribution
  //applications that must perform critical background processing on desktop
  //computers while the computer appears to be sleeping.
  ES_AWAYMODE_REQUIRED = UINT32($00000040); //Enables away mode. This value must be specified with ES_CONTINUOUS.
  {$EXTERNALSYM ES_AWAYMODE_REQUIRED}
  ES_SYSTEM_REQUIRED = UINT32($00000001); //Forces the system to be in the working state by resetting the system idle timer.
  {$EXTERNALSYM ES_SYSTEM_REQUIRED}
  ES_DISPLAY_REQUIRED = UINT32($00000002); //Forces the display to be on by resetting the display idle timer.
  {$EXTERNALSYM ES_DISPLAY_REQUIRED}
  ES_CONTINUOUS = UINT32($80000000); //anweisungen mit ES_CONTINUOUS bleiben
  {$EXTERNALSYM ES_CONTINUOUS}              //aktiv, bis nochmal ES_CONTINUOUS gesendet wird
{$ENDIF}

implementation

uses
{$IFDEF ANDROID}
  Androidapi.JNI,
  Androidapi.JNIBridge,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.JavaTypes,
  Androidapi.Helpers,
  Androidapi.JNI.Os, // enthält wakelock - added in Berlin
  FMX.Helpers.Android,
{$ENDIF}
  System.SysUtils;

{$IFDEF ANDROID}
function GetPowerManager: JPowerManager;
var
  PowerServiceNative: JObject;
begin
  PowerServiceNative := TAndroidHelper.Context.getSystemService(// veraltet: SharedActivityContext.getSystemService(
    TJContext.JavaClass.POWER_SERVICE);
  if not Assigned(PowerServiceNative) then
    raise Exception.Create('Could not locate Power Service');
  Result := TJPowerManager.Wrap(
    (PowerServiceNative as ILocalObject).GetObjectID);
  if not Assigned(Result) then
    raise Exception.Create('Could not access Power Manager');
end;

var
  // *** this is in Androidapi.JNI.Os (since Delphi 10.1 Berlin)
  // WakeLock: JWakeLock = nil;
  WakeLock: JPowerManager_WakeLock = nil;

//ANDROID:
// es gibt noch 2 weitere Flags, die sich auf die Wakelocks mit
// eingeschaltetem Bildschirm beziehen:
// ON_AFTER_RELEASE
// ACQUIRE_CAUSES_WAKEUP -> siehe web developer.android.com

// bei PARTIAL_WAKE_LOCK ist die CPU immer an (User hat keinerlei Einfluss)
// bei den Modi mit eingeschaltetem Bildschirm kann der User über
// Drücken des Powerknopfes alles (inkl. CPU) in den Schlafzustand schicken
// und damit den Wakelock "überschreiben"
//ENDE ANDROID

//PARTIAL_WAKE_LOCK: CPU ON; Screen OFF; Keyboard OFF
function Acquire_PARTIAL_WAKE_LOCK: Boolean;
var
  PowerManager: JPowerManager;
begin
  Result := Assigned(WakeLock);
  if not Result then
  begin
    PowerManager := GetPowerManager;
    WakeLock := PowerManager.newWakeLock(
      TJPowerManager.JavaClass.PARTIAL_WAKE_LOCK,
      StringToJString('Delphi'));
    Result := Assigned(WakeLock);
  end;
  if Result then
  begin
    if not WakeLock.isHeld then
    begin
      WakeLock.acquire;
      Result := WakeLock.isHeld
    end;
  end;
end;

//SCREEN_DIM_WAKE_LOCK: CPU ON; Screen DIM; Keyboard OFF
function Acquire_SCREEN_DIM_WAKE_LOCK: Boolean;
var
  PowerManager: JPowerManager;
begin
  Result := Assigned(WakeLock);
  if not Result then
  begin
    PowerManager := GetPowerManager;
    WakeLock := PowerManager.newWakeLock(
      TJPowerManager.JavaClass.SCREEN_DIM_WAKE_LOCK,
      StringToJString('Delphi'));
    Result := Assigned(WakeLock);
  end;
  if Result then
  begin
    if not WakeLock.isHeld then
    begin
      WakeLock.acquire;
      Result := WakeLock.isHeld
    end;
  end;
end;

//SCREEN_BRIGHT_WAKE_LOCK: CPU ON; Screen BRIGHT; Keyboard OFF
function Acquire_SCREEN_BRIGHT_WAKE_LOCK: Boolean;
var
  PowerManager: JPowerManager;
begin
  Result := Assigned(WakeLock);
  if not Result then
  begin
    PowerManager := GetPowerManager;
    WakeLock := PowerManager.newWakeLock(
      TJPowerManager.JavaClass.SCREEN_BRIGHT_WAKE_LOCK,
      StringToJString('Delphi'));
    Result := Assigned(WakeLock);
  end;
  if Result then
  begin
    if not WakeLock.isHeld then
    begin
      WakeLock.acquire;
      Result := WakeLock.isHeld
    end;
  end;
end;

//FULL_WAKE_LOCK: CPU ON; Screen BRIGHT; Keyboard BRIGHT
function Acquire_FULL_WAKE_LOCK: Boolean;
var
  PowerManager: JPowerManager;
begin
  Result := Assigned(WakeLock);
  if not Result then
  begin
    PowerManager := GetPowerManager;
    WakeLock := PowerManager.newWakeLock(
      TJPowerManager.JavaClass.FULL_WAKE_LOCK,
      StringToJString('Delphi'));
    Result := Assigned(WakeLock);
  end;
  if Result then
  begin
    if not WakeLock.isHeld then
    begin
      WakeLock.acquire;
      Result := WakeLock.isHeld
    end;
  end;
end;

procedure ReleaseWakeLock;
begin
  if Assigned(WakeLock) then
  begin
    WakeLock.release;
    WakeLock := nil
  end;
end;
{$ENDIF}

end.

In meinem Fall kann der Bildschirm ruhig ausgehen, Tastatur sowieso, nur die CPU soll weiter arbeiten. Der Aufruf erfolgt dann für dieses Beispiel so:

Delphi-Quellcode:
procedure PowerSaveON;
begin
{$IFDEF ANDROID}
  ReleaseWakeLock;
{$ENDIF}
{$IFDEF MSWINDOWS}
  SetThreadExecutionState(ES_CONTINUOUS);
{$ENDIF}
end;

procedure PowerSaveOFF;
begin
{$IFDEF ANDROID}
  Acquire_PARTIAL_WAKE_LOCK;
{$ENDIF}
{$IFDEF MSWINDOWS}
  SetThreadExecutionState(ES_CONTINUOUS or ES_SYSTEM_REQUIRED or ES_AWAYMODE_REQUIRED);
{$ENDIF}
end;
Hat jemand einen Ansatz oder eine Lösung für iOS? Meine Google-Versuche sind alle ziemlich erfolglos geblieben. Ich finde nur Schrott...

Danke schonmal vorab!
Wolfgang
  Mit Zitat antworten Zitat