需求
最近在做UWP的项目,其中有这样一个的需求:统计用户使用APP的时长。
思路
在用户打开app的时候,记录一个时间点t1
;然后在关闭app的时候记录第二个时间点t2
。在APP退出前上传时间差t2-t1
。关键问题点是如何知道关掉APP的时刻,也就是说需要知道关掉APP的事件才行。
实现
带着这样的问题,我们就开始在uwp
中寻找这样的事件。在uwp
的CoreApplication
类中还真发现有一个貌似满足我们需求的事件,Exiting
事件,那我们就赶紧在App.xaml.cs
中去处理这个事件。
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
CoreApplication.Exiting += (s, e) =>
{
Debug.WriteLine("CoreApplication.Exiting");
};
}
我们在第7行处加入断点看看程序在关掉app的时候能否跑进来。结果让人比较失望,发现在关闭app的时候,程序并没有执行到断点处。然后查找文档,微软的文档告诉我们“Windows Phone 8,This API is supported in native apps only.”看来此路不通。
于是开始启用面向谷歌编程的能力,发现uwp在Windows 10 Creators Update (10.0.15063.0)之后引入了一个类SystemNavigationManagerPreview
,这个类只做一件事情,就是向用户提供了一种能够响应关闭程序的方法。也就是CloseRequested
事件。微软的文档告诉我们:在用户点击了标题栏上的X
关闭按钮时会触发该事件。同时文档说,要想使用这个事件,需要先开启一个confirmAppClose
受限功能。
开启方法如下:
在工程的Package.appxmanifest
中添加以下代码。
xmlns:rescap="http://schemas.microsoft.com/appx/manifest/foundation/windows10/restrictedcapabilities"
<rescap:Capability Name="confirmAppClose"/>
受限功能开启后,我们需要在代码中去处理CloseRequested
事件。
public MainPage()
{
this.InitializeComponent();
。 SystemNavigationManagerPreview.GetForCurrentView().CloseRequested += (s, e) =>
{
var deferral = e.GetDeferral();
//Do extra task here
Debug.WriteLine("Do extra task here");
deferral.Complete();
};
}
迫不及待的运行起来,实验证明:在关掉app的时候,output中确实有Do extra task here
的日志输出。这说明CloseRequested
事件是有效的。
说明:代码var deferral = e.GetDeferral();
和deferral.Complete();
是必须要加的,这让uwp应用程序会确保extra task做完后再退出去。
小结
找到了CloseRequested
事件,我们的需求就能够解决了。当然我们还可以在这个事件里面做更多的事情以提升用户体验,比如在关闭APP的时候弹出一个对话框,询问用户是否保存用户数据等等。
程序员的工作就是不断填坑的过程。好记性不如烂笔头,写此博文,记录下自己填坑的过程,避免第二次填坑时仍然填的那么费力。如能帮到有需要的小伙伴,那将是我的荣幸。
参考
- special-and-restricted-capabilities(https://docs.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations?redirectedfrom=MSDN#special-and-restricted-capabilities)
- https://docs.microsoft.com/en-us/windows/uwp/packaging/app-capability-declarations?redirectedfrom=MSDN