Ler*_*ohr 8 android android-sensors
几天来,我一直在努力解决以下问题:我想在屏幕关闭时使用 Android 设备上的重力传感器计算运动模式。我正在使用我在前台启动的绑定服务(带有 Android 8 的通知以使其保持运行),并且在屏幕打开时一切正常。即使应用程序不在前台运行,一切正常。
然而,一旦显示器关闭,非常奇怪的事情就会开始发生:传感器数据仍在处理中,并且在一定程度上计算了移动,但结果非常糟糕且不准确。此外,如果再次打开屏幕,该应用程序的行为非常奇怪。有时应用程序按预期工作,但有时似乎旧传感器事件被延迟处理并在以后计数。从这个时候开始,整个算法就不能顺利运行了。还有什么有趣的:如果设备已插入并且我在 Android Studio 中使用控制台观察一切,一切都运行得非常完美,即使屏幕关闭也是如此。但是,如果拔掉设备,结果又会出错。
我尝试了很多事情:在主线程上运行所有内容,在另一个线程上,使用 IntentService,将 App 设置为Doze的白名单,在屏幕关闭时不向 MainActivity 发送数据,并遵循本指南(我正在开发 Galaxy J5) - 但没有任何效果。似乎 Android 系统的 SensorFusion 算法在待机状态下关闭,即使有注册的监听器,或者三星在后台运行了一些电池优化并限制了 CPU 操作。还有其他可能导致这种行为的原因吗?因此,如果应用程序处于活动状态,如果它在后台运行,但在设备处于睡眠状态时运行良好?
值得一提的是:我正在为 Cordova 开发一个插件。
这是我的代码
public class SensorPlugin extends CordovaPlugin implements ServiceClass.Delegate {
public void initialize() {
...
Intent serviceIntent = new Intent(applicationContext, ServiceClass.class);
applicationContext.bindService(serviceIntent, serviceConnection,
Context.BIND_AUTO_CREATE);
}
public void start() {
serviceClass.startMeasuring();
}
@Override
public void updateMovementCount(int count) {
...
};
}
Run Code Online (Sandbox Code Playgroud)
public class ServiceClass extends Service implements OtherClass.Delegate {
private volatile boolean isMeasuring;
private volatile double gravityX;
private volatile double gravityY;
private volatile double gravityZ;
public IBinder onBind(Intent intent) {
sensorManager = (SensorManager) getApplicationContext().
getSystemService(Context.SENSOR_SERVICE);
startForeground(1, buildNotification());
return mBinder;
}
public void startMeasuring() {
assert sensorManager != null;
Sensor gravity = sensorManager.getDefaultSensor(Sensor.TYPE_GRAVITY);
sensorManager.registerListener(this, gravity,
SensorManager.SENSOR_DELAY_GAME);
isTracking = true;
SensorThread sensorThread = new SensorThread();
sensorThread();
}
@Override
public void onSensorChanged(SensorEvent event) {
gravityX = event.values[0];
gravityY = event.values[1];
gravityZ = event.values[2];
}
// This is an interface method from another class that I wrote
// (see below). For which I set this class as delegate and as soon
// as the other class finds a pattern in the data it calls this method
@Override
public void movementPatternDidChange(int count) {
// Usually I send this count to the main class with
// the same delegation pattern
delegate.updateMovementCount(count);
}
class SensorProcessingThread extends Thread {
Handler handler = new Handler();
// I use another runnable here, as I only want to process 10
// sensor events per second. The sensor manager usually returns
// way more which I don't need.
private Runnable sensorProcessingRunnable = new Runnable() {
public void run() {
otherClass.processMotionData(gravityX, gravityY, gravityZ);
if (isMeasuring) {
handler.postDelayed(this, 100);
}
}
};
@Override
public void run() {
if (!isMeasuring) {
return;
}
handler.postDelayed(sensorProcessingRunnable, 100);
}
}
}
Run Code Online (Sandbox Code Playgroud)
在此期间我测试了很多。我现在使用Apache Commons Primitives Collections以获得更好的性能(而不是大型 FastUtil,这也导致了这个过去错误)。
我还在两台设备上测试了该应用程序,一台相当老的 LG G2 和 Galaxy J5。两者的问题是一样的。所以可能不是制造商特定的。Android Studio Profiler 报告两种设备的 CPU 使用率平均为 1-3%,因此我认为过载可能不是原因。我还测试了一个 TimerTask 和 Timer,而不是一个 Runnable 和 Handler,但效果不佳。
同样非常有趣的是:我尝试按照此处的说明通过 Wifi 调试应用程序,即使设备休眠且屏幕关闭,该应用程序也能正常运行。调试这个问题非常困难,因为即使没有连接电缆,应用程序在我调试它时也能正常运行。我不知道我还能做什么。
| 归档时间: |
|
| 查看次数: |
1942 次 |
| 最近记录: |