In the previous episode of this series about how to develop a Windows Phone application from scratch we used the Isolated Storage Explorer Tool to take a look at the contents of the ApplicationSettings, stored in IsolatedStorage on the device or emulator. This time we continue dealing with our application settings, because we are going to talk about Fast Application Switching and Tombstoning.
As you probably know, only one application can be running in the foreground on a Windows Phone. That application can use as much resources as it needs and should be as responsive as possible to give end users a great experience. Typically, users switch often between applications. They might not even think about different applications, because they are most likely very task oriented. To give end users the best experience, our applications share a responsibility with other applications and with the operating system.
If our application is currently running in the foreground, there are two important reasons for our application to stop running in the foreground:
- The user terminates our application by pressing the Back Key on the phone until the entire back stack of pages for our application is empty.
- Our application is interrupted because some sort of an event occurred.
The first situation is simple. When our application is terminating, it is our responsibility to store information that we want to persist until the next time our application is running. This is what we did for EvenTiles in part 5 of the series, using the Application_Launching and Application_Closing methods that are defined in the App.xaml.cs file.
NOTE: The description of Fast Application Switching and Tombstoning in this article is valid for Windows Phone Mango, not for previous versions of the operating system.
The following picture shows our application running over time. The user navigated to the SettingsPage on EvenTiles, modified the string value and decided to use the Start Key on the phone to start another application. After a while, the user returns to our application by pressing the Back Key until our SettingsPage is visible again.
For the user, this experience is great, because when they come back to our application, it shows up exactly as it was when they moved our application to the background. The operating system simply keeps our application in memory. There are some restrictions with regards to applications using certain resources like the camera. To keep our story lean and mean we will omit those. When the user starts many applications (thus putting more and more applications in the background), at some time the amount of available memory gets so low that another application can no longer be started. In this situation, the operating system decides to remove the oldest application in the background from memory, saving just minimal state information for that application. In this situation, the application that was just removed from memory is said to be Tombstoned. To restore our application from being tombstoned, we not only need to reload our application settings (as we did on the Application_Launching event), but most likely we also need to restore additional data. The Operating System ‘remembers’ the page in our application the user had visible when we were tombstoned. It is our responsibility to restore data that the user entered on that page (for instance the contents of a Textbox).
When our application is send to the background, several things happen. On the page that is currently visible, an OnNavigatedFrom event will occur. Also, the Application_Deactivated method in the App.xaml.cs file will be called. When an application is switched to the background, basically three things can happen to it:
- The application will become the foreground application again without having entered the tombstone state. In this situation the application can benefit from Fast Application Switching.
- The application got tombstoned, but it will become the foreground application after a while. In this situation the application must restore more state information.
- The user starts the application again by clicking its icon or tile on the start screen. In this situation, the previous instance of the application is removed and the user should see the application in its initial state.
When you are debugging your application in Visual Studio, the default behavior when the application is moved to the background is for it to remain in memory. However, by modifying one of the project properties (as shown in the screen dump on the left), you can force the application to become tombstoned, regardless from the amount of free memory on the device (emulator). In this way, we as developers have the possibility to test our applications in either state they enter when being moved to the background. You should make sure that you test the tombstone scenario for your application. For instance, if EvenTiles with its current functionality is tested for tombstoning it will crash. This currently has to do with the way that data is initialized. In EvenTiles, we have a string property defined in App.xaml.cs that will later be used to write information to the back side of our Secondary Tile. The SettingsPage already makes use of this property. However, we are initializing this property, named ActualBackSecContent when the application is started in the Application_Launching method.
- // Code to execute when the application is launching (eg, from Start)
- // This code will not execute when the application is reactivated
- private void Application_Launching(object sender, LaunchingEventArgs e)
- {
- if (!appSettings.Contains(keyActSecBackContent))
- {
- appSettings[keyActSecBackContent] = DefaultSecBackContent;
- }
- ActualSecBackContent = (string)appSettings[keyActSecBackContent];
- }
- // Code to execute when the application is activated (brought to foreground)
- // This code will not execute when the application is first launched
- private void Application_Activated(object sender, ActivatedEventArgs e)
- {
- }
- // Code to execute when the application is deactivated (sent to background)
- // This code will not execute when the application is closing
- private void Application_Deactivated(object sender, DeactivatedEventArgs e)
- {
- }
- // Code to execute when the application is closing (eg, user hit Back)
- // This code will not execute when the application is deactivated
- private void Application_Closing(object sender, ClosingEventArgs e)
- {
- appSettings[keyActSecBackContent] = ActualSecBackContent;
- }
Even though our application is removed from memory when it is tombstoned, if the user navigates through the back stack using the back key on the phone, eventually they will return back to a page of our application. In order to make this happen in case our application was tombstoned, it has to be reloaded again to memory to become active. In this situation, minimal state information was stored by the operating system (for instance which page was the last page the user saw when our application got tombstoned). On returning from tombstoning we will return to that page, but since the application needs to be started completely, classes have to be newly created and code in constructors of those classes will therefor be executed. To distinguish between starting a fresh copy of the application or returning from the background, Application_Launching (fresh restart) or Application_Activated (tombstoning or fast application switching) is called in our App.xaml.cs file. If our application was still in memory, there is no problem, after all, the property ActualSecBackContent still holds its value. If we are returning from a tombstoning situation we do have a problem, since Application_Activated will be called instead of Application_Launching. That is why the exception that is shown in the screen dump above was thrown.
You might think that this problem could easily be solved by initializing the ActualSecBackContent property in the constructor of our App class, but that would mean that we don’t benefit from fast application switching (the situation where our application remains in memory, even though it is in the background). A better solution is to make use of the Application_Activated event as follows:
- // Code to execute when the application is activated (brought to foreground)
- // This code will not execute when the application is first launched
- private void Application_Activated(object sender, ActivatedEventArgs e)
- {
- if (!e.IsApplicationInstancePreserved)
- {
- // The application was not preserved in memory, so we were tombstoned
- // Only in this case we need to re-initialize ActualSecBackContent
- ActualSecBackContent = (string)appSettings[keyActSecBackContent];
- }
- }
- // Code to execute when the application is deactivated (sent to background)
- // This code will not execute when the application is closing
- private void Application_Deactivated(object sender, DeactivatedEventArgs e)
- {
- appSettings[keyActSecBackContent] = ActualSecBackContent;
- }
If the application is becoming the foreground application, we check if we were still available in memory. If so (e.IsApplicationInstancePreserved == true) we don’t do anything, otherwise we just initialize the ActualSecBackContent property. There is nothing else to do, because we know that a value with that particular Settings key already is available, since the application was launched at some time before Application_Activated was called. If an application is moved to the background you want to make sure to save everything in such a way that you assume that your application will never return to the background. After all, the application can stay in memory, it might be tombstoned but there is also a possibility that the user starts a brand new instance of the application from the start menu. In the latter case, the existing instance of the application in the background will be removed by the operating system.
NOTE: If you are upgrading an existing application for Mango, at the very least (after converting your project in Visual Studio) you need to only retrieve stored data in the Application_Activated method when e.IsApplicationInstancePreserved is false. In that way your application will immediately benefit from fast application switching.
The following video shows the actions we took to prevent the EvenTiles application from crashing after being reactivated from a tombstoned state:
With the changes that were described so far added to our application, it no longer crashes if we are returning from a tombstone state. There are however more things that need to be considered when the application is brought back from background to foreground. In the next Episode of EvenTiles we will take a look at restoring Focus on an input control when returning from the background.
If you want to see EvenTiles already in action on your Windows Phone, you can install the latest release from Marketplace. Remember that this application is not meant to be extremely useful, although it contains similar functionality that “serious” applications have. All functionality that you can find in the released version of EvenTiles will be covered in the upcoming episodes of this blog series, together with all source code. Just go ahead and get your free copy of EvenTiles from Marketplace at this location: http://www.windowsphone.com/en-US/search?q=EvenTiles (or search on your phone for EvenTiles in the Marketplace application).
