2016-10-04 81 views
1

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

+0

你忽略了提及产品版本的用法。请通过编辑您的问题来解决这个问题。 – blong

+0

另外,您是否可以澄清...您是说,如果您的应用程序的CPU使用率指示您尝试停用传感器,则不会停用传感器?这是一个假设吗?您能否通过在停用传感器后看到事件仍然激活来证明这一点? 请在问题中添加更多详细信息,以平息任何看待您问题的人对“在各行之间阅读”的需求。 – blong

+0

我使用“Rad studio 10.1 update 1”。当“FSensor.Start”突然执行时,手机的CPU使用率增加到20%!直到我关闭应用程序,即使在代码中禁用并释放“Fsensor”和“FSensorManager”时也不会减少。 – khafan

回答

6

的问题是下到什么似乎是在FireMonkey Android的传感器执行的监督。会发生什么事情是这样的:

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

到目前为止没有什么大不了的。每个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

  • 新文件夹,进入这个RTL文件夹复制$(BDS)\源\ 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; 

编译并运行和CPU命中应该放弃完全关闭时,传感器对象所有的引用设置为nil

+0

我会在此记录一个错误。 – blong

+2

错误报告:https://quality.embarcadero.com/browse/RSP-16016 – blong

+0

这完全解决了问题并减少了CPU使用率。谢谢你的帮助。 – khafan