The document discusses WinRT apps and how they can transition between different states like running, suspended, and terminated. It provides examples of handling state transitions in the app code and accessing app data across states using local app data storage.
2. Our objective is to provide innovation
to society.
We work to shape trends and ideas using
technology.
How do we think• Software Development Engineer - Apps @ BR
Soluções Integradas
• Microsoft Most Valuable Professional (MVP) C#
• Microsoft Certified Professional
• Microsoft Certified Application Developer
• Microsoft Certified Solution Developer
• Microsoft Certified Technology Specialist - Silverlight
• Ex Moderador do Fórum de Silverlight da MSDN Brasil
• São Paulino
• Viciado em games
• Nerd e Bonitão
Ricardo Dorta
http://ricardodorta.net.br
@dortaway
8. sealed partial class App : Application
{
/// <summary>
/// Invoked when the application is launched normally by the end user.
/// </summary>
/// <param name="e">Details about the launch request and process.</param>
protected override async void OnLaunched(LaunchActivatedEventArgs e)
{
// How did the app exit the last time it was run (if at all)
ApplicationExecutionState previousState = e.PreviousExecutionState;
// What kind of launch is this?
ActivationKind activationKind = e.Kind;
// ...
NotRunning
Running
Suspended
Terminated
ClosedByUser
Launch
File
Protocol
VoiceCommand
Etc.
9. Aplicativo entra em modo
“suspended”
Todo o código do aplicativo para
de rodar
Nenhum timer executa o “tick”
Nenhum evento é disparado
O processo ainda está ativo na
memória
O código tem uma “chance” de
ser executado(próximo slide)
http://ricardodorta.net.br
@dortaway
10. sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
}
private async void OnSuspending(object sender, SuspendingEventArgs e)
{
// Ask for a deferral if you need to do async work
var deferral = e.SuspendingOperation.GetDeferral();
// TODO: whatever async work you need to do when suspending
deferral.Complete(); // Then mark the deferral complete
}
11. O mesmo aplicativo vai
para o estado “resumed”
Mesmo processo, mesmos
valores de memória,
portanto os valores de suas
varíaveis estão intactas!
Todo o seu código volta a
rodar
Seu código tem uma
chance de responder...
Launch Back Switcher
12. sealed partial class App : Application
{
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.Resuming += OnResuming;
}
private void OnResuming(object sender, object e)
{
// TODO: whatever you need to do to resume your app
}
http://ricardodorta.net.br
@dortaway
22. Diretório App Data Local
(ou diretório para dados roaming)
12:38
12:38
Jim Jones
Tel: 0111 222 333
Bob Brown
Tel: 0444 555 666
Arthur Abbott
Tel: 0777 888 999
CONTACTS
all 12:38
12:38
Work
Tel: 0111 222 333
Home
Tel: 0444 555 666
Email
jim@jones.com
CONTACTS
Jim Jones
12:38
CONTACTS
Add Phone
Mobile Phone
Phone type
Phone number
0888 777
State
Data
The Windows 8.1 model is arguably simpler than the Windows Phone 8.0 model.
In Windows 8.1 the whole model is based around the idea that the app is run and then while running it might be suspended/resumed so any temporal state needs to be saved across those boundaries and restored. But...suspended might be followed by terminated if the OS feels like it. In that case, when the app is next launched it will be run with a “Hey, you were previously terminated” flag which the app CAN use to restore any volatile state that was saved at the time of suspension. That’s pretty much it.
The Windows Phone 8.0 model is more complex in my view although it achieves the same thing. Some notes;
The Windows Phone 8.0 has a “Closing” event for when the user does a “back” out of the top level of the application. A developer could use this to store their permanent data changes (not their volatile state).
By default, when a user runs a Windows Phone 8.0 app that is already launched, the old app is thrown away and a brand new copy of the app is launched.
A user on Windows Phone 8.0 can make an application dormant at any time and the app gets activated/deactivated events much like suspend/resume of Windows 8.1. A dormant app is (to me) the same as a Windows 8.1 suspended app because it is still in memory but it’s consuming zero CPU.
Windows Phone 8.0 can make a dormant app into a tombstoned app by killing its process in response to resource pressure. This is similar to Windows 8.1 terminating an app except on Windows Phone 8.0 the OS itself actually takes on the responsibility of storing away both the navigation stack for the app and the volatile state dictionaries that the app has populated (global and per page). This is not done by the OS on Windows 8.1 and possibly that’s because not every app on Windows 8.1 has a Frame at all (including e.g. an HTML/JavaScript) app.
The user finds some way of launching your app. The easiest way is for them to tap on your app’s tile whether it’s on the start screen or not.
Other ways of launching an application;
From a secondary tile.
From a file association.
From a protocol association (i.e. mycustomprotocol:// )
From one of the built-in experiences like photos and so on.
The calculator is only being used as an example here.
In the first instance, your App object gets created and its OnLaunched override gets called. That override is passed a bunch of information including the previous executation state of your app which would be “NotRunning” the first time around. It also gets passed the “kind” of activation – i.e. Why has your OnLaunched override been called. Is it a straight launch? Was it in response to handling a protocol? Was it to handle a file? Etc.
NotRunning – user first runs app after installing from store or rebooting the phone. i.e. they have not already run the app in this “session”.
ClosedByUser – user runs the app having previously run it and explicitly closed it down from the task switcher.
Terminated – last time the app ran, the system terminated it.
Running – the app’s still running and the user is running it again from (e.g.) a secondary tile – not sure whether this is ever possible on the phone or not.
Suspended – the app has run, used moved away from it, still suspended in memory and the user runs it again from (e.g.) a secondary tile.
As soon as a user leaves a Windows Phone app, its suspending event fires.
On Windows 8.1, an app has 5 seconds to complete processing in the OnSuspending event handler, although certification requires 2 seconds. It is similar on Windows Phone, but general guidance here is to make sure your suspension processing completes as quickly as possible, otherwise you will start to damage the user experience if it’s not written to be as quick as possible.
Be careful when using the SupensionManager helper class, as that serializes all data that has been stored through it at this time, which has an impact on Suspension processing time.
It’s important to note here that the usual scenario is that the same app process will be resumed. This is different from what happens on the phone today unless a developer has opted in to “Fast Application Resume” which is an unusual thing for a Windows Phone 8 app to do.
If you have code to execute when the app is resuming, you must wire up an event handler for the App.Resuming event, as shown here.
Be careful! Because the debugger is attached to your code when running under debug, your app *will not* suspend when it loses focus, unlike when running normally. For this reason, the Debug Location Toolbar (normally visible when debugging) displays options for suspending, resuming and ‘suspend and shutdown’ (i.e. terminating) your app.
Note that this differs from debugging a Windows Phone Silverlight app which deactivates when your app loses focus, even when running under the debugger.
There’s only one way that a user can close your app – by pressing and holding the Back key to launch the Task Switcher and then tapping the ‘X’ shown on the app screen snapshot.
The app will get its suspending event so it will have saved state.
The next time the app runs it can use this state to “be aware” that the last time it ran it was explicitly closed by the user. The app then has to decide whether to start from a “clean state” or whether to put the user back to where they were at the last time that they used the app.
The guidance is that “each app is different” and it’s up to the app to decide whether to put the user back where they were previously or to start a clean run of the app. If the app is going to attempt to put the user back to where they were previously then it’s almost certainly going to want to factor in the amount of time that has elapsed and what the user was doing at the point where they closed the app.
Demo 1. Simple demo of how an app with a temporal nature doesn’t survive suspend/resume. Described in the document alongside the slide-deck.
If the system becomes short of memory, an app is selected for termination based on internal algorithms based on how long ago the app was running, and the amount of memory that will be freed by terminating it.
If an app is removed from the task switcher and no longer shown there (without being closed by the user) then it has been terminated by the OS.
Unlike Windows 8.1, the task switcher shows only running apps. Task switcher will not show an entry for an app that the system has terminated – the user would get back to that terminated app.
[Review this]
When thinking about how to restart an app that has been terminated, you (the developer) must consider what the users’ expectations will be.
They will be unaware that the system has chosen to terminate their app, so their normal expectation will usually be that the app should pick up from where it left off the last time they used it – unless the state the app should present to a user will have other factors that will affect it, such as
‘were they engaged in an activity that having been interrupted, the reasonable expectation might be to back out of that activity and resume at some earlier state’
or ‘has so much time elapsed that really the app should restart as if launched anew’?
Examples of what ‘recent activity’ might mean;
User is timing their workout session with a stopwatch. Stopwatch is ticking down from 60 minutes. User expects that if the app is terminated at minute 32 then when they resume at minute 48 the timer is preserved.
User is level 3 deep in a hierarchy of their photos. They move away to browse the app. They return to the app. They expect to be back on their previous photo.
User is navigating through a 3 page Wizard to register their sale on an auction web site. They have typed in lots of data that they have not yet submitted. They revisit the app 2 days later and do not expect to have to enter that data again.
User has entered some text into a textbox and has made a selection in a combo box. They navigate to another app momentarily and do not expect to have to re-enter those values when they return to the original app.
This slide builds (a lot). The idea here is that the user runs the app, it loads some contacts from some permanent state and then the user taps on one which causes navigation and then they tap on some ‘add’ button to add a new phone number and they enter the type of the phone number and part of the number itself but they have not hit save.
The slide highlights in blue that the contact details are coming from permanent data (whether loaded once or loaded on a per page basis) but that the volatile state includes the navigation stack (including parameters) and the current values on the “Phone Type” and “Phone Number” fields on the 3rd page.
The application developer has quite a lot to think about when saving and restoring state: navigation history, navigation arguments and volatile state data.
The SuspensionManager and NavigationHelper classes are designed to help with these tasks. See the comments in these classes for information on how to use them correctly.
This is a 2 slide build.
App runs up, creates Frame, registers with Suspension Manager which has a slot for Global State and now knows about this frame.
Frame then navigates to Page 1 (possibly with a parameter) which means it has a little navigation history and the page creates a navigation helper.
User then navigates to Page 2. The navigation helper fires its SaveState event into Page 1 which populates a dictionary which the Navigation Helper saves back to the Suspension Manager as the state for Page 1.
Page 2 is created with its own NavigationHelper and our navigation history is now a little longer.
The user now moves back to the start screen and so the OS suspends the app which fires the Suspending event which is handled by calling SuspensionManager.SaveAsync(). Next slide…
SaveAsync() calls into its registered frames asking them to save state. So…we grab the navigation state of the Frame in question but it also asks its Page and (via which) the corresponding NavigationHelper to do the right thing which fires the SaveState event which writes the state back into a new “Page 2” dictionary back in the Suspension Manager.
The manager can now grab the global dictionary, the page 1 dictionary, the page 2 dictionary, the navigation state (including parameters) and serialize them all to disk using the DataContractSerializer to do its work.
Seems over-engineered to me but that’s how it works as far as I understand it.