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

1 delphi sensor firemonkey 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;
Run Code Online (Sandbox Code Playgroud)

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

FSensor.Stop;
FSensorManager.Deactivate;
FSensor.Free;
FSensorManager.Free;
Run Code Online (Sandbox Code Playgroud)

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

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

之前

按下按钮并激活传感器后

blo*_*ong 6

问题在于FireMonkey Android传感器实施中的疏忽.这是怎么回事:

当您激活传感器管理器在Android上调用TAndroidSensorManager.Activate.这会尝试TCustomSensor为所有已知的Android传感器类型实例化后代,快速删除当前设备上不支持的任何内容.这使得管理器管理一堆自定义传感器对象,每个对象都创建了一个TNativeSensor具有传感器类型枚举值的对象,如Androidapi.Sensor单元中所定义.

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

启动传感器会导致底层TNativeSensor调用NDK ASensorEventQueue_enableSensor例程,这就是CPU遭受重击的地方.

停止自定义传感器对象调用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;
Run Code Online (Sandbox Code Playgroud)

实现析构函数:

destructor TNativeSensor.Destroy;
begin
  ASensorManager_destroyEventQueue(FSensorManager, FNativeEventQueue);
  inherited;
end;
Run Code Online (Sandbox Code Playgroud)

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