【问题标题】:FireMonkey Android acceleration sensor high cpu usageFireMonkey Android 加速度传感器 CPU 占用率高
【发布时间】:2016-10-04 10:52:16
【问题描述】:

当我尝试在 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

【问题讨论】:

  • 你忽略了产品版本的使用。请通过编辑您的问题来纠正此问题。
  • 另外,您能否澄清一下……您是说您尝试停用传感器并不会停用传感器,就应用程序的 CPU 使用情况而言?这是一个假设吗?您可以通过查看停用传感器后仍然触发的事件来证明这一点吗?请在问题中添加更多细节,以平息任何查看您问题的人“阅读字里行间”的需求。
  • 我使用“Rad studio 10.1 update 1”。当“FSensor.Start”突然执行时,手机CPU使用率增加到20%!并且在我关闭应用程序之前不会减少,即使在代码中我停用并释放“Fsensor”和“FSensorManager”。
  • 为了完整起见,您使用哪个工具来评估 CPU 使用率?
  • 您可以通过什么方式证明是您的传感器导致了这种 CPU 使用率?例如,您能否向我们展示一下此工具的屏幕截图?

标签: delphi firemonkey sensors delphi-10.1-berlin


【解决方案1】:

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

当您在 Android 上 activate the sensor manager 时,您调用 TAndroidSensorManager.Activate。这会尝试为所有已知的 Android 传感器类型实例化 TCustomSensor 后代,快速删除当前设备上不支持的任何内容。这让管理器管理一堆自定义传感器对象,每个对象都创建了一个带有sensor type enumeration valueTNativeSensor 对象,如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 中似乎有效的行为(目前没有更新)的唯一方法是修改 System.Android.Sensors.pas。如果你想同样地测试这个理论,这里是步骤:

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

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

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

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

destructor Destroy; override;

实现析构函数:

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

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

【讨论】:

  • 我将在此记录一个错误。
  • 这完全解决了问题并降低了CPU使用率。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-07
  • 2013-08-04
  • 2021-08-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多