应用开发中,开发者时常需要获取一些系统、用户信息用于数据统计遥测、问题反馈、用户识别等功能。本文旨在介绍在 Windows UWP 应用中获取一些常用系统、用户信息的方法。示例项目代码可参见 Github:
https://github.com/validvoid/UWP-SystemInfoCollector
由于涉及内容较多,故本文会分为多篇展开。本篇介绍获取设备和系统的基本信息、应用包信息、用户数据账户信息和用户账户信息。
Windows.System.Profile
命名空间下的 AnalyticsInfo 类负责提供用于设备分析的相关信息。通过此类,我们能够获得系统的具体版本号以及设备类型等信息。
通过 AnalyticsInfo
类中的 VersionInfo
属性我们可以获取当前应用运行设备的设备类型和操作系统具体版本。 AnalyticsVersionInfo 类型的 VersionInfo
属性包含两个成员:
DeviceFamily
属性的返回值类型为字符串。其提供的设备类型信息极为重要,几乎在所有 UWP 开发中均会用到。通常我们都会根据此属性返回的设备类型信息配合实现应用的响应式设计。例如,返回 "Windows.Desktop" 时表示应用运行在桌面端 Windows 10 上,则应用呈现适合于鼠标键盘操作的 PC 端界面;返回 "Windows.Mobile" 时表示应用运行在移动端的 Windows 10 上,则应用应当呈现适合于触屏操作的移动端小屏界面。
DeviceFamilyVersion
属性的返回值类型也是字符串。其返回值指示了当前设备运行的 Windows 的具体版本号。不过直接获取此属性拿到的返回值是一个形如 "2814750460870692" 的 long 型数字。如果想要获取可读的 "major.minor.revision.build" 形式的版本号,需要先将此数值转化为十六进制,然后进一步转化为可读的版本号。
格式化版本号的 C# 代码:
string sv = AnalyticsInfo.VersionInfo.DeviceFamilyVersion; ulong v = ulong.Parse(sv); ulong v1 = (v & 0xFFFF000000000000L) >> 48; ulong v2 = (v & 0x0000FFFF00000000L) >> 32; ulong v3 = (v & 0x00000000FFFF0000L) >> 16; ulong v4 = (v & 0x000000000000FFFFL); string version = $"{v1}.{v2}.{v3}.{v4}";
运行示例代码会得以类似以下内容的输出:
Device Analytics Info DeviceForm: Unknown DeviceFamily: Windows.Desktop DeviceFamilyVersion: 2814750460870692 Reconstructed OS Version: 10.0.10586.36
需要指出的是,如果你打算通过 DeviceFamilyVersion 进行数据统计、分析工作,那么在应用的客户端代码中不要将原始的 DeviceFamilyVersion 返回值格式化为可读形式。据微软官方人员在 MSDN 的解释, AnalyticsInfo.VersionInfo
旨在为遥测和日志记录提供一个不透明的版本号字符串值,最佳做法是将该原始值传回服务器,如果有必要,在服务器端进行格式化解析的工作。
另外, AnalyticsInfo
类中的 DeviceForm
属性具体作用不明,在 PC 和 Windows Mobile 设备中均返回 "Unknown"。MSDN 文档中仅将此属性描述为 "Gets the device form."
Windows.ApplicationModel.Resources.Core.ResourceContext
类封装了可能影响资源选定的资源限定符(qualifiers)。这些资源限定符影响了应用运行时所需资源的选定。查询资源限定符并做出适当匹配优化对于增进用户体验也有帮助。
要获得当前应用的资源限定符,我们需要调用 ResourceContext.GetForCurrentView()
方法获得当前应用视图的资源上下文,再访问其中的 QualifierValues
属性。 QualifierValues
属性的类型为 IObservableMap<string,string>
,可通过键名获得对应的限定符值。
以下为 MSDN 文档中列举的可能的资源限定符名称以及对应取值:
资源限定符 | 可能的取值 | 说明 |
---|---|---|
Language | 如 "en-us" | 此限定符名称可以映射到表示语言的字符串值,例如,"en-us" 表示美国英语。 |
Contrast | standard | 此限定符名称可以映射到当前对比度设置值。 |
high | ||
black | ||
white | ||
Scale | 80 | 此限定符名称可以映射到以百分比形式表示显示比例的值。 |
100 | ||
120 | ||
140 | ||
150 | ||
160 | ||
180 | ||
225 | ||
HomeRegion | 如 "021" | 此限定符名称可以映射到表示区域的字符串值,例如,"021" 表示北美。 |
TargetSize | 如 "256" | 此限定符名称可以映射到表示目标大小的字符串值,例如,"256"。 |
LayoutDirection | LTR | 此限定符名称可以映射到当前布局方向的值。 |
RTL | ||
TTBLTR | ||
TTBRTL | ||
Configuration | 此限定符名称可以映射到表示配置的字符串值。 | |
AlternateForm | 此限定符名称可以映射到表示替换窗体的字符串值。 | |
DXFeatureLevel | DX9 | 此限定符名称可以映射到表示 DirectX 功能级别。 |
DX10 | ||
DX11 |
有关 ResourceContext
类的更多用法,可以参阅 MSDN 文档 ResourceContext 类型 。
Windows.ApplicationModel.Package 类型负责提供应用包的信息。要获取当前应用的 Package 对象实例,可以通过 'Package.Current' 属性获取。获取当前应用的包对象之后,我们就可以进一步获得以下信息:
StorageFolder
类型。 Uri
类型。 除以上属性外, Package
类还提供了三个重要的属性: Id 、 Status 以及 Dependencies 。
Id
属性为 PackageId 类型。该属性提供了当前包 Id 的各种信息,包括:
PackageVersion
类型,可进一步格式化输出字符串。 ProductID
属性值。仅限 Windows Phone,在 Windows 10 上无效。 Status
属性为 PackageStatus 类型。该类型提供了一个 VerifyisOK()
方法用于判断当前包的状态是否良好,可以使用。该方法会验证 PackageStatus
中的一系列属性以判断包是否可用。 PackageStatus
包含的属性如下:
NotAvailable
, LicenseIssue
, Modified
, Tampered
中的一个或多个属性指示出当前包存在异常情况时,该属性即为 true。 DataOffline
, Disabled
, PackageOffline
中的一个或多个属性指示出当前包存在异常情况时,该属性即为 true。 Dependencies
属性为 IReadOnlyList<Package>
类型,可用于获取当前包的所有依赖项。注意该属性仅用于获取 Windows Store 应用包的依赖项。要获取一个桌面应用包的依赖项,需使用 Win32 函数 GetPackageInfo 。
有关 Package
的具体用法可参见 Github 上的示例代码。
Windows.Phone.Management.Deployment
命名空间下提供了一系列用于控制应用部署功能的类型,其中 InstallationManager 类型负责应用包的安装管理。我们可以通过其中的 FindPackagesForCurrentPublisher
方法获得当前 Windows Mobile 设备上安装的同一发布者的应用包部署情况。该方法的返回类型为 IEnumerable<Package>
,我们可以进一步检索返回值获取具体某个应用包的详细信息甚至启动这些应用。
值得说明的是, Windows.Phone.Management.Deployment
仅在 Windows Mobile 设备上有效 ,故在 UWP 应用中使用时,需要配合 AnalyticsInfo.VersionInfo.DeviceFamily
检测当前设备类型,选择是否调用该命名空间下的方法。另外,'InstallationManager' 类中提供的其它方法需要 ID_CAP_OEM_DEPLOYMENT
特别权限才能够正常使用,故一般开发者无法使用。
用户数据账户是什么呢?举例说明,如果你用过 Android 系统,那么你在 Android 的系统设置中会看到一项名为“账户”(Accounts)的设置栏目,其中列出了当前系统登录的 Gmail、Outlook、Office、Exchange、微博等各种应用注册的账户。这些账户就是用户数据账户。 Windows.ApplicationModel.UserDataAccounts
命名空间定义了用于控制邮件、预约、日历等用户数据账户信息的相关类型和枚举。其中, UserDataAccount 类型表示一个用于存取邮件、联系人、日历等数据的用户数据账户。 UserDataAccountManager 类型提供了与用户数据账户交互的 API。 UserDataAccountStore 代表用户数据账户的储存区。本文主要讲述如何通过 Windows Store App API 获取一些常用的信息,故在此不涉及操作用户数据账户的内容。仅关注如何获得一些数据。
要使用 UserDataAccounts
相关 API,要求应用在清单文件中声明联系人(contacts)、约会(appointments)、邮件(email)等功能中的一个或多个。
假设我们想要列举出当前系统上登录的所有用户数据账户,并输出这些账户的相关信息,首先我们需要通过 UserDataAccountManager.RequestStoreAsync
方法向系统请求用户数据账户的储存区。该方法接受一个 UserDataAccountStoreAccessType 枚举类型的参数。该参数用于指定要求的用户数据账户存储区的访问类型。 UserDataAccountStoreAccessType
枚举包含两个成员:
AllAccountsReadOnly
对应用以及系统的用户数据账户进行只读访问 AppAccountsReadWrite
对当前应用的用户数据储存区进行读/写访问 由枚举可知,我们虽然可以检索当前应用自身以外的用户数据账户,但对于自身以外的用户数据账户并没有写权限。
这里我们选择第一种访问类型,使用以下代码请求用户数据账户储存区:
UserDataAccountStore userDataAccountStore = await UserDataAccountManager.RequestStoreAsync(UserDataAccountStoreAccessType.AllAccountsReadOnly);
获取到的用户数据账户储存区实例为 UserDataAccountStore
类型,该类型包含三个方法:
这里我们调用 FindAccountsAsync
即可获得所有用户数据账户,并进行下一步操作。具体演示可参见 Github 上的示例代码。
在 Windows 8 应用中,我们使用 Windows.System.UserProfile
命名空间中的 UserInformation 访问系统登录的用户账户信息。而在 Windows 10 以及以后版本的 Windows 中, UserInformation
不再被支持。因为在 Windows 10 中,除非用户授权,应用是不能获取用户信息的。而 Windows 8 应用则是默认得到授权的。并且,旧的 Windows 8 应用运行于 Windows 10 时也无法正常获取用户信息。
在 Windows 10 上我们需要使用新的 API 提供的 Windows.System.User 类型获取用户信息。注意使用该 API 需要应用在清单文件中配置“用户账户信息”(User Account Information) 功能。
User
类提供了三个静态方法及其重载:
我们可以通过 FindAllAsync
或 GetFromId
方法获取用户账户实例,获取用户后,可以通过调用 GetPropertyAsync 方法取得该用户的属性信息。 GetPropertyAsync
方法接受一个 string 类型的参数,具体传入内容可以通过 KnownUserProperties 类中定义的属性获取。 KnownUserProperties
类中定义了已知可用的用户账户属性键名。例如,我们想要获取账户显示名称时,可以采用如下方法:
string displayName = await user.GetPropertyAsync(KnownUserProperties.DisplayName);
User
类还包含以下三个属性成员:
配合使用 UserDataAccount 和 User 两个 API 可以使应用更好地实现唯一用户识别、用户账户体系、自定义授权等功能特性。
更多内容请参阅本文后续内容更新。