1

I'm trying to create a foreground service that can keep track of the linear acceleration of the phone, using the Accelerometer sensor. I have a ForegroundService class that implements Service() and SensorEventListener. I have two global variables that I initialize like this:

mSensorManager = getSystemService(SENSOR_SERVICE) as SensorManager
mAccelerometer = mSensorManager!!.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION)

I then register the listener, then override onSensorChanged(), where I should log some values, but nothing is displayed (which means the function does not run at all). Why could this be? Thank you.

Edit: Having done more testing since I've posted the answer, I've noticed that the problem is that Android does not update the values on the Sensors (at least the Linear Acceleration one) when the screen is off. The service clearly keeps running, since other tasks (like the location) do get updates, but the Linear Acceleration sensor stops. Once the screen is turned on again it starts to get updates like it should. How to fix this?

Enrico Cortinovis
  • 811
  • 3
  • 8
  • 31
  • Did you actually request updates anywhere? I don't see it in your code. All you got was a representation of the sensor. – Gabe Sechan Oct 28 '21 at 05:08
  • @GabeSechan Shouldn’t it be enough to implement ‘SensorEventListener’ and to override the ‘onSensorChanged’ method? It was working in a normal activity (when the screen was on, etc.). – Enrico Cortinovis Oct 28 '21 at 05:34
  • No, just defining functions isn't enough. You need to ask for the OS to start sending your data. The call is sensorManager.registerListener(listener, sensor, frequency). Also remember to unregister when done. – Gabe Sechan Oct 28 '21 at 13:32

1 Answers1

-1

Try ensuring that you are creating an actual foreground service (with a notification and a notification channel). You also requested an appropriate permission <uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> and registered a listener for your sensor like so:

mSensorManager.registerListener(
    this, // if called in your ForegroundService
    mAccelerometer,
    SensorManager.SENSOR_DELAY_NORMAL
)

and unregistered it:

override fun onDestroy() {
    mSensorManager.unregisterListener(this)
}

finally, you are starting the service from an activity or a receiver of some sort with startService and call startForeground(id, notification) in service's onStartCommand.

Jakub Licznerski
  • 1,008
  • 1
  • 17
  • 33
  • Thank you for your answer. I've done more testing since I had posted the question, and it seems that it only does not work when the screen is off. The service keeps running because other tasks do work, but it seems that Android does not update data on the sensors when the screen is off... How to fix this? – Enrico Cortinovis Nov 01 '21 at 20:56
  • Yes, that is true unfortunately. The only way is to prevent the screen from turning off. https://stackoverflow.com/questions/46805637/how-to-get-sensor-data-in-service-when-screen-is-turned-off – Jakub Licznerski Nov 01 '21 at 21:11
  • I think I had read that it worked on some devices but didn't on others. In that case, the app could possibly check or make the user check if it works with the foreground service as well, or not. Do you think that could work? – Enrico Cortinovis Nov 02 '21 at 08:32
  • Yeah, but I'd suspect that mostly it doesn't. Android has battery usage optimization policies which are rather strict. Even though it may depend on the hardware as well, you'd struggle to maintain the app over future Android versions for example. I suspect you cannot keep the screen on when you gather sensory data? Maybe instead of a wakelock you'd try with batching sensory data https://stackoverflow.com/questions/30390148/step-counter-in-android-always-on – Jakub Licznerski Nov 02 '21 at 08:42
  • It would be a bit of a problem to keep the screen on all the time, yes. What I'm doing now is I'm turning the activity to complitely black and automatically turning the screen brightness to the minimum, and this isn't really as I'd like to keep it, if possible. If a wakelock is used to prevent the phone from going to sleep, would it be possible to still turn the screen complitely off but keep the device on to be able to still get the sensor data? – Enrico Cortinovis Nov 02 '21 at 08:52
  • you don't really need an activity when you have a foreground service, additionally acquicing the wake lock does not necesarily mean that the screen will be turned on. The partial wakelock, which should be sufficient for sensors to turn on, would not trigger screen backlight (https://developer.android.com/reference/android/os/PowerManager#PARTIAL_WAKE_LOCK). Still having a wakelock acquired all the time has big impact on the battery drain. Hence the batching solution I linked in the last comment. – Jakub Licznerski Nov 02 '21 at 09:52
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/238800/discussion-between-enrico-cortinovis-and-jakub-licznerski). – Enrico Cortinovis Nov 02 '21 at 11:49