【问题标题】:Delphi XE5 Android. How to use PowerManager.WakeLock?德尔福 XE5 安卓。如何使用 PowerManager.WakeLock?
【发布时间】:2013-09-26 07:10:32
【问题描述】:

即使没有用户活动,我也想保持设备开机并避免从内存中卸载我的应用程序。服务之类的。我制作了 How to check if network is available on Android and iOS ( Delphi XE5 ) 这样的模块,但是当我运行 SetWakeLock 时系统崩溃了:

unit Android.PowerManager;

interface

function SetWakeLock : boolean;
procedure ReleaseWakeLock;

implementation

uses
  System.SysUtils,
  Androidapi.JNI,
  Androidapi.JNIBridge,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.JavaTypes,
  FMX.Helpers.Android;

type
  JPowerManager = interface;
  JWakeLock = interface;

  JWakeLockClass = interface(JObjectClass)
  ['{4CF7A13D-15A9-4DEE-8CA7-66600C188CB7}']
  end;

  [JavaSignature('android/os/PowerManager/WakeLock')]
  JWakeLock = interface(JObject)
  ['{55983EDC-782F-490A-BF0C-12207EB7829E}']
    {Methods}
    procedure acquire; cdecl;
    procedure release; cdecl;
    function isHeld: Boolean; cdecl;
  end;
  TJWakeLock = class(TJavaGenericImport<JWakeLockClass, JWakeLock>) end;

  JPowerManagerClass = interface(JObjectClass)
  ['{B127DD4E-1DA6-49E7-98BA-5966DC7E26FA}']
  end;

  [JavaSignature('android/os/PowerManager')]
  JPowerManager = interface(JObject)
  ['{241C3B3D-3DF0-489B-A33E-3CD7F5D26313}']
    {Methods}
    function newWakeLock(levelAndFlags: integer; tag: JString): JWakeLock; cdecl;
  end;
  TJPowerManager = class(TJavaGenericImport<JPowerManagerClass, JPowerManager>) end;

function GetPowerManager: JPowerManager;
var
  PowerServiceNative: JObject;
begin
  PowerServiceNative := 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 fWakeLock : JWakeLock = nil;

function SetWakeLock : boolean;
var
  PowerManager: JPowerManager;
begin
  result := fWakeLock<>nil;
  if result then begin
    PowerManager := GetPowerManager;
    fWakeLock := PowerManager.newWakeLock(1,StringToJString('VC'));  //PARTIAL_WAKE_LOCK =1
    Result := fWakeLock<>nil;
    if Result then begin
       fWakeLock.acquire;
       Result := fWakeLock.IsHeld;
    end;
  end else if not fWakeLock.IsHeld then
    fWakeLock.acquire;
end;

procedure ReleaseWakeLock;
begin
  if fWakeLock<>nil then begin
    fWakeLock.release;
  end;
end;

end.

【问题讨论】:

    标签: android delphi delphi-xe5


    【解决方案1】:

    忽略我在评论中引用的错误逻辑,您没有在接口声明中正确引用嵌套类。

    这个单元适合我。请注意,我使用的是屏幕唤醒锁(已弃用,但仍然有效)。

    unit Android.JNI.PowerManager;
    
    interface
    
    function AcquireWakeLock : Boolean;
    procedure ReleaseWakeLock;
    
    implementation
    
    uses
      System.SysUtils,
      Androidapi.JNI,
      Androidapi.JNIBridge,
      Androidapi.JNI.GraphicsContentViewText,
      Androidapi.JNI.JavaTypes,
      FMX.Helpers.Android;
    
    type
      JPowerManager = interface;
      JWakeLock = interface;
    
      JWakeLockClass = interface(JObjectClass)
      ['{918E171F-CDB8-4464-9507-F49272CE7636}']
      end;
    
      [JavaSignature('android/os/PowerManager$WakeLock')]
      JWakeLock = interface(JObject)
      ['{D17B1136-FA15-4AEB-85B1-2D490F0FD320}']
        {Methods}
        procedure acquire; cdecl;
        procedure release; cdecl;
        function isHeld: Boolean; cdecl;
      end;
      TJWakeLock = class(TJavaGenericImport<JWakeLockClass, JWakeLock>) end;
    
      JPowerManagerClass = interface(JObjectClass)
      ['{7D0696A2-ADEA-4158-AE1F-5E720DEDBCF9}']
        {Property methods}
        function _GetFULL_WAKE_LOCK: Integer; cdecl;
        function _GetSCREEN_BRIGHT_WAKE_LOCK: Integer; cdecl;
        function _GetSCREEN_DIM_WAKE_LOCK: Integer; cdecl;
        function _GetPARTIAL_WAKE_LOCK: Integer; cdecl;
        {Properties}
        //Keep screen on bright & keyboard on
        //Deprecated in API level 17 - Jelly Bean MR1
        property FULL_WAKE_LOCK: Integer read _GetFULL_WAKE_LOCK;
        //Keep screen on bright
        //Deprecated in API level 13 - Honeycomb MR2
        property SCREEN_BRIGHT_WAKE_LOCK: Integer read _GetSCREEN_BRIGHT_WAKE_LOCK;
        //Keep screen on dim
        //Deprecated in API level 17 - Jelly Bean MR1
        property SCREEN_DIM_WAKE_LOCK: Integer read _GetSCREEN_DIM_WAKE_LOCK;
        //Keep CPU running, screen & keyboard can go off
        property PARTIAL_WAKE_LOCK: Integer read _GetPARTIAL_WAKE_LOCK;
      end;
    
      [JavaSignature('android/os/PowerManager')]
      JPowerManager = interface(JObject)
      ['{DEAED658-4353-4D17-B0A3-8179E48BE87F}']
        {Methods}
        function newWakeLock(levelAndFlags: Integer; tag: JString): JWakeLock; cdecl;
      end;
      TJPowerManager = class(TJavaGenericImport<JPowerManagerClass, JPowerManager>) end;
    
    function GetPowerManager: JPowerManager;
    var
      PowerServiceNative: JObject;
    begin
      PowerServiceNative := 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
      WakeLock: JWakeLock = nil;
    
    function AcquireWakeLock: 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;
    
    procedure ReleaseWakeLock;
    begin
      if Assigned(WakeLock) then
      begin
        WakeLock.release;
        WakeLock := nil
      end;
    end;
    
    end.
    

    【讨论】:

    • 我认为还需要更正:程序 ReleaseWakeLock;如果已分配(WakeLock)则开始,然后开始 WakeLock.release;唤醒锁 := nil;结尾;结束;
    • 是的,完成后整理一下可能是个好主意。我会相应地编辑我的帖子。
    【解决方案2】:

    您是否添加了android.permission.WAKELOCK 权限(在Delphi 中显示为Wake lock)?

    【讨论】:

    • 是的,已设置唤醒锁定权限。我无法调试,但通过注释代码行,我发现 GetPowerManager 上发生了迷恋
    • 可能与您的布尔逻辑有关。如果 fWakeLock 为 nil,您似乎向下分支并调用 isHeld。
    【解决方案3】:

    非常感谢blong 的解决方案。因为它开始在柏林德尔福工作,我重新编写了模块代码。我希望这很有用。

    需要在你的项目中开启android.permission.WAKELOCK权限。

    unit Android.JNI.PowerManager;
    
    interface
    
    function AcquireWakeLock: Boolean;
    procedure ReleaseWakeLock;
    
    implementation
    
    uses
      System.SysUtils,
      Androidapi.JNI,
      Androidapi.JNIBridge,
      Androidapi.JNI.GraphicsContentViewText,
      Androidapi.JNI.JavaTypes,
      Androidapi.Helpers,
      Androidapi.JNI.Os, // added in Berlin
      FMX.Helpers.Android;
    
    //type
      // *** this is in Androidapi.JNI.Os
      // JPowerManager = interface;
      // JWakeLock = interface;
    
      // *** this is in Androidapi.JNI.Os
      // JWakeLockClass = interface(JObjectClass)
      // ['{918E171F-CDB8-4464-9507-F49272CE7636}']
      // end;
    
      // *** this is in Androidapi.JNI.Os
      // [JavaSignature('android/os/PowerManager$WakeLock')]
      // JWakeLock = interface(JObject)
      // ['{D17B1136-FA15-4AEB-85B1-2D490F0FD320}']
      // { Methods }
      // procedure acquire; cdecl;
      // procedure release; cdecl;
      // function isHeld: Boolean; cdecl;
      // end;
      // TJWakeLock = class(TJavaGenericImport<JWakeLockClass, JWakeLock>)
      // end;
    
      // *** this is in Androidapi.JNI.Os
      // JPowerManagerClass = interface(JObjectClass)
      // ['{7D0696A2-ADEA-4158-AE1F-5E720DEDBCF9}']
      // { Property methods }
      // function _GetFULL_WAKE_LOCK: Integer; cdecl;
      // function _GetSCREEN_BRIGHT_WAKE_LOCK: Integer; cdecl;
      // function _GetSCREEN_DIM_WAKE_LOCK: Integer; cdecl;
      // function _GetPARTIAL_WAKE_LOCK: Integer; cdecl;
      // { Properties }
      // // Keep screen on bright & keyboard on
      // // Deprecated in API level 17 - Jelly Bean MR1
      // property FULL_WAKE_LOCK: Integer read _GetFULL_WAKE_LOCK;
      // // Keep screen on bright
      // // Deprecated in API level 13 - Honeycomb MR2
      // property SCREEN_BRIGHT_WAKE_LOCK: Integer read _GetSCREEN_BRIGHT_WAKE_LOCK;
      // // Keep screen on dim
      // // Deprecated in API level 17 - Jelly Bean MR1
      // property SCREEN_DIM_WAKE_LOCK: Integer read _GetSCREEN_DIM_WAKE_LOCK;
      // // Keep CPU running, screen & keyboard can go off
      // property PARTIAL_WAKE_LOCK: Integer read _GetPARTIAL_WAKE_LOCK;
      // end;
    
      // *** this is in Androidapi.JNI.Os
      // [JavaSignature('android/os/PowerManager')]
      // JPowerManager = interface(JObject)
      // ['{DEAED658-4353-4D17-B0A3-8179E48BE87F}']
      // { Methods }
      // function newWakeLock(levelAndFlags: Integer; tag: JString): JWakeLock; cdecl;
      // end;
      // TJPowerManager = class(TJavaGenericImport<JPowerManagerClass, JPowerManager>)
      // end;
    
    function GetPowerManager: JPowerManager;
    var
      PowerServiceNative: JObject;
    begin
      PowerServiceNative := TAndroidHelper.Context.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
      // WakeLock: JWakeLock = nil;
      WakeLock: JPowerManager_WakeLock = nil;
    
    function AcquireWakeLock: 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;
    
    procedure ReleaseWakeLock;
    begin
      if Assigned(WakeLock) then
      begin
        WakeLock.release;
        WakeLock := nil
      end;
    end;
    
    end.
    

    【讨论】:

      【解决方案4】:

      你需要:

      1) 设置项目选项、使用权限、唤醒锁定 = True

      2) 在uses子句中添加Android.JNI.PowerManager

      3) 调用:

       AcquireWakeLock; // at start up.
      
       ReleaseWakeLock; // at shutdown.
      

      来自 Android.JNI.PowerManager 单元

      【讨论】:

        【解决方案5】:

        在XE6上为Android编译时,将Androidapi.helpers添加到uses子句中,否则找不到StringToJString例程。

        【讨论】:

          【解决方案6】:

          我在 XE8 上对其进行了测试,效果很好,只需添加 FMX.Platform.Android 和 Androidapi.Helpers 使用。 这是IOS版本。

          uses
            iOSapi.UIKit;
          
          procedre SetSleep(Enable:Boolean);
              var
                UIApp : UIApplication;
              begin
                UIApp := TUIApplication.Wrap(TUIApplication.OCClass.sharedApplication);
                UIApp.setIdleTimerDisabled(Enable); //Change it to false on app close
              end;
          

          【讨论】:

          • 我无法让它在 XE8 上运行。你能发布它是如何实现的吗?
          猜你喜欢
          • 1970-01-01
          • 2014-07-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多