This week I was hit by another bug because of not considering impact of Android’s application life cycle management. Last week I had blogged about unexpected behaviour because of using static members in Activity class. The new bug (in another application) was not the same, but it was caused by Android’s application lifecycle management. To be clear, I am not saying there is any problem with the way Android handles application lifecycle.
A user of my application ‘Annotated Call Log’ informed me that when the call duration was very long (more than 45 minutes), the application sometimes did not save call information. The way this application works is – it has a broadcast receiver for getting call status. When a call begins, this class receives notification and it saves call information like phone number, call start time etc in member variables. When the call ends, the receiver class is again called and it then saves call information in the database.
I suspected that the problem could be because Android might have removed the application from memory (Android automatically handles application lifecycle when it needs to reclaim memory for active applications, by removing applications that are inactive for long time, and reloading them when they are required). To verify this, I made a call and during the call I force quit my application. When I ended the call, the data was not saved.
That confirmed my guess. When the call was made, my application was notified and it saved call data in member variables, When Android removed the application, all that data was lost. When call ended, Android activated my application again, but the information that application had saved was not avilable.
The solution was to persist call data when it was received at the beginning of every call. As mentioned in my earlier post, there are different ways to persist data in Android. In that post I opted to save data in the application class. But I could not do that for the current problem, because I needed the data even after application was removed and re-loaded. So I decided to save call information in preferences. And with that application worked fine even after long duration calls.
One thing to note when using preferences is that preferences are not stored until you call commit method on the preference store object. I had overlooked this initially and spent some time trying to figure out why my preferences were not saved.
When writing Android applications you would probably never think that you would lose data stored in the member variables of an object when accessing it from the same class. This is mostly true when the object lives and dies when application is still running. However care must be taken to persist data if the object acts as a listener for external events; because event information saved in the object may not be available in subsequent event notifications.