As of Android 2.2 (a.k.a. Froyo) this problem has been fixed.
To get notified about sensor changes, an application has to explicitly register itself and pick what kind of sensors it wants to monitor. For this we use the SensorManager API. For example, an application can register to be informed about orientation changes by doing something like this:
The last call above, SensorManager.registerListener() receives as the first parameter an implementation of the SensorEventListener interface. This interface includes 2 methods that will be called when the accuracy of a sensor changes (for example, increased/decreased GPS accuracy) and when the status of the sensor change (changed position, for example). Here is very simple example of a SensorEventListener interface implementation:
Whenever you are done with getting updates from a sensor, you should tell the system about that too by calling:
Activities x Services.
In a very simplified way, an Activity is an application (or part of an application) that only exists when you are seeing it. Usually an Activity corresponds to one of the possible different screens you see in an application. It is very common for a game, for example, to be composed of a single Activity. When a phone enters standby mode, an Activity that was previously being show is "frozen" and restored whenever needed. During this time, the activity is not running.
A Service, on the other hand, usually has no visual part (except for notifications it may generate) and, contrary to an Activity, runs even when the phone is in standby mode.. A service can be used, for example, to fetch news information periodically or, for the purposes of this document, to monitor a sensor and take action based on changes to it.
Monitoring sensors works very well in Android and Activity derived classes that make use of this will have no problem. Up until around July, 2009, this was also true for Service derived classes. But then something changed.
Let's start with a very simple implementation of a Service that wants to use the orientation sensor:
Whenever the service above is started, it will have its onSensorChanged() method called whenever you move the phone around (in some phones, the sensors are so sensitive that even with the phone being completely still, this methos will still be called with very small deltas since the last call). This works as expected until we get the problem mentioned above and what happens is that whenever the phone enters standby mode, onSensorChanged() is not called anymore. The result is that although the service itself is running, it won't be doing anything. This basically broke every single app in the Market that expected to get notifications even in standby mode.
As I wrote an application that was also affected by this problem (Silencer) and this led me to try to find some kind of workaround. It was just by accident that I discovered the solution: If you re-register for getting sensor notifications after the phone enters standby mode, it starts getting notifications again!
Here are the status of phones that I know about:
In other words, my workaround seems to work only on Motorola phones so far. Also, all recent HTC phones seem to completelly disable the accelerometer on standby (probably to save battery, although the battery usage does not seem to be an issue in the Motorola phones mentioned). An interesting case is the HTC G1 as the accelerometer works in standby mode even without my workaround, but you need to get a CPU lock and that drains the battery in around 8 hours without the phone doing anything else.
Here is one way to implemented this solution using the service above (lines added are in blue and ines changed in light green):
// BroadcastReceiver for handling ACTION_SCREEN_OFF.
As you can see above, we added a BroadcastReceiver for the ACTION_SCREEN_OFF Intent and this lets us get notified about when the screen goes off (which happens when the phone enters standby mode), When this happens, we unregister for our sensor and then register again.
There is definitely some bug in Android concerning this. Either the issue described here is a feature and the fact that there is a workaround is a bug or the issue is really a bug and it should be fixed so the workaround is not needed. Some points that I think are relevant to mention here: