MediaCapture + CaptureElement lifecycle/navigation management - c#

This is in a Windows Phone 8.1 Store app. My MainPage has a CaptureElement to display the preview stream from my MediaCapture object. For navigation within the app (between pages), this works well:
MediaCapture mc;
protected override async void OnNavigatedTo(NavigationEventArgs e)
{
mc = new MediaCapture();
await mc.InitializeAsync();
preview.Source = mc;
await mc.StartPreviewAsync();
}
protected override async void OnNavigatedFrom(NavigationEventArgs e)
{
await mc.StopPreviewAsync();
}
I can navigate to other pages and come back, and the preview runs reliably. I'm running into problems for the following scenarios though:
User presses the Windows button, then the back button
User presses the Windows button, then uses the task switcher to come back to my app
User presses the search button, then the back button
User presses the power button, then presses it again and swipes up to unlock the device
User holds down the back button to enter the task switcher, then taps on my app again
After each of the above actions (and/or combinations of them), when my app comes back the preview is frozen at the last frame that was displayed.
If the user then navigates to a different page and then back to the MainPage, the preview starts running again without an issue, so this leads me to believe I just need to stop/start the preview after coming back from one of the above scenarios.
I tried subscribing to the App.Suspending and App.Resuming events, but these don't trigger on these occasions. What am I missing?

You will have to use App.Suspending and App.Resuming (for the cases you have described) with combination of Navigation events (when navigating between Pages). The OnNavigatingFrom event is called when you hit Start, hold Back or use Search (when the App is being suspended), but when you resume the App, OnNavigatedTo is not being called - this event is called only when you are navigating. So in your case, when you hit Start, the preview stops and when you come back it doesn't start again. A refference to MSDN:
Note On Windows Phone, OnNavigatedFrom() is called when the app is suspended. OnNavigatedTo() is not called when the app is resumed.
The other thing is that to debug the App properly you will have to use Lifecycle Events of Debug Location tab in Visual Studio - while you are debbuging the app, it is not being suspended, but when you run your app normally, it gets suspended just after you hit Start.
Note also that the App can be put into Not Running state. More about Lifecycle at MSDN.

The scenarios you described should trigger the Window.Current.VisibilityChanged event where you can use VisibilityChangedEventArgs.Visible passed into the event handler to cleanup preview when not visible and initialize preview when visible. You can subscribe\unsubscribe to Window.Current.VisibilityChanged event in your Loaded\Unloaded handler for your Page\UserControl.
The reason why Suspend/Resume lifecycle events is not sufficient is because the scenarios you mentioned above doesn't deterministically invoke those events at a certain time as the OS will only suspend an app based on an internal policy that can change with OS release updates.
Also as an aside, I would avoid using Navigation handlers and instead rely on Loaded\Unloaded handlers which will allow initialization\cleanup to occur properly if you ever had to move your CaptureElement into its own UserControl as opposed to in a Page and avoids the scenario where WP will call OnNavigatedFrom and not call OnNavigatedTo for suspend\resume (Loaded\Unloaded will always be called in order).

Related

Release mode UWP app crashes when in tablet mode and with code in OnSuspended

We have a Xamarin UWP app that needs to be logged out whenever a user minimizes or clicks away from the window.
In my App.xaml.cs I have registered an event handler for the Suspending event. I then put our logout code in this event handler like so:
private void OnSuspending(object sender, SuspendingEventArgs e)
{
var deferral = e.GetDeferral();
AppBackgrounded();
deferral.Complete();
}
This AppBackgrounded() method looks like this:
void AppBackgrounded()
{
if (!_isInBackgroundMode)
{
_isInBackgroundMode = true;
if (UserSetPin)
{
PinPage passcodePin = new PinPage();
Navigation.PushModalAsync(New NavigationPage(passcodePin), false);
}
else
{
App.Logout(null, true, true);
}
// clears the pasteboard so data can't be copied from this app into other apps
Clipboard.Clear();
}
}
We also have a AppLeavingBackground method that we use to restore the app when the user returns, but the app does not crash when returning. It only crashes when running the OnSuspended method.
This crash only occurs when
The App is built for release and
The device is in tablet mode
When in tablet mode, if you press the Task View button and navigate to another application the UWP app freezes trying to run through this code. If you try to return to the app, it will immediately exit.
I have tried to make the navigation to the other pages async and the app will then crash even when its not in tablet mode. I have also tried to put this logic in AppEnteredBackground and it still occurs.
This is hard to debug since it only occurs in release mode. Any ideas?
In my case it was the Clipboard.Clear() function that was crashing the application. For those encountering similar issues, checkout the other answers as they all provide great points.
As a side note, I also found that using async code in these events was crashing my application. I'm not sure why since I was using the deferral, but since it's working i'm not going to pursue it further.
I cannot say that I have read exactly the documentation that says that navigating the pages in suspending will result in a crash, but it is clear that this is the wrong place to do it.
The suspending is not used to prepare your app to be opened again, the whole reason for this lifecycle event is that you need to prepare your app for not being open again, which means saving some data that may eventually get lost. Preparing your app to be opened again is done in resuming.

How to manage the cycle life on Xamarin Forms with PiP mode

I’m developing a video app that supports PiP mode. The app is developed with Xamarin forms and the page where is the player I release resources and stop the video on the method “ondisappearing” but when app changes to PiP mode, this method is called and then app stops of playing.
I have been checking other methods in order to detect it… but I’m not finding the correct combination. One thing that I have though is to check the pressed back button but… when user tap the soft button isn’t executed this method. Next I have checked is the pause and resume event of “App” of Xamarin forms but this methods aren’t executed when app in/out of PIP mode. I may use this with some Boolean for example in order to detect the state of pause vs pip mode. But I can’t different from back navigation (or I don’t see how)
From Main activity of android I have seen that is executed the method of onPause and onResume when in/out PiP mode, but this method is executed later of launching onDisappearing event on player page, so app has unregistered events and I can't resume .
Are there some property on NavigationPage which I can detect if user is navigating or is in/out PiP mode? I would like release resources and stop player only when user navigate or change to other app. Thank you

How to return to app after ShareTargetActivated event finishes?

If the app is already in background/suspended and OnShareTargetActivated event is invoked, it runs in new ApplicationView with new window. It works good, but when sharing is finished I would like to return to my main view (previous) of application, which was in background/suspended. Is it possible?
In former builds (10586) of UWP, there was ShareOperation.DismissUI method which done the job, but starting from 10493 this method is deprecated and doesn't work on all devices. As I've tried ShareOperation.ReportCompleted closes share window, but then returns to the app that was a source of shared data, not to the background/suspended view of my app.
Sample scenario: user clicks in my app button 'Find translation in internet', this opens Edge with bing/google translator and my app gets suspended. In Edge user marks some text and clicks share and chooses the app. This fires OnShareTargetActivated which starts new View of the app, once share is finished (ReportCompleted) user is redirected to Edge. I would like somehow to switch to my main (previously suspended) view - I'm able to do this on mobile with usage of ApplicationViewSwitcher, however, on desktop it's not possible due to exception you get while trying to access CoreWindow of previous view.

Event on returning to app, after exiting by Windows key [UWP][Win10 Mobile]

I have big trouble finding right event for me - user during browsing files in my app [UWP Windows 10 Mobile app] can tap on it and then I launch it in default app by
Windows.System.Launcher.LaunchFileAsync
my app is 'minimzed' (just like by pressing Windows key) and user can interact with file in whatever app he wants. Now by pressing back-key he is returning to my app. Do you know any event which is trigerred now? I want to update the file (if it was changed) but I cannot find any event to check it.
Take a look at App lifecycle, I think you should register event handler for both OnLaunched and Resuming, one for switching back from terminated state, another for from suspended state.
When the user switches back to a suspended app that has been terminated, the app should restore its application data in its OnLaunched method.
If an app registered an event handler for the Application.Resuming event, it is called when the app is resumed from the Suspended state. You can refresh your app content and data using this event handler.
It is important to understand the UWP app lifecycle.
If you want to have control on what is happening while application is Launched first time, Suspended or Resumed you should refer to below guideline:
https://msdn.microsoft.com/en-us/windows/uwp/launch-resume/app-lifecycle
Also in the App.xaml.cs file you can manage this cycle. For instance you can control what to do when application is Resumed from the background:
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
this.Resuming += App_Resuming;
}
private void App_Resuming(object sender, object e)
{
//Code to execute while resuming the app...
}

Refreshing interface in Windows Phone when reactivating

In my first WP7 App, I have all resolved (with MVVM pattern) except for recovering the App from inactivity. I have a main screen with a list of database ítems and a field for each one that, depending on a value and the actual day, shows one value or another (not a calendar, but the same problem).
If the user goes home and, the next day, resumes the App, the calcs must be done again, to refresh the contents. Also, in a second screen happens the same: what it shows depends on the day it is.
How can I detect the activation (I know it is on the Application_Activated function, but don't know how to use it) and refresh all that I need (a refreshInterface function in my second screen, if the user leave the App there, and the main list in the main screen).
I don't need to save nothing in deactivation, just refresh data on activation only.
In your page's OnNavigatedTo method you can subscribe to Application.Activated event (don't forget to unsubscribe in OnNavigatedFrom). In the event handler you can then update the viewmodel.

Categories