当我尝试在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使用量增加的屏幕截图:
答案 0 :(得分:6)
问题在于FireMonkey Android传感器实施中的疏忽。会发生什么:
当您在Android上activate the sensor manager时,您会调用TAndroidSensorManager.Activate
。这会尝试为所有已知的Android传感器类型实例化TCustomSensor
后代,快速删除当前设备上不支持的任何内容。这使得管理器管理一堆自定义传感器对象,每个对象都创建了一个TNativeSensor
对象,其中sensor type enumeration value与Androidapi.Sensor单元中定义的一样。
到目前为止没什么大不了的。每个TNativeSensor
对象构造函数都调用了几个NDK例程来设置:ASensorManager_getDefaultSensor
和ASensorManager_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命中应该完全下降。