I am attempting to handle the loss of focus of my application, either by a phone call or other event, and also by the pressing of the home key.
I have tried setting a flag in the OnNavigatingFrom/OnNavigatedFrom and OnNavigatedTo event handlers but each time the app starts (either after pressing home, or something else) it always seems to be resetting the flag.
Which are the correct events I should be using in order to correctly "pause" and subsequently "resume" my application if it loses focus?
You should read the documentation about application lifecycle.
When you press the Home button, or when you receive a phone call, the application is paused.
If you pressed Home, you can then restore the application by pressing the back button.
to handle these events, in App.xaml.cs by default the methods are: Application_Activated and Application_Deactivated
Of course you can manage to store data before the pause, and restore it when application is restored.
This is called tombstoning.
What you need is described in the following links:
http://windowsphone7.vectorform.com/2010/11/16/wp7-application-lifecycle/
http://www.windowsphonegeek.com/articles/WP7-Application-Lifecycle-and-Tombstoning
Read this. This is a microsoft tutorial on how to save state.
It'll give you how to save your ApplicationData when it is tombstoned.
Basically edit the Application_Closing and Application_Activated methods in the App.xaml to save the data to the system using isolated storage.
Related
I am a little bit confused if I need to really do anything for fast switching. It seems like if I am not using media element, camera and sockets I get this "fast switching" for free.
I am not sure how to test it though. I see a couple videos where
Hit the Windows Icon(Start Icon)
Hit the back button
or
Hold down the back button till you get the screen view
Go to some other app
Come back to your app.
These both seem to load up fast again but how about if.
Load up app
Hit windows icon
click on tile app
Should fast switching happen at this point or does it load a new instance of your app up killing your old one?
There is different concept involved here:
-the first thing is Fast App resume which is a new feature of windows phone 8 that you can enable so that when you press the application tile it don't restart your app but keep the same instance (by default it will just kill the app and just recreate a new instance exactly as if the app was never opened). You can find more information about that here.
-the second concept is Fast App Switch and Tombstoning. You can find more information about the application life-cycle here. Basically what happen is when you press the windows button or navigate to another app your app will go in dormant state. In this state the application is not running but is still in memory. When you go back since everything is still in memory everything should as it was left off. The main case to handle in case of fast app switch is the fact that when your app is deactivated all the network connection are killed so you should make sure that when you go back you don't display any web error message dialog and that you redo any failed web request.
The second possible state of your application is that after the app is in dormant state you open a couple of app and the device don't have enough memory, then it will choose to tombstone your app. In that state your app is removed from memory so anything you have not saved will be lost. When you go back to your app it will go back to the page where the user previously was and recreate it.
That mean that to handle this case before the app deactivate you should have :
save any context specific data that you might not have been passing by navigation parameter.
maybe save what the user have been currently doing (for example if he is currently entering a long text, it might be better to save it so that the user don't have to reenter it from scratch)
saving the current scroll position or thing like selected items could be a plus
Also when the app resume you have to make sure that you re-query all information that you need. An example of something which would break would be if you load some Data (from a web server for example) in OnNavigatedTo of the main page and then just reuse the data on the detail page without re-querying it. If you are on the detail page press the start button and then do some other and the app tombstonne, when you go back to the app than the data will not be available (since the memory has been "cleared" and onNavigatedTo of the main page is not called since it will navigate back directly to the detail page).
You can use the page state and application state to save whatever information you need to handle properly the tombstoning case. Basically there are dictionary to which you can add some object which will be serialize (so you need to make sure that whatever object you try to save is serialisable) automatically when the app is deactivated.
To test the Tombtonning case easily, what you can do is in the project properties, in the Debug Tab check the check box "Tombstone upon deactivation while debugging". Like this it will always tombstonne the app when you debug and press the windows button or go to another app. To check that it is really tombstonning, when you go back you should see your app showing a resuming screen for a few second (while in the tombstonning case it's almost instantaneous.
So this is a bit confusing. It took me forever to figure out what they really mean by this.
What fast switching references is for more complicated apps. Apps that take advantage of something that requires a saved state.
For example if you are creating a navigation app. You are navigating then you leave the app. When you go back to that app it should show the "Resuming..." indicator and then bring your app back to its previous state.
Here is a Channel 9 video on FAS
http://channel9.msdn.com/events/MIX/MIX11/DVC09
Also here is the MSDN article about it
http://msdn.microsoft.com/en-us/library/windowsphone/develop/ff967547(v=vs.105).aspx
Should fast switching happen at this point or does it load a new instance of your app up killing your old one?
In that case, new instance of your would be launched.
Actually, its a bit confusing, but not that much.
App can be either closed (by Windows key or pressing BAck key for a while) or exited (by pressing Back key in the main menu). Next, app comes to dormant state, it holds everything in memory. ApplicationDeactivated would be risen.
So, if you would just re-activate it (by pressing Back and selecting your app, or by pressing Back only, if you have nothing else in the stack), it would be resumed. ApplicationActivated event would be risen with e.IsApplicationInstancePreserved = true
If you would use lots of other apps (device would run out of memory), your app would go to tombstoned state. Then, you'd be needed to restore all data. e.IsApplicationInstancePreserved would be false.
If you would re-launch your app (by clicking on tile), new instance would be launched, and ApplicationLaunching would be risen.
Fast switching isn't something that really concerns you as a developer. What you need to worry about is "tombstoning" - when someone switches away from your app, you need to save the state: when the user switches back to it, you as the developer have to assume that your app was actually restarted from scratch and needs to reload that saved state. That's the difference between Application_Launching and Application_Activated (user started your app anew from the start screen, vs. app was suspended and is now being resumed, but from scratch).
At some earlier point this was the only way app switching worked. Fast App Switching was added later on and simply changed the contract such that sometimes your app would be resumed where it left off without being tombstoned. It depends on memory, etc, but it is simply a benefit to the user who will, in many cases, no longer need to wait for the app to reload its tombstoned state. You as the developer still have to assume you'll be tombstoned.
I'm developing my first Windows Phone 7 app. I don't yet have access to an actual device, so I am relying on the emulator that ships with the SDK.
In my app, I use the EmailComposeTask and SmsComposeTask where required. When debugging my app in the emulator, I click a button which runs one of these tasks, and it works. But when I then push the back button to get out of the task and back to my app, the app state is lost - it's as if I am launching it fresh all over again.
But, where it gets weird, is that on occasion this doesn't happen. I have gone back from one of the Tasks more than once to find my app state exactly how I left it.
And so, my questions:
Is this just a bug with the emulator?
If not, why is not consistent, and how should I be "saving" my app state prior to call the Email or SMS task?
Thanks.
Your page is being tombstoned which is why it seems like your application has restarted. This basically means that your app is still stored on the stack, ready to be called, but pages state and other data information is lost. To fix this, you need to handle the serialization of any data you want to keep.
For transient data, like page state things (e.g. textboxes, checkbox etc..), you can use PhoneApplicationPage.State. I believe the limit is 2mb. If you need to store more, you should store it in Isolated Storage (unlikely, unless you need to save an image). You can read about the process here. To understand the process of Tombstoning, you should read this MSDN page. To save time, you can use Tombstone Helper which handles all the lower level storage details for you, but it's a good idea to understand the process of Tombstoning anyway so you know what's going on.
The reason your app doesn't always get tombstoned is because EmailComposeTask doesn't cause a tombstone straight away. From this MSDN blog post:
Below is the list of native
experiences that, when invoked, do not
trigger an automatic tombstone in the
calling application:
PhotoChooserTask
CameraCaptureTask
MediaPlayerLauncher
EmailAddressChooserTask
PhoneNumberChooserTask
There are three scenarios in which an
application in the background will
immediately be tombstoned:
User forward navigates away from an application [for example, user
presses the Start key]
Application invokes launchers or choosers not listed above
System requires more resources to carry out a foreground activity
As you can see, that's not to say EmailComposeTask will never cause a tombstone, so you should still handle it, but it explains why your page state is sometimes kept automatically.
I am facing some issues in WP7 tombstoning. My issue is application hangs when i try for a sudden tombstone and come back. ie, After loading the page i press device menu button and with in seconds i pressed back button( Pressed Back button before the actual page disappeared) In that time the page loads but the application hangs / its back key press is not working. and if we try for a slow thombstone it is working perfectly. And the pretty interesting thing is that, while tombstoning the loaded and unloaded events of APP working perfectly. Please any one help me to solve this issue.
It sounds like your App has been deactivated, but not tombstoned. This results in neither the App or Page contrusctor being called, causing your app to act in unexpected ways. I highly recommend reading the Windows Phone Silverlight Application Life Cycle document. The relevant extract for said article:
This case can occur if the user
presses the Start and Back buttons on
the phone in quick succession. In this
case, the application received a
Deactivate event and the system was
starting to save the state of the
application to perform an application
tombstone. Before this operation is
completed, the app Activated event is
received. The system knows that the
application was not removed from
memory, so the flow of execution is
different. Specifically:
• The app constructor is not called.
• The page constructor is not called.
The only way for the application to determine
if this condition has occurred is to
set a flag to indicate if the page
constructor has been called. If you
notice in the above section, this flag
was set in the page constructor, and
cleared in the OnNavigateFrom event.
In this case, we will receive the
OnNavigatedTo event, but we will see
that the page constructor was not
called. This tells us that our
application was not tombstoned.
I have an application which adds an icon to the notification area (aka the "system tray") using Shell_NotifyIcon. The icon has a context menu with various important commands. When the app runs on the local system, the context menu works fine. However, when the app is run as a Terminal Services RemoteApp, right-clicking the icon does not display the context menu. The various keyboard-based methods for opening the context menu also don't work.
Double-clicking the icon still behaves as expected, so I know it's not totally broken. We need the context menu to work as well, though. Does anybody know what might be wrong?
Edit: One more piece of information: if I press Ctrl+Alt+End to open the Windows Security screen (which lets you log off, lock the session, etc), and then close that screen, the context menu starts working.
It appears that this happens because the application does not receive a WM_CONTEXTMENU notification in the RemoteApp case. The usual WM_RBUTTONDOWN and WM_RBUTTONUP notifications arrive, but that's all. Strangely, if you try to activate the context menu with the keyboard, you also receive WM_RBUTTONDOWN and WM_RBUTTONUP, even though the mouse wasn't involved. Pressing Ctrl+Alt+End appears to resolve this problem; the system starts sending normal WM_CONTEXTMENU notifications. My guess is that this is a bug in the remote desktop client process.
One potential fix would be to trigger the context menu using WM_RBUTTONUP, but that breaks keyboard accessibility, so I don't recommend it.
The workaround I settled on was the following:
When you see a WM_RBUTTONUP notification, set a timer with a short timeout (50-100ms).
When you see a WM_CONTEXTMENU notification, cancel the timer and display the context menu.
When the timer fires, cancel the timer and display the context menu.
This should work for local usage and RemoteApp usage. The timeout value in step 1 needs to be long enough that it doesn't expire before the WM_CONTEXTMENU comes in, but no longer.
After creating a translucent window (based on example code by Matt Gemmell) I want to get keyboard events in this window. It seems that there are only keyboard events when my application is the active application while I want keyboard events even when my application isn't active but the window is visible.
Basically I want behavior like that provided by the Quicksilver application (by blacktree).
Does anybody have any hints on how to do this?
There are two options:
Use GetEventMonitorTarget() with a tacked-on Carbon run loop to grab keyboard events. Sample code is available on this page at CocoaDev.
Register an event trap with CGEventTapCreate. Sample code can be found in this thread from the Apple developer mailing list.
Edit: Note that these methods only work if you check off “Enable access for assistive devices” in the Universal Access preference pane.
A simpler route that may work better for you is to make your app background-only. The discussion on CocoaDev of the LSUIElement plist key explains how to set it up. Basically, your application will not appear in the dock or the app switcher, and will not replace the current application's menu bar when activated. From a user perspective it's never the 'active' application, but any windows you open can get activated and respond to events normally. The only caveat is that you'll never get to show your menu bar, so you'll probably have to set up an NSStatusItem (one of those icon menus that show up on the right side of the menu bar) to control (i.e. quit, bring up prefs, etc.) your application.
Edit: I completely forgot about the Non-Activating Panel checkbox in Interface Builder. You need to use an NSPanel instead of an NSWindow to get this choice. This setting lets your panel accept clicks and keyboard input without activating your application. I'm betting that some mix of this setting and the Carbon Hot Keys API is what QuickSilver is using for their UI.
Update:
Apple actually seems to have changed everything again starting with 10.5 BTW (I recently upgraded and my sample code did not work as before).
Now you can indeed only capture keydown events setting up an event tap if you are either root or assistive devices are enabled, regardless on which level you plan to capture and regardless if you selected to capture (which allows you to modify and even discard events) or to be listen only. You can still get information when flags have changed (actually even change these) and other events, but keydown under no other circumstances.
However, using the carbon event handler and the method RegisterEventHotKey() allows you to register a hotkey and you'll get notified when it is pressed, you neither need to be root for that nor do you need anything like assistive devices enabled. I think Quicksilver is probably doing it that way.