My app creates a Service
that overrides onStartCommand to create a SensorManager
and attach a SensorEventListener
to one of the sensors:
public class AccelerometerService extends Service {
private SensorManager sensorManager;
private Sensor sensor;
private SensorEventListener activeListener;
// ...
@Override
public int onStartCommand(Intent intent, int flags, int startid) {
// ...
sensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
sensor = sensorManager.getDefaultSensor(Sensor.TYPE_LINEAR_ACCELERATION);
activeListener = new SensorEventListener() {
@Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
}
@Override
public void onSensorChanged(SensorEvent event) {
Log.i("PluckLock", "" + event.values[0]);
}
};
sensorManager.registerListener(activeListener, sensor, SensorManager.SENSOR_DELAY_NORMAL);
return START_STICKY;
}
// ...
}
The full code is available on GitHub.
I want to override Service
's onDestroy()
method and, in it, kill the sensor:
sensorManager.unregisterListener(activeListener);
But when I do this, nothing actually happens! My onSensorChanged()
listener continues to receive correct values from the accelerometer (or software LINEAR_ACCELERATION sensor, in my case). The problem, of course, is quoted here in the docs:
Always make sure to disable sensors you don't need, especially when your activity is paused. Failing to do so can drain the battery in just a few hours.
My app only needs to ping the accelerometer for as long as the screen is actually unlocked. I've implemented (and verified the correct function of) BroadcastReceiver
s that destroy the Service
when the phone is locked, successfully calling its onDestroy()
method. But nothing actually happens once I try to unregister the listeners.
I've found a few others asking this question, with no resolution.
I can only assume it is an API bug, and that there is really no good way to kill these sensors once I've started grabbing data from them. I have tried setting the SensorManager
, Sensor
, and SensorEventListener
to null, as well as trying to register a null sensor listener with the manager. None of these have any effect on the polling.
My current "workaround" has almost no effect on battery life. I have a private boolean in my class's definition that I set to true
or false
depending on whether I want sensor values. In my onSensorChanged()
method, I immediately return
if the sensor listener is supposed to be inactive. But by then, it is too late: the brunt of the work being performed by the OS (getting sensor values) occurs before I can manage to leave the onSensorChanged()
method, so battery life is still horrendous for as long as my service is running.
My real question here, barring some miracle real solution, is what can I do to stop getting sensor values? Obviously, unregistering the sensor listener does not work at this point; even setting everything to null and destroying the service has no effect. But there must be some way to indicate to the operating system that my app doesn't require use of the sensor values anymore. Is there some way to kill my entire app, only restarting it when the phone is unlocked? Maybe that would let the operating system know that my app's not in need of values anymore. Really, any solution that legitimately stops polling the sensor but gives me some way to restart it, even if the code is ugly, would make me happy.
The minimum API level for my project is 9.
I faced similar issue.
Workaround to stop the sensor from draining the battery.
I used a static boolean mIsSensorUpdateEnabled
. Set it to 'false' when you want to stop getting values from sensors.
And in onSensorChanged() method, check the value of the boolean variable and again make to call to unregister the sensors. And this time, it works. The sensors would be unregistered and you will no longer get onSensorChanged callback.
public class MainActivity extends Activity implements SensorEventListener{
private static boolean mIsSensorUpdateEnabled = false;
private SensorManager mSensorManager;
private Sensor mAccelerometer;
@override
protected void onCreate(){
mSensorManager = (SensorManager) getSystemService(Context.SENSOR_SERVICE);
}
private startSensors(){
mAccelerometer = mSensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
int delay = 100000; //in microseconds equivalent to 0.1 sec
mSensorManager.registerListener(this,
mAccelerometer,
delay
);
mIsSensorUpdateEnabled =true;
}
private stopSensors(){
mSensorManager.unregisterListener(this, mAccelerometer);
mIsSensorUpdateEnabled =false;
}
@Override
public void onSensorChanged(SensorEvent event) {
if (!mIsSensorUpdateEnabled) {
stopSensors();
Log.e("SensorMM", "SensorUpdate disabled. returning");
return;
}
//Do other work with sensor data
}
}`
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With