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使用量增加的屏幕截图:
问题在于FireMonkey Android传感器实施中的疏忽.这是怎么回事:
当您激活传感器管理器在Android上调用TAndroidSensorManager.Activate.这会尝试TCustomSensor为所有已知的Android传感器类型实例化后代,快速删除当前设备上不支持的任何内容.这使得管理器管理一堆自定义传感器对象,每个对象都创建了一个TNativeSensor具有传感器类型枚举值的对象,如Androidapi.Sensor单元中所定义.
到目前为止没什么大事.每个TNativeSensor对象构造函数都调用了几个NDK例程来设置:ASensorManager_getDefaultSensor和ASensorManager_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.