3

Question:
What are best practices for a persistent/always-on sensor data collection service in an embedded setting? Permanently attached power source and no user to aggravate with another running service, so no battery life or usability concerns.

Plan:
A local Service, startForeground(), START_STICKY, probably acquiring a PARTIAL_WAKE_LOCK, starting on BOOT_COMPLETED. This will not be a Play Store application. I will have an activity which can bind to the service to get feedback, set preferences, and manually start/stop the service if so desired. Since this will be running on a dedicated device with no UI and will not be reliant on battery power, which should bypass most of the usual concerns with services, is there anything else I can/should do to ensure the service runs at a high priority with the least likely chance it will be killed? Is there a better option than a service implemented in this way?


Background (optional reading):
I've written a multi-threaded Activity-based app which starts via a broadcast receiver on boot completed, runs through validations, runs a data collection thread, a data transmission thread which connects to a remote service, and executes other tasks which aren't pertinent to this discussion. I need to transition to a Service-based solution. From what I've read, best practices for a service which collects sensor data usually involve periodically starting the service via an AlarmManager. This will not work in my case.

rsg
  • 53
  • 5
  • 1
    Great question! I would recommend distilling this down a bit, people will be more willing to answer if they don't have to read too much. – Zach Spencer Mar 12 '14 at 20:20
  • Thanks for the suggestion! I distilled as much as possible – rsg Mar 14 '14 at 03:45
  • Where did you put the sensor controller? If the service is there just to keep the app running, the controller can be a Singleton, or held by some object in the Application class, right? – Asaf Pinhassi Mar 21 '20 at 04:44

1 Answers1

0

In general, there's no issue with a Service receiving sensor data. But, be sure that you are processing any data on a background thread rather than in the SensorListener callbacks. If you need to keep receiving data even when the screen turns off, you'll need to hold a partial wakelock to prevent the system from going to a lower power state. Battery life is affected with the "foreground" service only because you are leaving the sensor activated at some interval. Otherwise, there's nothing magical about a service being considered foreground, other than it has a very low chance of being killed off by the framework.

You may also need to make sure the accuracy of the sensor doesn't change (via the listener callback) and if it is different than what your algorithms expect, you'll have to re-configure it with the SensorManager. An Activity based solution won't really do what you are talking about as the Activity is only "running" when it is visible to the user.

Larry Schiefer
  • 15,687
  • 2
  • 27
  • 33
  • Thank you, I hadn't considered that. I think `SensorListener` is deprecated, I am using `SensorEventListener` in my current Activity though. Do you think that will be a problem in a Service? I think what you're saying is to, for example, populate instance variables in `onSensorChanged()` or `onLocationChanged()`, then have another thread reading and processing those values? – rsg Mar 14 '14 at 03:57
  • My apologies, I meant the `SensorEventListener` rather than `SensorListener`. It's no problem to use in a service, you just have to manage your service appropriately so it is long running and can appropriately keep the device awake when needed (i.e. hold a wake lock). It's best to process the data in another thread, but that could be a simple as posting a `Runnable` which has a reference to the `SensorEvent` data to a `Handler` bound to another thread. – Larry Schiefer Mar 14 '14 at 04:07
  • OP or @LarrySchiefer, can you guys tell me how to call getSystemService() inside a service? If I want to do that, I have to put in the Conext of the activity that start the service, not the running service itself, due to the null base context. If you are not sure what I'm asking, this is the fully-explained question: http://stackoverflow.com/questions/24970677/calling-getsystemservice-inside-a-service, Your help is much appriecated. – EyeQ Tech Jul 28 '14 at 00:26
  • You can call `getSystemService()` from your `Service` without an issue. The `Service` object, which you service extended, is derived from the `Context` object as well. You do not need (nor would you want to use) an `Activity` context. That other question appears as though the person asking the question is creating the service manually rather than using `startService()` or `bindService()`. You have to start via these framework calls, otherwise your service will not properly initialize and go through its lifecycle. – Larry Schiefer Jul 28 '14 at 14:41