次の方法で共有


Exiting a Windows Phone Application

[Update 12/31/2012: See also this post for a new Windows Phone 8 API to terminate apps]

[Update August 10th below]

A pretty common request both on the forums and on our internal discussion lists is "how do I exit my Silverlight application?" As you might imagine, this is something that we discussed at considerable length on the team before deciding not to expose such an API in Windows Phone 7.

The lay of the land

For the record, here are the various ways an application can be "exited" in Windows Phone; we'll discuss each in turn:

  1. An XNA application can call Game.Exit() to exit the game.
  2. The user can exit a Silverlight application by hitting the Back button on the first page of the application.
  3. The user can pause any application by hitting the Start button on any page of your application (or taking another action that switches to another application, such as tapping on a toast message).
  4. An unhandled exception in any application will cause the application to be killed

And an overview of the behaviour of each of them:

  • #1 is only available to XNA applications. It will raise the Game.Exiting event
  • #1 and #2 will raise the PhoneApplicationService.Closing event and your application (along with any saved State) will be removed from the back stack
  • #3 will raise the PhoneApplicationService.Deactivated event and your application's pages (along with any saved State)will be preserved on the back stack until one of:
    • The user re-launches your application via the Start Menu (or any other mechanism except the Back key)
    • The application "falls off the end" of the back stack because it is full
    • The device loses power, reboots, gets updated, the app is uninstalled, etc.
  • #4 will kill your application and remove it from the back stack without raising any other events

Let's tackle the first one first. XNA applications have an explicit Exit method exposed for two main reasons: firstly the API already existed on Xbox and Windows so removing it could have caused a porting issue with other games, and secondly XNA doesn't participate in the page-based navigation model that Silverlight does and so there was no automatic way to handle the Back button. Nevertheless, section 5.2.4 of the application guidelines make it pretty clear when and how an XNA application should handle the Back key and when they should call Exit such that it is as consistent as possible with other applications. It may seem like XNA gets special treatment here, but really they are bound by the same rules that Silverlight is.

The second case is the way the user actually exits an application cleanly. After using the application, they will simply "back out" of it, closing any intermediate screens as necessary and finally closing the application when they back out of the first page. This is also a quick way to get out of an application if you launch it by accident (Start -> app appears -> Back) and is one reason why it's generally bad to automatically perform a navigation or show a popup when your application starts up (because now there will be two pages on the back stack). Give the user the option to log in (even if it's the only option on the screen!) but don't take up a slot in the back-stack for it on start-up.

The third case is also a common way to "quit" an application, except that it is kept on the back stack in case the user goes back to it (although some users may never really discover what the back stack does or how it works, but that's OK). If the user just wants to get on with some other activity and doesn't want to focus on your app right now they can just hit Start and go on their merry way (they could also hit Search, or tap on a toast, or do something else). If the user gets back to your application via the Back key, it will be restored with all the previous state (assuming you saved it correctly ;-) ) ready for them to continue their previous task. If, on the other hand, they start your application again from the Start menu then the old state will be thrown away and a new "session" of your application will start.

As an aside, a pretty common question we get asked is "How should I handle Deactivated vs. Closing, given that in both cases my application is shut down and the user may never come back to it?" The golden rule is that in both cases you should save any data that the user would not want to lose. Basically any data they've entrusted to the application that they would be unable (or unwilling) to enter again should be saved, even if it's only in a "draft" form. The key difference is that in the Closing case you don't need to worry about saving any view state or caching any information to enable a fast re-activation, whereas in the Deactivated case you should consider saving such information into the provided State bags (you should not persist this view state information to IsolatedStorage because it will be stale next time the application gets launched).

The final case is what happens if your application has a problem and you can't recover from it in the Application.UnhandledException event handler (in general it's a bad idea to unconditionally set e.Handled = true in this handler, because you have no idea what's going on... it's OK to handle specific errors that you know how to recover from though). The application will disappear from the screen and the user will be returned to the Start menu.

Scenarios for needing Exit

With the introduction out of the way, the two most common scenarios people cite when asking for an Exit method are because (a) the user failed accept a EULA, login to an account, or something else that renders the application inoperable, or (b) the application is in an unstable state due to unexpected errors, etc. and needs to be shut down.

We can quickly answer (b) by saying you should follow #4 above - simply ignore the error in your UnhandledException event and the application will be terminated for you. A simple way to do this can be to declare your own Exception subclass - say ApplicationNeedsToExitException - and explicitly check for that in your UnhandledException event handler. If you have an instance of that exception, immediately return from the handler without setting e.Handled to true, and you'll be set. There is the chance that some catch clauses may get the exception - in which case again you can explicitly catch this kind of exception and re-throw it - and / or that some finally clauses may execute as well. If that's the case you need to make sure they are "safe" to execute in the face of unexpected application state, but that's already the case for general exceptions.

That leaves (a), which I think is primarily caused by application designs carried over from other platforms like desktop Windows or other mobile platforms. Here's probably what happens:

  1. User starts the application
  2. It navigates to a EULA / Login / some other kind of "must successfully complete" page
    1. This may be the first page, or a popup, or even a forced navigation to a second page... which is bad as I note above
  3. The user declines the EULA / fails to login / etc.
  4. The application wants to programmatically exit

I think the reason that people want a programmatic way to exit is because they want to do something like this:

image

Of course, given this UI the user might expect that when they click "Decline" the application terminates (which is why the developer wants to call an Exit method) but there are at least two ways out of this. The most obvious one is to simply get rid of the "Decline" button! The user already knows they can quit an app using the Back key, so you don't need to give them another way to do that. No on-screen button = no need to call an API to exit. The other approach, if you really need an explicit "Decline" button, is to replace the page contents with a simple message like "You have declined the EULA and cannot use this application" and leave it to the user to hit Back themselves. Funnily enough, even if you had a programmatic way to exit the application, it would only be polite to afford the user the courtesy of such an explanation, in which case it would itself have an "OK" or "Dismiss" UX... and then you're back to just relying on the hardware Back button to accomplish the same task.

Lucky developers who already have a phone can see this if you try and add an e-mail account through the Settings control panel. The screen has an "Email address" field, a "Password" field, and a "Sign in" button. No need for a "Cancel" button, since you can always hit Back if you can't remember your login or want to abandon the account creation process. This is the interaction model of the phone, and we wanted to make sure everyone followed the same pattern to avoid confusing users.

[Update August 10]

I forgot the #1 piece of advice regarding EULA / Login screens - don't make them into pages. If you instead make them Popup controls you can show or hide them at any time (on first navigation; when the user hits a "protected" part of the app; after a time-out; etc.) and they don't consume a slot in the backstack. This should cover the majority of cases.

A third reason people sometimes cite for wanting an Exit method is because they want to have an explicit "Exit" menu item in their application so that the user doesn't have to hit Back, Back, Back, Back,... in order to get out of a deep page hierarchy and back to the Start menu. But that's what the Start button is for - if the user wants to get back to Start, they hit Start.

Future

In this release of Windows Phone we've taken a fairly hard stance that applications should follow the user interaction model of 1st-party applications and should not have a programmatic way to exit themselves. Originally I was a proponent of having such a method primarily because I knew we'd get a lot of requests for it from developers (and would spend time explaining why it wasn't there... ha ha) but I am glad that I lost that argument for now because I think it will result in a more cohesive application ecosystem for users.

That said, it doesn't mean we can't or won't add such a method in the future if we get a lot of feedback that it really is necessary (for scenarios X, Y, and Z we didn't consider) or because we want to rationalize the API set with the other platforms or because it's Tuesday and we feel like it. For example, something like Environment.FailFast might be useful for apps that really do just want to log an error and bail. Or maybe it's too hard to write Silverlight games that act like XNA games with their explicit Exit call. If you have such scenarios (or just want to vent ;-) ), please leave a comment below.

Comments

  • Anonymous
    August 02, 2010
    Peter Torr's blog on Windows Phone application development with Silverlight

  • Anonymous
    August 03, 2010
    The comment has been removed

  • Anonymous
    August 04, 2010
    Hi Ed, there is no 3rd-party multitasking in Windows Phone 7 so there is no need to clean up things in this way. If the user wants to switch to a different application, the most efficient way of doing that is to hit the Start button (much easier and more consistent than trying to find an "Exit" button in the application, which could be hidden anywhere).

  • Anonymous
    August 09, 2010
    Some confusion comes from the term 'Start' button.  It seems to me that the original intent of this' Start' button was to support multitasking (Start another Process or App).  Start button does not describe this hardware buttons current function ... it 'Starts' nothing ... in effect, it just hibernates the current application and  returns you to the 'Desktop' where you can elect to start something else, or just use the 'Go back' hardware button to 'hopefully' resume what you were doing.  The problem here is that if you have saved state in the application, then the user never really 'Exited' your application when they hit the Start button.   So technically one can only truly 'Exit' an application by popping off of the stack with the Back button.  Way too Web-Like for me! I've developed CF/SqlCe applications in the past and was hoping WP7 would be more WPF-lite than Silverlight-lite (a little more 'Stateful' would have been nice!).  After wading in the weeds, WP7 looks more like a silverlight Web-Appliance than anything else. I think Microsoft may have really missed the boat with this one! I've been trying to port a few desktop games to this platform. For now, I think I'll just move to a more Application friendly framework like Android!

  • Anonymous
    August 09, 2010
    Hi nhrones, the Start button returns you to the Start menu so that you can "start doing something else." I don't see it as being tied to multitasking at all, although some functions such as playing music or downloading web pages do continue in the background. It is also true that hitting Start should not be seen as "exiting" the application from the user's point of view; if they navigate back into the application then it should resume doing what it was in the past. I list in the post the possible ways an application might be completely terminated and removed from the back stack (aka "exited").

  • Anonymous
    August 10, 2010
    We need exit function. Our app requires the user to be logged in but sometimes he wants to log out. so, in the settings of the app I added a function called "Log Out". Clicking on it deletes all user's data from isolated Storage, delete the username/password I saved for the user and exit the app. this is the way we do it on all other major platforms and have no issues with that.

  • Anonymous
    August 16, 2010
    Yaron, for that example I can think of two ways to implement it that don't require an exit call:

  1. Programmatically navigate back to the home screen, so that there are no pages to view
  2. Ensure that all your pages are aware of the "logged in" state, and make sure they go to a zombied stated in their OnNavigatedTo handlers if the user is not logged in Note that your applicaiton will need to be robust against things like being tombstoned while deleting content (if it takes too long, your process will be killed) or even the user removing the battery while you are deleting content. You will need a flag that you can reliably persist to IsoStore that says "logged in" or not, and then can delete the content on next boot if it didn't cleanly delete last time
  • Anonymous
    August 27, 2010
    TechEd Australia is all wrapped up, and I wanted to let everyone else know about one of the new concepts

  • Anonymous
    August 27, 2010
    One more post on the subject of keeping screens out of the backstack. A common scenario we see is a variation

  • Anonymous
    August 31, 2010
    The comment has been removed

  • Anonymous
    August 31, 2010
    Hi Simon, custom exit animations are not something we specifically designed for in WP7. Remember there are many ways the user can leave your app and in most cases they are unlikely to actually exit out of it using back (more common, I think, will be to just hit "Start" and do something else).

  • Anonymous
    September 20, 2010
    Peter, I found this blog post while searching for the exact same answer in the exact same EULA scenario you described above.   At first I was incredulous that such an oversight could be possible but as I read your explanation, it made more and more sense...and I came to terms that it's possibly the best way to move forward with my app.   I would be curious if anyone has found a vaild reason (to you) for having a Silverlight exit functionality...