Reputation: 269
I am trying to implement Fast app resume for Windows Phone 8. I followed the link at MSDN.
And here is the code in XAML:
<Tasks>
<DefaultTask Name="_default" NavigationPage="MainPage.xaml" ActivationPolicy="Resume"/>
</Tasks>
And this is the code in app.xaml.cs
public static PhoneApplicationFrame RootFrame { get; private set; }
bool wasRelaunched = false;
bool mustClearPagestack = false;
IsolatedStorageSettings settings = IsolatedStorageSettings.ApplicationSettings;
enum SessionType
{
None,
Home,
DeepLink
}
private SessionType sessionType = SessionType.None;
public App()
{
UnhandledException += Application_UnhandledException;
InitializeComponent();
InitializePhoneApplication();
InitializeLanguage();
if (Debugger.IsAttached)
{
Application.Current.Host.Settings.EnableFrameRateCounter =true;
PhoneApplicationService.Current.UserIdleDetectionMode = IdleDetectionMode.Disabled;
}
}
private void Application_Launching(object sender, LaunchingEventArgs e)
{
RemoveCurrentDeactivationSettings();
}
private void Application_Activated(object sender, ActivatedEventArgs e)
{
mustClearPagestack = CheckDeactivationTimeStamp();
if (!e.IsApplicationInstancePreserved)
{
RestoreSessionType();
}
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
SaveCurrentDeactivationSettings();
}
private void Application_Closing(object sender, ClosingEventArgs e)
{
RemoveCurrentDeactivationSettings();
}
private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
if (Debugger.IsAttached)
{
Debugger.Break();
}
}
private void Application_UnhandledException(object sender,ApplicationUnhandledExceptionEventArgs e)
{
if (Debugger.IsAttached)
{
Debugger.Break();
}
}
private bool phoneApplicationInitialized = false;
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
RootFrame= new PhoneApplicationFrame();
RootFrame.Background = new SolidColorBrush(Color.FromArgb(255, 27, 200, 174));
RootFrame.Navigated += CompleteInitializePhoneApplication;
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
RootFrame.Navigated += CheckForResetNavigation;
RootFrame.Navigating += RootFrame_Navigating;
phoneApplicationInitialized = true;
}
void RootFrame_Navigating(object sender, NavigatingCancelEventArgs e)
{
if (e.Uri.ToString().Contains(@"/MainPage.xaml") == true && !AppPrefManager.Instance.IsFastAppResumeEnabled)
{
RootFrame.Dispatcher.BeginInvoke(delegate
{
if (!AppPrefManager.Instance.IsVirginLaunchCompleted)
{
RootFrame.Navigate(new Uri(Constants.kIntroPage, UriKind.Relative));
}
else
{
RootFrame.Navigate(new Uri(Constants.kMainPage, UriKind.Relative));
}
});
e.Cancel = true;
}
if (sessionType == SessionType.None && e.NavigationMode == NavigationMode.New)
{
if (e.Uri.ToString().Contains("DeepLink=true"))
{
sessionType = SessionType.DeepLink;
}
else if (e.Uri.ToString().Contains("/MainPage.xaml"))
{
sessionType = SessionType.Home;
}
}
if (e.NavigationMode == NavigationMode.Reset)
{
wasRelaunched = true;
}
else if (e.NavigationMode == NavigationMode.New && wasRelaunched)
{
wasRelaunched = false;
if (e.Uri.ToString().Contains("DeepLink=true"))
{
sessionType = SessionType.DeepLink;
}
else if (e.Uri.ToString().Contains("/MainPage.xaml"))
{
if (sessionType == SessionType.DeepLink)
{
sessionType = SessionType.Home;
}
else
{
if (!mustClearPagestack)
{
e.Cancel = true;
RootFrame.Navigated -= ClearBackStackAfterReset;
}
}
}
mustClearPagestack = false;
}
}
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
if (RootVisual != RootFrame)
RootVisual = RootFrame;
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
private void CheckForResetNavigation(object sender, NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.Reset)
RootFrame.Navigated += ClearBackStackAfterReset;
}
private void ClearBackStackAfterReset(object sender, NavigationEventArgs e)
{
RootFrame.Navigated -= ClearBackStackAfterReset;
if (e.NavigationMode != NavigationMode.New && e.NavigationMode != NavigationMode.Refresh)
return;
while (RootFrame.RemoveBackEntry() != null)
{
;
}
}
private void InitializeLanguage()
{
try
{
FlowDirection flow = (FlowDirection)Enum.Parse(typeof(FlowDirection), AppResources.ResourceFlowDirection);
RootFrame.FlowDirection = flow;
}
catch
{
if (Debugger.IsAttached)
{
Debugger.Break();
}
throw;
}
}
bool CheckDeactivationTimeStamp()
{
DateTimeOffset lastDeactivated;
if (settings.Contains("DeactivateTime"))
{
lastDeactivated = (DateTimeOffset)settings["DeactivateTime"];
}
var currentDuration = DateTimeOffset.Now.Subtract(lastDeactivated);
return TimeSpan.FromSeconds(currentDuration.TotalSeconds) > TimeSpan.FromSeconds(30);
}
public bool AddOrUpdateValue(string Key, Object value)
{
bool valueChanged = false;
if (settings.Contains(Key))
{
if (settings[Key] != value)
{
settings[Key] = value;
valueChanged = true;
}
}
else
{
settings.Add(Key, value);
valueChanged = true;
}
return valueChanged;
}
public void RemoveValue(string Key)
{
if (settings.Contains(Key))
{
settings.Remove(Key);
}
}
public void SaveCurrentDeactivationSettings()
{
if (AddOrUpdateValue("DeactivateTime", DateTimeOffset.Now))
{
settings.Save();
}
if (AddOrUpdateValue("SessionType", sessionType))
{
settings.Save();
}
}
public void RemoveCurrentDeactivationSettings()
{
RemoveValue("DeactivateTime");
RemoveValue("SessionType");
settings.Save();
}
void RestoreSessionType()
{
if (settings.Contains("SessionType"))
{
sessionType = (SessionType)settings["SessionType"];
}
}
Suppose while I am in ThirdPage. I press the Windows button. And then I press my App icon from the start screen. Rather than the app resuming from the ThirdPage. It first shows the ThirdPage and then starts from the MainPage.
Upvotes: 2
Views: 302
Reputation: 19
Code as listed will mess up. It doesn't match the comments. Look at the RootFrame_Navigating - mustClearPagesStack at the bottom is set to false - but look at the comments in the original MSDN link - two places above it say the page stack must be cleared.... but because the flag is set to false it's messed up. So set the flag false at the top, but then set it to true in the two 'if conditions' where it says to. Then it will work like a champ.
Upvotes: 0
Reputation: 3568
By default, the app still navigates to the default page, when the application is launched via the app tile. You can check the session type in the RootFrame_Navigated methods and cancel that navigation, if you so wish.
The default template adds a CheckNavigation method to in the app.xaml.cs that clears the backstack after a navigation with NavigationMode Reset.
You can check there, if your app should stay on the last page or if it is better to reset and start over.
A sample for handling different activation types can be found here: MSDN Fast Resume Sample, App.xaml.cs
(Method: RootFrame_Navigated)
Upvotes: 1