I'm developing an application for my final thesis on computer science, and I need to collect and log accelerometer data. I need to acquire it for a whole day long, so there are serious battery constraints (for instance, I cannot leave the screen on). Also, this isn't a market targeted application, so it is pretty acceptable to do some serious hacking, even low level C/C++ coding, if required.
It is well known that on many devices the listeners for accelerometer events stop generating events when screen goes off (some links regarding this problem: http://code.google.com/p/android/issues/detail?id=3708 , Accelerometer stops delivering samples when the screen is off on Droid/Nexus One even with a WakeLock). I have thoroughly searched for some alternatives, some of them include workarounds that do not work for my device (LG P990, stock ROM).
So what happens is this: When you register an event listener for android accelerometer sensor in a Service, it works fine until the screen is turned off. I have already tried to register the eventListener on a Service, on an IntentService, tried to acquire WakeLocks. Regarding wakelocks, I can verify that the service is still running watching the LOGcat output, but it seems the accelerometer is put into sleep mode. One of the workarounds presented in some of the links is to unregister and re-register the event listener periodically using the thread of an IntentService like in this code snippet bellow
synchronized private static PowerManager.WakeLock getLock(Context context) {
if (lockStatic==null) {
PowerManager mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE);
lockStatic = mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,NAME);
lockStatic.setReferenceCounted(true);
}
return(lockStatic);
}
@Override
protected void onHandleIntent(Intent intent) {
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.unregisterListener(this);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
synchronized (this) {
boolean run = true;
while (run){
try {
wait(1000);
getLock(AccelerometerService.this).acquire();
sensorManager=(SensorManager) getSystemService(SENSOR_SERVICE);
sensorManager.unregisterListener(this);
sensorManager.registerListener(this, sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER), SensorManager.SENSOR_DELAY_NORMAL);
Log.d("Accelerometer service", "tick!");
} catch (Exception e) {
run = false;
Log.d("Accelerometer service", "interrupted; cause: " + e.getMessage());
}
}
}
}
@Override
public void onSensorChanged(SensorEvent event) {
Log.d("accelerometer event received", "xyz: "+ event.values[0] + "," + event.values[1] + "," + event.values[2]);
}
which indeed makes the onSensorChange be called every time we unregister/register the listener. The problem is that the event received contains always the same values, regardless of me shaking the device.
So, basically my questions are: ( bear with me, I'm almost finishing :P )
is it possible to have low level access (C/C++ approach) to the accelerometer hardware WITHOUT registering to an event listener?
is there any other workaround or hack?
could anyone with a more up-to-date phone kindly test if the problem persists in firmware 3.0 and above?
[UPDATE]
Unfortunately, it seems to be a bug with some cellphones. More details in my answer.