MediaCapture 和 Window VisibilityChanged
MediaCapture and Window VisibilityChanged
[问题]
On Windows Phone 8.1,在用户离开应用程序和 OnSuspended 事件触发之间到底发生了什么?我无法管理该范围内的对象,尤其是 MediaCpture 对象。
为了更好地解释问题,这里是场景:
- 用户所在的页面上有视频预览被推送到 CaptureElement
- 用户点击“开始”按钮
- 用户点击“后退”按钮 returns 到 MediaCapture 损坏的页面
对于 WinRT,没有 ObscuredEvent 并且 OnNavigatingFrom 不会触发,除非您要转到同一页面中的另一个页面框架。经过一些调查,我发现唯一触发的事件是 Window.Current.VisibilityChanged
我已经继续并在页面 NavigatedTo 中挂钩它并在 OnNavigatedFrom 中取消挂钩(参见下面的 ex2)。在该事件中,我检查指示应用程序是隐藏还是显示的参数,并相应地 dispose/initialize(参见下面的示例 1)。
[问题]
但是,此仅适用于附加的调试器。如果我在没有连接调试器的情况下执行此操作,它不会重新初始化并且 经常使相机崩溃 我必须重新启动设备。
代码示例 1(注意:e.Visible == false 离开应用程序,返回时为 true)
async void Current_VisibilityChanged(object sender, VisibilityChangedEventArgs e)
{
if (!e.Visible) //means leaving the app
{
await DisposeAll(); //cleans the MediaCapture and CaptureElement
}
else
{
if(mediaCaptureManager != null) await DisposeAll();
await Initialization(); //set up camera again
}
}
示例 2(连接到事件中)
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Window.Current.VisibilityChanged += Current_VisibilityChanged;
this.navigationHelper.OnNavigatedTo(e);
}
protected async override void OnNavigatedFrom(NavigationEventArgs e)
{
Window.Current.VisibilityChanged -= Current_VisibilityChanged;
this.navigationHelper.OnNavigatedFrom(e);
}
[更新:决议]
不使用 VisibilityChanged,而是挂接到页面构造函数中的 Window.Current.Activated。在调试器完全分离的情况下,Activated 事件将在 WindowActivatedEventArgs 中提供 WindowActivationState 参数。像这样:
private async void CurrentOnActivated(object sender, WindowActivatedEventArgs e)
{
if(e.WindowActivationState == CoreWindowActivationState.Deactivated)
{
//dispose MediaCapture here
}
else if(e.WindowActivationState == CoreWindowActivationState.CodeActivated || e.WindowActivationState == CoreWindowActivationState.PointerActivated)
{
//initialize MediaCapture here
}
}
我不确定使用 Suspending/Resuming 事件是否更合适。请注意,在这种情况下,您必须正确调试它 - 它 behaves little different while being run with/without debugger attached.
至于代码 - 在 OnNavigatedTo/OnNavigatedFrom 挂钩你的事件不是一个好主意 - 当 OS 暂停应用程序并且你正在使用 SuspensionManager 然后 OnNavigatedFrom 将被调用,但是当您返回您的应用程序(恢复它)时,然后 OnNavigatedTo 不会被调用。
使用Window事件也可以在这里工作,但为什么不在构造函数的某个地方订阅一次呢? - 它是 window-wide,因此在 phone 中只有一个 window,它代表应用程序,然后订阅一次。在这种情况下,您可以添加一行来识别 window 中的当前页面,如果该页面包含 mediacapture 然后处理(创建类似的)。然后,您还可以 dispose/initialize 在导航事件中,以防用户不离开您的应用而只是导航。
在 中查看我的回答。我相信将 Window.VisibilityChanged
与 Page\UserControl Loaded\Unloaded 处理程序结合使用应该可以解决您的问题。
使用 Window.Activated
不如 Window.VisibilityChanged
理想,因为 Activated 与可见性和焦点相关,而 VisibilityChanged 仅与可见性有关。对于显示具有焦点的预览不适用。由于 Windows Windows Phone 上的商店应用只能有一个 Window 显示使用两者都没有区别但是如果您的应用变得通用并且运行在 Windows 8+ Modern shell(可以通过 Snap window 功能显示多个 Store 应用)或 Windows 10 desktop(可以支持同时显示多个 Store 应用)当用户从您的应用更改焦点但您的应用仍在显示时,不想停止预览。
[问题]
On Windows Phone 8.1,在用户离开应用程序和 OnSuspended 事件触发之间到底发生了什么?我无法管理该范围内的对象,尤其是 MediaCpture 对象。
为了更好地解释问题,这里是场景:
- 用户所在的页面上有视频预览被推送到 CaptureElement
- 用户点击“开始”按钮
- 用户点击“后退”按钮 returns 到 MediaCapture 损坏的页面
对于 WinRT,没有 ObscuredEvent 并且 OnNavigatingFrom 不会触发,除非您要转到同一页面中的另一个页面框架。经过一些调查,我发现唯一触发的事件是 Window.Current.VisibilityChanged
我已经继续并在页面 NavigatedTo 中挂钩它并在 OnNavigatedFrom 中取消挂钩(参见下面的 ex2)。在该事件中,我检查指示应用程序是隐藏还是显示的参数,并相应地 dispose/initialize(参见下面的示例 1)。
[问题]
但是,此仅适用于附加的调试器。如果我在没有连接调试器的情况下执行此操作,它不会重新初始化并且 经常使相机崩溃 我必须重新启动设备。
代码示例 1(注意:e.Visible == false 离开应用程序,返回时为 true)
async void Current_VisibilityChanged(object sender, VisibilityChangedEventArgs e)
{
if (!e.Visible) //means leaving the app
{
await DisposeAll(); //cleans the MediaCapture and CaptureElement
}
else
{
if(mediaCaptureManager != null) await DisposeAll();
await Initialization(); //set up camera again
}
}
示例 2(连接到事件中)
protected override void OnNavigatedTo(NavigationEventArgs e)
{
Window.Current.VisibilityChanged += Current_VisibilityChanged;
this.navigationHelper.OnNavigatedTo(e);
}
protected async override void OnNavigatedFrom(NavigationEventArgs e)
{
Window.Current.VisibilityChanged -= Current_VisibilityChanged;
this.navigationHelper.OnNavigatedFrom(e);
}
[更新:决议]
不使用 VisibilityChanged,而是挂接到页面构造函数中的 Window.Current.Activated。在调试器完全分离的情况下,Activated 事件将在 WindowActivatedEventArgs 中提供 WindowActivationState 参数。像这样:
private async void CurrentOnActivated(object sender, WindowActivatedEventArgs e)
{
if(e.WindowActivationState == CoreWindowActivationState.Deactivated)
{
//dispose MediaCapture here
}
else if(e.WindowActivationState == CoreWindowActivationState.CodeActivated || e.WindowActivationState == CoreWindowActivationState.PointerActivated)
{
//initialize MediaCapture here
}
}
我不确定使用 Suspending/Resuming 事件是否更合适。请注意,在这种情况下,您必须正确调试它 - 它 behaves little different while being run with/without debugger attached.
至于代码 - 在 OnNavigatedTo/OnNavigatedFrom 挂钩你的事件不是一个好主意 - 当 OS 暂停应用程序并且你正在使用 SuspensionManager 然后 OnNavigatedFrom 将被调用,但是当您返回您的应用程序(恢复它)时,然后 OnNavigatedTo 不会被调用。
使用Window事件也可以在这里工作,但为什么不在构造函数的某个地方订阅一次呢? - 它是 window-wide,因此在 phone 中只有一个 window,它代表应用程序,然后订阅一次。在这种情况下,您可以添加一行来识别 window 中的当前页面,如果该页面包含 mediacapture 然后处理(创建类似的)。然后,您还可以 dispose/initialize 在导航事件中,以防用户不离开您的应用而只是导航。
在 中查看我的回答。我相信将 Window.VisibilityChanged
与 Page\UserControl Loaded\Unloaded 处理程序结合使用应该可以解决您的问题。
使用 Window.Activated
不如 Window.VisibilityChanged
理想,因为 Activated 与可见性和焦点相关,而 VisibilityChanged 仅与可见性有关。对于显示具有焦点的预览不适用。由于 Windows Windows Phone 上的商店应用只能有一个 Window 显示使用两者都没有区别但是如果您的应用变得通用并且运行在 Windows 8+ Modern shell(可以通过 Snap window 功能显示多个 Store 应用)或 Windows 10 desktop(可以支持同时显示多个 Store 应用)当用户从您的应用更改焦点但您的应用仍在显示时,不想停止预览。