MediaCapture + CaptureElement lifecycle/navigation

2019-01-26 11:35发布

问题:

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?

回答1:

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.



回答2:

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).