FireMonkey Android加速度传感器使用率高

时间:2016-10-04 10:52:17

标签: delphi firemonkey sensor delphi-10.1-berlin

当我尝试在Android中使用加速度传感器时,它会导致高CPU使用率 - 即使我尝试通过代码停止传感器并将其停用。

我只需要在我的应用程序中读取一次加速度传感器,但看起来FireMonkey没有响应并且无法停止传感器。

以下是代码:

var
  Sensor: TCustomSensor;
begin
   { attempt to get and activate the sensor manager }
  FSensorManager := TSensorManager.Current;
  FSensorManager.Activate;

  { attempt to get an orientation sensor }
  FSensors := TSensorManager.Current.GetSensorsByCategory(TSensorCategory.Motion);

  FSensor := nil;
  for Sensor in FSensors do
    if TCustomMotionSensor(Sensor).SensorType = TMotionSensorType.Accelerometer3D then
    begin
      FSensor := TCustomMotionSensor(Sensor);
      Break;
    end;

  if not Assigned(FSensor) then
  begin
    Exit; { no orientation sensor is available }
  end;

  { start the sensor if it is not started }
  if not FSensor.Started then
  begin
    FSensor.Start;
    Timer1.Enabled := True;
  end;
end;

我试图通过以下方式停止传感器:

FSensor.Stop;
FSensorManager.Deactivate;
FSensor.Free;
FSensorManager.Free;

但看起来这根本不起作用!

以下是显示CPU使用量增加的屏幕截图:

Before

After pushing button and activated sensor

1 个答案:

答案 0 :(得分:6)

问题在于FireMonkey Android传感器实施中的疏忽。会发生什么:

当您在Android上activate the sensor manager时,您会调用TAndroidSensorManager.Activate。这会尝试为所有已知的Android传感器类型实例化TCustomSensor后代,快速删除当前设备上不支持的任何内容。这使得管理器管理一堆自定义传感器对象,每个对象都创建了一个TNativeSensor对象,其中sensor type enumeration value与Androidapi.Sensor单元中定义的一样。

到目前为止没什么大不了的。每个TNativeSensor对象构造函数都调用了几个NDK例程来设置:ASensorManager_getDefaultSensorASensorManager_createEventQueue。到目前为止,对CPU没有明显的影响。

Starting the sensor导致底层TNativeSensor调用NDK ASensorEventQueue_enableSensor例程,这就是CPU遭受重击的地方。

Stopping the custom sensor object调用ASensorEventQueue_disableSensor,您可能认为这会停止CPU使用。然而,事实上似乎并非如此。

要正确地从传感器中移除CPU使用率(仅通过实际实验),您需要销毁本机传感器事件队列,即撤消之前对ASensorManager_createEventQueue的调用。但是,FireMonkey Android代码不会这样做。代码中没有ASensorManager_destroyEventQueue的调用。

这意味着即使您将对传感器和传感器管理器的所有引用都设置为nil并且所有这些传感器对象(包括内部传感器对象)都被破坏,那么您仍会受到CPU命中:ಠ╭╮ ಠ

我能在Delphi 10.1 Berlin(目前没有Update)中获得似乎有效的行为的唯一方法是修改System.Android.Sensors.pas。如果你想同样地测试这个理论,可以采取以下步骤:

  • 在您的项目中创建一个名为RTL的新文件夹

  • 进入此RTL文件夹复制$(BDS)\ source \ rtl \ common \ System.Android.Sensors.pas,其中$(BDS)是您的Delphi安装文件夹

  • 使用项目经理将此复制的文件添加到项目中。

现在对复制的System.Android.Sensors.pas进行这些更改。在TNativeSensor的公共部分添加一个析构函数声明:

destructor Destroy; override;

实现析构函数:

destructor TNativeSensor.Destroy;
begin
  ASensorManager_destroyEventQueue(FSensorManager, FNativeEventQueue);
  inherited;
end;

编译并运行,当所有对传感器对象的引用都设置为nil时,CPU命中应该完全下降。