Windows phone navigation bug - windows-phone-7

I encountered an issue.
I have a loading page with progress bar. It is non-interactive, it only shows progress on loading data. AFter data is loaded - it navigates to MenuPage.
If user minimizes app during loading process sometimes a phantom corrupted entry is added to BackStack.
Problem:
If this corrupted entry is in backstack - NavigationService.RemoveBackEntry() throws NullReferenceException.
Question:
My goal is to exit app from 2nd page when user presses back. Can i somehow do that without removing items from backstack and throwing exceptions ?

In short, no. You can't directly quit an application and it sucks. However you can do it with a well handled exception.
private class QuitException : Exception { }
public static void Quit()
{
throw new QuitException();
}
private void Application_UnhandledException(object sender,
ApplicationUnhandledExceptionEventArgs e)
{
if (e.ExceptionObject is QuitException)
return;
if (System.Diagnostics.Debugger.IsAttached)
{
System.Diagnostics.Debugger.Break();
}
}
Source:
http://www.imaginativeuniversal.com/blog/post/2010/08/22/How-to-Quit-a-WP7-Silverlight-Application.aspx

Related

How can I correctly close an application in Application_Launching event

I want to close my app if network not available.
I check network in App.cs:
private void Application_Launching(object sender, LaunchingEventArgs e)
{
if (!NetworkInterface.GetIsNetworkAvailable())
{
//close my app
}
else
{
//continue to work
}
}
Is there a better way to do it?
Thanks in advance.
just add reference to Microsoft.Xna.Framework.Game i'm sure you can achieve exit with this code and it will be ok. if you wanna show message box you have to do it in main page
what i would do:
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (!NetworkInterface.GetIsNetworkAvailable())
{
MessageBoxResult m = MessageBox.Show(Sorry, no internet connection is available.do you want to exit the application , "Oops...", MessageBoxButton.OKCancel);
if (m == MessageBoxResult.OK)
{
var g = new Microsoft.Xna.Framework.Game();
g.Exit();
}
}
}
you should provide a "gentle" way for closing
5.1.2 - App closure
The app must handle exceptions raised by the any of the managed or native System API
and not close unexpectedly. During the certification process, the app is monitored
for unexpected closure. An app that closes unexpectedly fails certification. The app
must continue to run and remain responsive to user input after the exception is
handled.
for more information visit this link
Application.Current.Terminate();

Lock app with password

In WP application we need to provide user option to lock app with password.
As I understand WP app lifecycle, I need to put navigation to LockPage in App.Application_Activated, App.Application_Deactivated and start page, but I can not use NavigationService in App class...
I do not want to put navigation code to lock page in each other pages, or there is no other options?
I writed own solution, but may be it is not so elegant as it could be.
App locking logic: User enable app locking with password, we handling Application_Deactivated and Application_Closing events in App class and marking app as locked if user enabled this option. Then, on each page we should put check: is app currently locked and if it is, we should navigate to AppLockedWithPasswordPage. On AppLockedWithPasswordPage we need to check user`s password, if it is correct call NavigationService.GoBack().
So we need to do 6 steps:
You should choose where to save IsAppCurrentlyLocked (bool flag), AppLockPassword (string) and IsUserEnabledAppLockWithPassword (bool flag). I had chosen IsolatedStorageSettings
Create AppLockedWithPassword page, where you need to show TextBox and Button, do not forget to provide option for user to reset AppLock of course with deleting app data
AppLockedWithPasswordPage should prevent BackButton navigation, so preventing it:
// AppLockedWithPasswordPage
protected override void OnBackKeyPress(CancelEventArgs e)
{
// Preventing back key navigation
e.Cancel = true;
}
Check password on button click
// AppLockedWithPasswordPage
private void UnlockAppButton_Click(object sender, RoutedEventArgs e)
{
if (PasswordBox.Password.Equals(IsolatedStorageSettings["AppLockPassword"]))
{
NavigationService.GoBack();
}
else
{
// Say user, that password incorrect, etc...
}
}
In App class find Application_Deactivated (to handle app minimizing (windows button)) and Application_Closing (to handle when user closing app) methods, we should mark app as locked if user enabled this option when this events happens
private void SetIsAppCurrentlyLockedFlagIfUserEnabledAppLocking()
{
if ((bool)IsolatedStorageSettings["IsUserEnabledAppLockWithPassword"])
{
IsolatedStorageSettings["IsAppCurrentlyLocked"] = true;
}
}
private void Application_Deactivated(object sender, DeactivatedEventArgs e)
{
SetIsAppCurrentlyLockedFlagIfUserEnabledAppLocking();
}
private void Application_Closing(object sender, ClosingEventArgs e)
{
SetIsAppCurrentlyLockedFlagIfUserEnabledAppLocking();
}
And final step, on all pages you want to lock you should add check in OnNavigatedTo method which will navigate to AppLockedWithPasswordPage if app is currently locked
// Create some class, like PagesUtils or so on with check method
private static Uri uriToAppLockedWithPasswordPage = new Uri("pathToAppLockedWithPasswordPage", UriKind.Relative);
public static void NavigateToAppLockedWithPasswordPageIfAppLocked(PhoneApplicationPage page)
{
if ((bool)IsolatedStorageSettings["IsAppCurrentlyLocked"])
{
page.NavigationService.Navigate(uriToAppLockedWithPasswordPage);
}
}
// In each page you want to lock add
protected override void OnNavigatedTo(NavigationEventArgs e)
{
PagesUtils.NavigateToAppLockedWithPasswordPageIfAppLocked();
base.OnNavigatedTo();
}
P.S. of course real code is much better, this is just simple example, I hope it will help you
You should add the check in the Application_Launching and Application_Activated events.
The launching event for when the app is first opened and the activated one for when the user returns to the app after having left to do something else.
Have these events both set a flag and have the base page that all your pages inherit from check for this flag when navigated to. The check should be for if the flag is set, if it is, show the login prompt and then clear the flag after successful password entry.
This approach will handle FAS, FAR & deep linking, in addition to starting the app normally.
Beware Some choosers will trigger the activated event when they return to the app. Add extra handling for these as appropriate / if necessary.
Why not create a start page where the passwords is entered?
For instances you have your MainPage.xaml, create a InsertPasswordPage.xaml reference it on WMAppManifest as the start page:
<DefaultTask Name="_default" NavigationPage="InsertPasswordPage.xaml" />
And insert all the password logic on the InsertPasswordPage.xaml, when the user successfully logins just navigate to your main page ;)
EDIT: As Gambit said if the user pressed the back button he will return to the insert password page, but you can solve this by removing from the backstack the page after the user logged in.

Switch Screens in BlackBerry

I have a BlackBerry App that has a Listener for the Send Button implemented in the CheckIn Screen. Data is sent through a web service. If the data is sent successfully, a confirmation message of "OK" is received. I am trying to switch screens in my BlackBerry App depending on the response received.
FieldChangeListener sendBtnListener = new FieldChangeListener() {
public void fieldChanged(Field field, int context)
{
try {
String alertMsg=sendTextCheckIn();
if(alertMsg.equals("OK"))
{
UiApplication.getUiApplication().invokeLater( new Runnable()
{
public void run ()
{
UiApplication.getUiApplication().pushScreen(new MyScreen());
}
} );
}
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
However, the above is throwing an App Error 104: IllegalStateException. Can anyone please guide on how to switch screens between a BlackBerry App.
EDIT: I can switch to any other screen but I CAN NOT switch to MyScreen. NOTE: MyScreen is the main (first) screen of the App. The above method sendTextCheckIn() calls another method that is placed inside MyScreen. Has this got anything to do with the error? Please advice.
The 'fieldChanged' event is already running on the UI event thread, so you shouldn't need to do the invokeLater call within it, just call pushScreen directly.
You mention that your problem with IllegalStateException only happens for MyScreen. That makes it sound like something specific with the implementation of MyScreen. Start narrowing down the problem - look at what happens in the constructor of MyScreen, and any events that might get called before the screen is visible. Some of that code is what is causing the problem.
Wrap everything that could possibly raise in exception in try/catch.
Don't do e.printStackTrace() - that won't give you much.
Instead do something like System.err.println ("KABOOM in method abc() - " + e); - seems like more effort, but trust me, that becomes INVALUABLE when debugging issues like this.
Catch Exception, unless you have a VERY good reason to catch a specific a subtype - otherwise you WILL end up with unexpected, and uncaught exceptions, which you will hunt for DAYS.

Can't tombstone ItemsSource of a ListBox

I have a ListBox populated with data coming from XML.
Fine so far, the problem is that I get some errors when I try to tombstone it.
protected override void OnNavigatedFrom(System.Windows.Navigation.NavigationEventArgs e)
{
State["listbox1"] = listBox1.ItemsSource;
}
Then:
protected override void OnNavigatedTo(System.Windows.Navigation.NavigationEventArgs e)
{
if (State.ContainsKey("listbox1"))
{
listBox1.ItemsSource = (IEnumerable)State["listbox1"];
}
}
When I hit the start button I already get an error. The App.xaml.cs opens and the line below becomes yellow
System.Diagnostics.Debugger.Break();
I've also used tombstoning helper but it did not return the items in my listbox.
What is the listbox bound to? And what error are you seeing?
If it's a DataServiceCollection, you may have tracking turned on & you cannot put it flatly in Isolated Storage or State dictionaries. Should be fine if using ObservableCollection.
Thanks!

Caliburn.Micro(.WP7) and Bing Maps Crashing

I have an app that I'm upgrading from some beta bits - and my map screen is crashing. So to try to get to the bottom of it - I started a brand new - blank "Win Phone Application".
Referenced Caliburn.Micro (just built from new code last night) Version: caliburnmicro_1296ea635677 (from codeplex)
referenced Microsoft.phone.controls.map.dll
and in the MainPage I added
<Grid>
<Maps:Map />
</Grid>
and I add a bootstrapper to app.xaml
<WP7:PhoneBootStrapper x:Name="bootstrapper" />
when the page runs in the phone emulator - the main page renders and I see a map of the world. if I click anywhere on the page - I get an unhandled exception of "The parameter is incorrect"
if I remove the
from the app.xaml - the map works correctly.
What do you think?
Thanks for any advice?
I have found the answer.
The key here - is that I had this setup and wroking with the Beta Templates - and it stopped working when I moved to the WinPhone RTM Templates in VS2010.
Caliburn does some work on my behalf, that was "ADDED" to the RTM templates - which were conflicting with each other. In the end This problem has/had nothing to do with the Bing Maps control - it just so happens that - that was my first screen - so that's where I was trying to solve the problem.
This was the ever so Not-Helpful exception:
The parameter is incorrect
Which, I'm pretty sure would happen on any screen - if you went to the upgrade path of templates, like I did. So here is what I had to remove - to get everything back to normal. In the new App.Xaml.cs - I removed (by commenting) in the App Ctor ...
// Phone-specific initialization
// InitializePhoneApplication();
// Global handler for uncaught exceptions.
// UnhandledException += Application_UnhandledException;
And then I removed these method bodies, because it's just dead code after removing the InitializePhoneApplication() call from ctor ...
// 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)
{
}
// 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)
{
}
// Code to execute if a navigation fails
private void RootFrame_NavigationFailed(object sender, NavigationFailedEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
// A navigation has failed; break into the debugger
System.Diagnostics.Debugger.Break();
}
}
// Code to execute on Unhandled Exceptions
private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e)
{
if (System.Diagnostics.Debugger.IsAttached)
{
// An unhandled exception has occurred; break into the debugger
System.Diagnostics.Debugger.Break();
}
}
#region Phone application initialization
// Avoid double-initialization
private bool phoneApplicationInitialized = false;
// Do not add any additional code to this method
private void InitializePhoneApplication()
{
if (phoneApplicationInitialized)
return;
// Create the frame but don't set it as RootVisual yet; this allows the splash
// screen to remain active until the application is ready to render.
RootFrame = new PhoneApplicationFrame();
RootFrame.Navigated += CompleteInitializePhoneApplication;
// Handle navigation failures
RootFrame.NavigationFailed += RootFrame_NavigationFailed;
// Ensure we don't initialize again
phoneApplicationInitialized = true;
}
// Do not add any additional code to this method
private void CompleteInitializePhoneApplication(object sender, NavigationEventArgs e)
{
// Set the root visual to allow the application to render
if (RootVisual != RootFrame)
RootVisual = RootFrame;
// Remove this handler since it is no longer needed
RootFrame.Navigated -= CompleteInitializePhoneApplication;
}
#endregion
Special Thanks to Rob for his help solving this mystery!

Resources