Merge pull request #3 from kartelan/master
Refactor SensorCore sample to show use of ActivitySensor and Pedometer in OS APIs
This commit is contained in:
Коммит
fdab69c6b1
|
@ -1,178 +0,0 @@
|
|||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
# User-specific files
|
||||
*.suo
|
||||
*.user
|
||||
*.sln.docstates
|
||||
|
||||
# Build results
|
||||
[Dd]ebug/
|
||||
[Dd]ebugPublic/
|
||||
[Rr]elease/
|
||||
x64/
|
||||
build/
|
||||
bld/
|
||||
[Bb]in/
|
||||
[Oo]bj/
|
||||
|
||||
# MSTest test Results
|
||||
[Tt]est[Rr]esult*/
|
||||
[Bb]uild[Ll]og.*
|
||||
|
||||
#NUNIT
|
||||
*.VisualState.xml
|
||||
TestResult.xml
|
||||
|
||||
# Build Results of an ATL Project
|
||||
[Dd]ebugPS/
|
||||
[Rr]eleasePS/
|
||||
dlldata.c
|
||||
|
||||
*_i.c
|
||||
*_p.c
|
||||
*_i.h
|
||||
*.ilk
|
||||
*.meta
|
||||
*.obj
|
||||
*.pch
|
||||
*.pdb
|
||||
*.pgc
|
||||
*.pgd
|
||||
*.rsp
|
||||
*.sbr
|
||||
*.tlb
|
||||
*.tli
|
||||
*.tlh
|
||||
*.tmp
|
||||
*.tmp_proj
|
||||
*.log
|
||||
*.vspscc
|
||||
*.vssscc
|
||||
.builds
|
||||
*.pidb
|
||||
*.svclog
|
||||
*.scc
|
||||
|
||||
# Chutzpah Test files
|
||||
_Chutzpah*
|
||||
|
||||
# Visual C++ cache files
|
||||
ipch/
|
||||
*.aps
|
||||
*.ncb
|
||||
*.opensdf
|
||||
*.sdf
|
||||
*.cachefile
|
||||
|
||||
# Visual Studio profiler
|
||||
*.psess
|
||||
*.vsp
|
||||
*.vspx
|
||||
|
||||
# TFS 2012 Local Workspace
|
||||
$tf/
|
||||
|
||||
# Guidance Automation Toolkit
|
||||
*.gpState
|
||||
|
||||
# ReSharper is a .NET coding add-in
|
||||
_ReSharper*/
|
||||
*.[Rr]e[Ss]harper
|
||||
*.DotSettings.user
|
||||
|
||||
# JustCode is a .NET coding addin-in
|
||||
.JustCode
|
||||
|
||||
# TeamCity is a build add-in
|
||||
_TeamCity*
|
||||
|
||||
# DotCover is a Code Coverage Tool
|
||||
*.dotCover
|
||||
|
||||
# NCrunch
|
||||
*.ncrunch*
|
||||
_NCrunch_*
|
||||
.*crunch*.local.xml
|
||||
|
||||
# MightyMoose
|
||||
*.mm.*
|
||||
AutoTest.Net/
|
||||
|
||||
# Web workbench (sass)
|
||||
.sass-cache/
|
||||
|
||||
# Installshield output folder
|
||||
[Ee]xpress/
|
||||
|
||||
# DocProject is a documentation generator add-in
|
||||
DocProject/buildhelp/
|
||||
DocProject/Help/*.HxT
|
||||
DocProject/Help/*.HxC
|
||||
DocProject/Help/*.hhc
|
||||
DocProject/Help/*.hhk
|
||||
DocProject/Help/*.hhp
|
||||
DocProject/Help/Html2
|
||||
DocProject/Help/html
|
||||
|
||||
# Click-Once directory
|
||||
publish/
|
||||
|
||||
# Publish Web Output
|
||||
*.[Pp]ublish.xml
|
||||
*.azurePubxml
|
||||
|
||||
# NuGet Packages Directory
|
||||
packages/
|
||||
## TODO: If the tool you use requires repositories.config uncomment the next line
|
||||
#!packages/repositories.config
|
||||
|
||||
# Enable "build/" folder in the NuGet Packages folder since NuGet packages use it for MSBuild targets
|
||||
# This line needs to be after the ignore of the build folder (and the packages folder if the line above has been uncommented)
|
||||
!packages/build/
|
||||
|
||||
# Windows Azure Build Output
|
||||
csx/
|
||||
*.build.csdef
|
||||
|
||||
# Windows Store app package directory
|
||||
AppPackages/
|
||||
|
||||
# Others
|
||||
sql/
|
||||
*.Cache
|
||||
ClientBin/
|
||||
[Ss]tyle[Cc]op.*
|
||||
~$*
|
||||
*~
|
||||
*.dbmdl
|
||||
*.dbproj.schemaview
|
||||
*.pfx
|
||||
*.publishsettings
|
||||
node_modules/
|
||||
|
||||
# RIA/Silverlight projects
|
||||
Generated_Code/
|
||||
|
||||
# Backup & report files from converting an old project file to a newer
|
||||
# Visual Studio version. Backup files are not needed, because we have git ;-)
|
||||
_UpgradeReport_Files/
|
||||
Backup*/
|
||||
UpgradeLog*.XML
|
||||
UpgradeLog*.htm
|
||||
|
||||
# SQL Server files
|
||||
*.mdf
|
||||
*.ldf
|
||||
|
||||
# Business Intelligence projects
|
||||
*.rdl.data
|
||||
*.bim.layout
|
||||
*.bim_*.settings
|
||||
|
||||
# Microsoft Fakes
|
||||
FakesAssemblies/
|
||||
|
||||
#WindowsStore build artefacts
|
||||
BundleArtifacts
|
||||
.nuget/NuGet.exe
|
|
@ -1,6 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<solution>
|
||||
<add key="disableSourceControlIntegration" value="true" />
|
||||
</solution>
|
||||
</configuration>
|
|
@ -1,144 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">$(MSBuildProjectDirectory)\..\</SolutionDir>
|
||||
|
||||
<!-- Enable the restore command to run before builds -->
|
||||
<RestorePackages Condition=" '$(RestorePackages)' == '' ">true</RestorePackages>
|
||||
|
||||
<!-- Property that enables building a package from a project -->
|
||||
<BuildPackage Condition=" '$(BuildPackage)' == '' ">false</BuildPackage>
|
||||
|
||||
<!-- Determines if package restore consent is required to restore packages -->
|
||||
<RequireRestoreConsent Condition=" '$(RequireRestoreConsent)' != 'false' ">true</RequireRestoreConsent>
|
||||
|
||||
<!-- Download NuGet.exe if it does not already exist -->
|
||||
<DownloadNuGetExe Condition=" '$(DownloadNuGetExe)' == '' ">true</DownloadNuGetExe>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(PackageSources)' == '' ">
|
||||
<!-- Package sources used to restore packages. By default, registered sources under %APPDATA%\NuGet\NuGet.Config will be used -->
|
||||
<!-- The official NuGet package source (https://www.nuget.org/api/v2/) will be excluded if package sources are specified and it does not appear in the list -->
|
||||
<!--
|
||||
<PackageSource Include="https://www.nuget.org/api/v2/" />
|
||||
<PackageSource Include="https://my-nuget-source/nuget/" />
|
||||
-->
|
||||
</ItemGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' == 'Windows_NT'">
|
||||
<!-- Windows specific commands -->
|
||||
<NuGetToolsPath>$([System.IO.Path]::Combine($(SolutionDir), ".nuget"))</NuGetToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(OS)' != 'Windows_NT'">
|
||||
<!-- We need to launch nuget.exe with the mono command if we're not on windows -->
|
||||
<NuGetToolsPath>$(SolutionDir).nuget</NuGetToolsPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PackagesProjectConfig Condition=" '$(OS)' == 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName.Replace(' ', '_')).config</PackagesProjectConfig>
|
||||
<PackagesProjectConfig Condition=" '$(OS)' != 'Windows_NT'">$(MSBuildProjectDirectory)\packages.$(MSBuildProjectName).config</PackagesProjectConfig>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<PackagesConfig Condition="Exists('$(MSBuildProjectDirectory)\packages.config')">$(MSBuildProjectDirectory)\packages.config</PackagesConfig>
|
||||
<PackagesConfig Condition="Exists('$(PackagesProjectConfig)')">$(PackagesProjectConfig)</PackagesConfig>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<!-- NuGet command -->
|
||||
<NuGetExePath Condition=" '$(NuGetExePath)' == '' ">$(NuGetToolsPath)\NuGet.exe</NuGetExePath>
|
||||
<PackageSources Condition=" $(PackageSources) == '' ">@(PackageSource)</PackageSources>
|
||||
|
||||
<NuGetCommand Condition=" '$(OS)' == 'Windows_NT'">"$(NuGetExePath)"</NuGetCommand>
|
||||
<NuGetCommand Condition=" '$(OS)' != 'Windows_NT' ">mono --runtime=v4.0.30319 $(NuGetExePath)</NuGetCommand>
|
||||
|
||||
<PackageOutputDir Condition="$(PackageOutputDir) == ''">$(TargetDir.Trim('\\'))</PackageOutputDir>
|
||||
|
||||
<RequireConsentSwitch Condition=" $(RequireRestoreConsent) == 'true' ">-RequireConsent</RequireConsentSwitch>
|
||||
<NonInteractiveSwitch Condition=" '$(VisualStudioVersion)' != '' AND '$(OS)' == 'Windows_NT' ">-NonInteractive</NonInteractiveSwitch>
|
||||
|
||||
<PaddedSolutionDir Condition=" '$(OS)' == 'Windows_NT'">"$(SolutionDir) "</PaddedSolutionDir>
|
||||
<PaddedSolutionDir Condition=" '$(OS)' != 'Windows_NT' ">"$(SolutionDir)"</PaddedSolutionDir>
|
||||
|
||||
<!-- Commands -->
|
||||
<RestoreCommand>$(NuGetCommand) install "$(PackagesConfig)" -source "$(PackageSources)" $(NonInteractiveSwitch) $(RequireConsentSwitch) -solutionDir $(PaddedSolutionDir)</RestoreCommand>
|
||||
<BuildCommand>$(NuGetCommand) pack "$(ProjectPath)" -Properties "Configuration=$(Configuration);Platform=$(Platform)" $(NonInteractiveSwitch) -OutputDirectory "$(PackageOutputDir)" -symbols</BuildCommand>
|
||||
|
||||
<!-- We need to ensure packages are restored prior to assembly resolve -->
|
||||
<BuildDependsOn Condition="$(RestorePackages) == 'true'">
|
||||
RestorePackages;
|
||||
$(BuildDependsOn);
|
||||
</BuildDependsOn>
|
||||
|
||||
<!-- Make the build depend on restore packages -->
|
||||
<BuildDependsOn Condition="$(BuildPackage) == 'true'">
|
||||
$(BuildDependsOn);
|
||||
BuildPackage;
|
||||
</BuildDependsOn>
|
||||
</PropertyGroup>
|
||||
|
||||
<Target Name="CheckPrerequisites">
|
||||
<!-- Raise an error if we're unable to locate nuget.exe -->
|
||||
<Error Condition="'$(DownloadNuGetExe)' != 'true' AND !Exists('$(NuGetExePath)')" Text="Unable to locate '$(NuGetExePath)'" />
|
||||
<!--
|
||||
Take advantage of MsBuild's build dependency tracking to make sure that we only ever download nuget.exe once.
|
||||
This effectively acts as a lock that makes sure that the download operation will only happen once and all
|
||||
parallel builds will have to wait for it to complete.
|
||||
-->
|
||||
<MsBuild Targets="_DownloadNuGet" Projects="$(MSBuildThisFileFullPath)" Properties="Configuration=NOT_IMPORTANT;DownloadNuGetExe=$(DownloadNuGetExe)" />
|
||||
</Target>
|
||||
|
||||
<Target Name="_DownloadNuGet">
|
||||
<DownloadNuGet OutputFilename="$(NuGetExePath)" Condition=" '$(DownloadNuGetExe)' == 'true' AND !Exists('$(NuGetExePath)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="RestorePackages" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
Condition="'$(OS)' != 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
|
||||
<Exec Command="$(RestoreCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition="'$(OS)' == 'Windows_NT' And Exists('$(PackagesConfig)')" />
|
||||
</Target>
|
||||
|
||||
<Target Name="BuildPackage" DependsOnTargets="CheckPrerequisites">
|
||||
<Exec Command="$(BuildCommand)"
|
||||
Condition=" '$(OS)' != 'Windows_NT' " />
|
||||
|
||||
<Exec Command="$(BuildCommand)"
|
||||
LogStandardErrorAsError="true"
|
||||
Condition=" '$(OS)' == 'Windows_NT' " />
|
||||
</Target>
|
||||
|
||||
<UsingTask TaskName="DownloadNuGet" TaskFactory="CodeTaskFactory" AssemblyFile="$(MSBuildToolsPath)\Microsoft.Build.Tasks.v4.0.dll">
|
||||
<ParameterGroup>
|
||||
<OutputFilename ParameterType="System.String" Required="true" />
|
||||
</ParameterGroup>
|
||||
<Task>
|
||||
<Reference Include="System.Core" />
|
||||
<Using Namespace="System" />
|
||||
<Using Namespace="System.IO" />
|
||||
<Using Namespace="System.Net" />
|
||||
<Using Namespace="Microsoft.Build.Framework" />
|
||||
<Using Namespace="Microsoft.Build.Utilities" />
|
||||
<Code Type="Fragment" Language="cs">
|
||||
<![CDATA[
|
||||
try {
|
||||
OutputFilename = Path.GetFullPath(OutputFilename);
|
||||
|
||||
Log.LogMessage("Downloading latest version of NuGet.exe...");
|
||||
WebClient webClient = new WebClient();
|
||||
webClient.DownloadFile("https://www.nuget.org/nuget.exe", OutputFilename);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex) {
|
||||
Log.LogErrorFromException(ex);
|
||||
return false;
|
||||
}
|
||||
]]>
|
||||
</Code>
|
||||
</Task>
|
||||
</UsingTask>
|
||||
</Project>
|
|
@ -1,4 +1,16 @@
|
|||
<Page
|
||||
<!--
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
-->
|
||||
<Page
|
||||
x:Class="ActivitiesExample.AboutPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
|
@ -22,7 +34,8 @@
|
|||
<TextBlock x:Uid="ApplicationName" Style="{ThemeResource TitleTextBlockStyle}" Typography.Capitals="SmallCaps" Foreground="White"/>
|
||||
<TextBlock x:Uid="AboutPage" Style="{ThemeResource HeaderTextBlockStyle}" Foreground="White"/>
|
||||
</StackPanel>
|
||||
<StackPanel x:Name="ContentPanel" Grid.Row="1" Margin="24,24,24,0">
|
||||
<ScrollViewer Grid.Row="1">
|
||||
<StackPanel x:Name="ContentPanel" Margin="24,24,24,0">
|
||||
<RichTextBlock FontSize="16">
|
||||
<Paragraph>
|
||||
<Run x:Uid="VersionText" Text="_version: " Foreground="White"/>
|
||||
|
@ -44,5 +57,6 @@
|
|||
<HyperlinkButton x:Uid="AboutHyperlinkProject" NavigateUri="http://"
|
||||
Content="_project link" FontSize="24"/>
|
||||
</StackPanel>
|
||||
</ScrollViewer>
|
||||
</Grid>
|
||||
</Page>
|
|
@ -1,4 +1,5 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2015 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
|
|
@ -0,0 +1,709 @@
|
|||
/*
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2015 Microsoft
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
using ActivitiesExample.Data;
|
||||
using Lumia.Sense;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Resources;
|
||||
using Windows.Devices.Sensors;
|
||||
using Windows.Foundation;
|
||||
using Windows.Security.ExchangeActiveSyncProvisioning;
|
||||
using Windows.UI.Popups;
|
||||
using Windows.UI.Xaml;
|
||||
|
||||
namespace ActivitiesExample
|
||||
{
|
||||
public delegate void ReadingChangedEventHandler(object sender, object args);
|
||||
/// <summary>
|
||||
/// Platform agnostic Activity Sensor interface.
|
||||
/// This interface is implementd by OSActivitySensor and LumiaActivitySensor.
|
||||
/// </summary>
|
||||
public interface IActivitySensor
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes the sensor.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task</returns>
|
||||
Task InitializeSensorAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Activates the sensor and registers for reading changed notifications.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task</returns>
|
||||
Task ActivateAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Deactivates sensor the sensor and registers for reading changed notifications.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task</returns>
|
||||
Task DeactivateAsync();
|
||||
|
||||
/// <summary>
|
||||
/// Pull activity entries from history database and populate the internal list.
|
||||
/// </summary>
|
||||
/// <param name="DayOffset">DayOffset from current day</param>
|
||||
/// <returns>Asynchronous task</returns>
|
||||
Task UpdateSummaryAsync(uint DayOffset);
|
||||
|
||||
/// <summary>
|
||||
/// Update current cached activity of the user.
|
||||
/// </summary>
|
||||
/// <param name="args">Current Activity reported by the sensor. Type of this argument is either Windows.Devices.Sensors.ActivityType or Lumia.Sense.Activity</param>
|
||||
void UpdateCurrentActivity(object args);
|
||||
|
||||
/// <summary>
|
||||
/// Get an instance of ActivityData<T>. This is the data source that reflects
|
||||
/// the history entries that gets displayed in the UI.
|
||||
/// </summary>
|
||||
object GetActivityDataInstance();
|
||||
|
||||
/// <summary>
|
||||
/// Delegate for receving reading changed events.
|
||||
/// </summary>
|
||||
event ReadingChangedEventHandler ReadingChanged;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Factory class for instantiating Activity Sensor. If there an activity sensor surfaced
|
||||
/// through Windows.Devices.Sensor then the factory creates an instance of OSActivitySensor
|
||||
/// otherwise this falls back to using LumiaActivitySensor.
|
||||
/// </summary>
|
||||
public static class ActivitySensorFactory
|
||||
{
|
||||
/// <summary>
|
||||
/// Static method to get the default activity sensor present in the system.
|
||||
/// </summary>
|
||||
public static async Task<IActivitySensor> GetDefaultAsync()
|
||||
{
|
||||
IActivitySensor sensor = null;
|
||||
|
||||
try
|
||||
{
|
||||
// Check if there is an activity sensor in the system
|
||||
ActivitySensor activitySensor = await ActivitySensor.GetDefaultAsync();
|
||||
|
||||
// If there is one then create OSActivitySensor.
|
||||
if (activitySensor != null)
|
||||
{
|
||||
sensor = new OSActivitySensor(activitySensor);
|
||||
}
|
||||
}
|
||||
catch (System.UnauthorizedAccessException)
|
||||
{
|
||||
// If there is an activity sensor but the user has disabled motion data
|
||||
// then check if the user wants to open settngs and enable motion data.
|
||||
MessageDialog dialog = new MessageDialog("Motion access has been disabled in system settings. Do you want to open settings now?", "Information");
|
||||
dialog.Commands.Add(new UICommand("Yes", async cmd => await Windows.System.Launcher.LaunchUriAsync(new Uri("ms-settings:privacy-motion"))));
|
||||
dialog.Commands.Add(new UICommand("No"));
|
||||
await dialog.ShowAsync();
|
||||
new System.Threading.ManualResetEvent(false).WaitOne(500);
|
||||
return null;
|
||||
}
|
||||
|
||||
// If the OS activity sensor is not present then create the LumiaActivitySensor.
|
||||
// This will use ActivityMonitor from SensorCore.
|
||||
if (sensor == null)
|
||||
{
|
||||
// Check if all the required settings have been configured correctly
|
||||
await LumiaActivitySensor.ValidateSettingsAsync();
|
||||
|
||||
sensor = new LumiaActivitySensor();
|
||||
}
|
||||
return sensor;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of IActivitySensor that surfaces Activity Sensor supported by the OS (Windows.Devices.Sensor.ActivitySensor).
|
||||
/// </summary>
|
||||
public class OSActivitySensor : IActivitySensor
|
||||
{
|
||||
#region Private members
|
||||
/// <summary>
|
||||
/// Singleton instance.
|
||||
/// </summary>
|
||||
protected static OSActivitySensor _self;
|
||||
|
||||
/// <summary>
|
||||
/// Physical sensor.
|
||||
/// </summary>
|
||||
private static Windows.Devices.Sensors.ActivitySensor _sensor = null;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new ResourceLoader object.
|
||||
/// </summary>
|
||||
static protected readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView("Resources");
|
||||
|
||||
/// <summary>
|
||||
/// Check if running in emulator.
|
||||
/// </summary>
|
||||
protected bool _runningInEmulator = false;
|
||||
|
||||
/// <summary>
|
||||
/// Reading changed handler.
|
||||
/// </summary
|
||||
public event ReadingChangedEventHandler ReadingChanged = null;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// OSActivitySensor constructor.
|
||||
/// </summary
|
||||
public OSActivitySensor(ActivitySensor sensor)
|
||||
{
|
||||
_sensor = sensor;
|
||||
// Using this method to detect if the application runs in the emulator or on a real device. Later the *Simulator API is used to read fake sense data on emulator.
|
||||
// In production code you do not need this and in fact you should ensure that you do not include the Lumia.Sense.Test reference in your project.
|
||||
EasClientDeviceInformation x = new EasClientDeviceInformation();
|
||||
if (x.SystemProductName.StartsWith("Virtual"))
|
||||
{
|
||||
_runningInEmulator = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the singleton instance of ActivityData<Windows.Devices.Sensors.ActivityType>.
|
||||
/// </summary>
|
||||
/// <returns>ActivityData/returns>
|
||||
public object GetActivityDataInstance()
|
||||
{
|
||||
return ActivityData<Windows.Devices.Sensors.ActivityType>.Instance();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize sensor.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous Task</returns>
|
||||
public Task InitializeSensorAsync()
|
||||
{
|
||||
// Subscribe to all supported acitivities
|
||||
foreach (ActivityType activity in _sensor.SupportedActivities)
|
||||
{
|
||||
_sensor.SubscribedActivities.Add(activity);
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activate the sensor. For activity sensor exposed through
|
||||
/// Windows.Devices.Sensor register reading changed handler.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task/returns>
|
||||
public Task ActivateAsync()
|
||||
{
|
||||
_sensor.ReadingChanged += new TypedEventHandler<ActivitySensor, ActivitySensorReadingChangedEventArgs>(ActivitySensor_ReadingChanged);
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactivate the sensor. For activity sensor exposed through
|
||||
/// Windows.Devices.Sensor unregister reading changed handler.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task/returns>
|
||||
public Task DeactivateAsync()
|
||||
{
|
||||
_sensor.ReadingChanged -= new TypedEventHandler<ActivitySensor, ActivitySensorReadingChangedEventArgs>(ActivitySensor_ReadingChanged);
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the reading in the screen.
|
||||
/// </summary>
|
||||
/// <returns>Nothing/returns>
|
||||
/// <param name="sender">The sender of the event</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
async private void ActivitySensor_ReadingChanged(object sender, ActivitySensorReadingChangedEventArgs e)
|
||||
{
|
||||
if (ReadingChanged != null)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
ActivitySensorReading reading = e.Reading;
|
||||
// Call into the reading changed handler registered by the client
|
||||
ReadingChanged(this, reading.Activity);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the activity at the given time
|
||||
/// </summary>
|
||||
/// <param name="sensor">Sensor instance</param>
|
||||
/// <param name="timestamp">Time stamp</param>
|
||||
/// <returns>Activity at the given time or <c>null</c> if no activity is found.</returns>
|
||||
public static async Task<ActivitySensorReading> GetActivityAtAsync(DateTimeOffset timestamp)
|
||||
{
|
||||
// We assume here that one day overshoot is enough to cover most cases. If the previous activity lasted longer
|
||||
// than that, we will miss it. Overshoot duration can be extended but will decrease performance.
|
||||
TimeSpan overshoot = TimeSpan.FromDays(1);
|
||||
IReadOnlyList<ActivitySensorReading> history = await ActivitySensor.GetSystemHistoryAsync(
|
||||
timestamp - overshoot,
|
||||
overshoot);
|
||||
if (history.Count > 0)
|
||||
{
|
||||
return history[history.Count - 1];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Updates the summary in the screen.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task/returns>
|
||||
/// <param name="DayOffset">Day offset</param>
|
||||
/// <returns>Asyncrhonous Task</returns>
|
||||
public async Task UpdateSummaryAsync(uint DayOffset)
|
||||
{
|
||||
// Read current activity
|
||||
ActivitySensorReading reading = await _sensor.GetCurrentReadingAsync();
|
||||
if (reading != null)
|
||||
{
|
||||
ActivityData<Windows.Devices.Sensors.ActivityType>.Instance().CurrentActivity = reading.Activity;
|
||||
}
|
||||
|
||||
// Fetch activity history for the day
|
||||
DateTime startDate = DateTime.Today.Subtract(TimeSpan.FromDays(DayOffset));
|
||||
DateTime endDate = startDate + TimeSpan.FromDays(1);
|
||||
|
||||
var history = await ActivitySensor.GetSystemHistoryAsync(startDate, TimeSpan.FromDays(1));
|
||||
|
||||
// Create a dictionary to store data
|
||||
Dictionary<Windows.Devices.Sensors.ActivityType, TimeSpan> activitySummary = new Dictionary<Windows.Devices.Sensors.ActivityType, TimeSpan>();
|
||||
|
||||
// Initialize timespan for all entries
|
||||
var activityTypes = Enum.GetValues(typeof(Windows.Devices.Sensors.ActivityType));
|
||||
foreach (var type in activityTypes)
|
||||
{
|
||||
activitySummary[(Windows.Devices.Sensors.ActivityType)type] = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
if (history.Count == 0 || history[0].Timestamp > startDate)
|
||||
{
|
||||
ActivitySensorReading firstReading = await GetActivityAtAsync(startDate);
|
||||
if (firstReading != null)
|
||||
{
|
||||
List<ActivitySensorReading> finalHistory = new List<ActivitySensorReading>(history);
|
||||
finalHistory.Insert(0, firstReading);
|
||||
history = finalHistory.AsReadOnly();
|
||||
}
|
||||
}
|
||||
|
||||
// Update the timespan for all activities in the dictionary
|
||||
if (history.Count > 0)
|
||||
{
|
||||
Windows.Devices.Sensors.ActivityType currentActivity = history[0].Activity;
|
||||
DateTime currentDate = history[0].Timestamp.DateTime;
|
||||
foreach (var item in history)
|
||||
{
|
||||
if (item.Timestamp >= startDate)
|
||||
{
|
||||
TimeSpan duration = TimeSpan.Zero;
|
||||
if (currentDate < startDate)
|
||||
{
|
||||
// If first activity of the day started already yesterday, set start time to midnight.
|
||||
currentDate = startDate;
|
||||
}
|
||||
if (item.Timestamp > endDate)
|
||||
{
|
||||
// If last activity extends over to next day, set end time to midnight.
|
||||
duration = endDate - currentDate;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
duration = item.Timestamp - currentDate;
|
||||
}
|
||||
activitySummary[currentActivity] += duration;
|
||||
}
|
||||
currentActivity = item.Activity;
|
||||
currentDate = item.Timestamp.DateTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the summary to add it to data source
|
||||
List<ActivityDuration<Windows.Devices.Sensors.ActivityType>> historyList = new List<ActivityDuration<Windows.Devices.Sensors.ActivityType>>();
|
||||
foreach (var activityType in activityTypes)
|
||||
{
|
||||
// For each entry in the summary add the type and duration to data source
|
||||
historyList.Add(new ActivityDuration<Windows.Devices.Sensors.ActivityType>((Windows.Devices.Sensors.ActivityType)activityType, activitySummary[(Windows.Devices.Sensors.ActivityType)activityType]));
|
||||
}
|
||||
|
||||
// Update the singleton instance of the data source
|
||||
ActivityData<Windows.Devices.Sensors.ActivityType>.Instance().History = historyList;
|
||||
ActivityData<Windows.Devices.Sensors.ActivityType>.Instance().Date = startDate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update the current activity that's displayed.
|
||||
/// </summary>
|
||||
/// <param name="args">Event arguments</param>
|
||||
public void UpdateCurrentActivity(object args)
|
||||
{
|
||||
ActivityData<Windows.Devices.Sensors.ActivityType>.Instance().CurrentActivity = (Windows.Devices.Sensors.ActivityType)args;
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of IActivitySensor that surfaces Activity Sensor supported by the SensorCore.
|
||||
/// instance.
|
||||
/// </summary>
|
||||
public class LumiaActivitySensor : IActivitySensor
|
||||
{
|
||||
#region Private members
|
||||
/// <summary>
|
||||
/// Physical sensor.
|
||||
/// </summary>
|
||||
public static Lumia.Sense.ActivityMonitor _activityMonitor = null;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new ResourceLoader object.
|
||||
/// </summary>
|
||||
static protected readonly ResourceLoader _resourceLoader = ResourceLoader.GetForCurrentView("Resources");
|
||||
|
||||
/// <summary>
|
||||
/// Check if running in emulator
|
||||
/// </summary>
|
||||
protected bool _runningInEmulator = false;
|
||||
|
||||
/// <summary>
|
||||
/// Reading changed handler.
|
||||
/// </summary
|
||||
public event ReadingChangedEventHandler ReadingChanged = null;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Lumia Activity Sensor constructor.
|
||||
/// </summary
|
||||
public LumiaActivitySensor()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs asynchronous Sense SDK operation and handles any exceptions
|
||||
/// </summary>
|
||||
/// <param name="action">The function delegate to execute asynchronously when one task in the tasks completes</param>
|
||||
/// <returns><c>true</c> if call was successful, <c>false</c> otherwis:)
|
||||
/// e</returns>
|
||||
private async Task<bool> CallSensorCoreApiAsync(Func<Task> action)
|
||||
{
|
||||
Exception failure = null;
|
||||
try
|
||||
{
|
||||
await action();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
failure = e;
|
||||
Debug.WriteLine("Failure:" + e.Message);
|
||||
}
|
||||
if (failure != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageDialog dialog = null;
|
||||
switch (SenseHelper.GetSenseError(failure.HResult))
|
||||
{
|
||||
case SenseError.LocationDisabled:
|
||||
{
|
||||
dialog = new MessageDialog("In order to recognize activities you need to enable location in system settings. Do you want to open settings now? If not, application will exit.", "Information");
|
||||
dialog.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(async (cmd) => await SenseHelper.LaunchLocationSettingsAsync())));
|
||||
dialog.Commands.Add(new UICommand("No", new UICommandInvokedHandler((cmd) => { Application.Current.Exit(); })));
|
||||
await dialog.ShowAsync();
|
||||
new System.Threading.ManualResetEvent(false).WaitOne(500);
|
||||
return false;
|
||||
}
|
||||
case SenseError.SenseDisabled:
|
||||
{
|
||||
dialog = new MessageDialog("In order to recognize activities you need to enable Motion data in Motion data settings. Do you want to open settings now? If not, application will exit.", "Information");
|
||||
dialog.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(async (cmd) => await SenseHelper.LaunchSenseSettingsAsync())));
|
||||
dialog.Commands.Add(new UICommand("No", new UICommandInvokedHandler((cmd) => { Application.Current.Exit(); })));
|
||||
await dialog.ShowAsync();
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
dialog = new MessageDialog("Failure: " + SenseHelper.GetSenseError(failure.HResult), "");
|
||||
await dialog.ShowAsync();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Debug.WriteLine("Failed to handle failure. Message:" + ex.Message);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get singleton instance of ActivityData<Lumia.Sense.Activity>.
|
||||
/// </summary>
|
||||
public object GetActivityDataInstance()
|
||||
{
|
||||
return ActivityData<Lumia.Sense.Activity>.Instance();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initialize sensor core.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task/returns>
|
||||
public async Task InitializeSensorAsync()
|
||||
{
|
||||
// Make sure all necessary settings are enabled
|
||||
await ValidateSettingsAsync();
|
||||
|
||||
if (_runningInEmulator)
|
||||
{
|
||||
// await CallSensorCoreApiAsync( async () => { _activityMonitor = await ActivityMonitorSimulator.GetDefaultAsync(); } );
|
||||
}
|
||||
else
|
||||
{
|
||||
// Get the activity monitor instance
|
||||
await CallSensorCoreApiAsync(async () =>
|
||||
{
|
||||
_activityMonitor = await ActivityMonitor.GetDefaultAsync();
|
||||
});
|
||||
}
|
||||
if (_activityMonitor == null)
|
||||
{
|
||||
// Nothing to do if we cannot use the API
|
||||
Application.Current.Exit();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Validate if settings have been configured correctly to run SensorCore.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task/returns>
|
||||
public static async Task ValidateSettingsAsync()
|
||||
{
|
||||
if (!(await ActivityMonitor.IsSupportedAsync()))
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog(_resourceLoader.GetString("FeatureNotSupported/Message"), _resourceLoader.GetString("FeatureNotSupported/Title"));
|
||||
await dlg.ShowAsync();
|
||||
Application.Current.Exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint apiSet = await SenseHelper.GetSupportedApiSetAsync();
|
||||
MotionDataSettings settings = await SenseHelper.GetSettingsAsync();
|
||||
if (settings.Version < 2)
|
||||
{
|
||||
// Device which has old Motion data settings which requires system location and Motion data be enabled in order to access
|
||||
// ActivityMonitor.
|
||||
if (!settings.LocationEnabled)
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog("In order to recognize activities you need to enable location in system settings. Do you want to open settings now? If not, application will exit.", "Information");
|
||||
dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(async (cmd) => await SenseHelper.LaunchLocationSettingsAsync())));
|
||||
dlg.Commands.Add(new UICommand("No", new UICommandInvokedHandler((cmd) => { Application.Current.Exit(); })));
|
||||
await dlg.ShowAsync();
|
||||
}
|
||||
else if (!settings.PlacesVisited)
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog("In order to recognize activities you need to enable Motion data in Motion data settings. Do you want to open settings now? If not, application will exit.", "Information");
|
||||
dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(async (cmd) => await SenseHelper.LaunchSenseSettingsAsync())));
|
||||
dlg.Commands.Add(new UICommand("No", new UICommandInvokedHandler((cmd) => { Application.Current.Exit(); })));
|
||||
await dlg.ShowAsync();
|
||||
}
|
||||
}
|
||||
else if (apiSet >= 3)
|
||||
{
|
||||
if (!settings.LocationEnabled)
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog("In order to recognize biking you need to enable location in system settings. Do you want to open settings now?", "Helpful tip");
|
||||
dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(async (cmd) => await SenseHelper.LaunchLocationSettingsAsync())));
|
||||
dlg.Commands.Add(new UICommand("No"));
|
||||
await dlg.ShowAsync();
|
||||
}
|
||||
else if (settings.DataQuality == DataCollectionQuality.Basic)
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog("In order to recognize biking you need to enable detailed data collection in Motion data settings. Do you want to open settings now?", "Helpful tip");
|
||||
dlg.Commands.Add(new UICommand("Yes", new UICommandInvokedHandler(async (cmd) => await SenseHelper.LaunchSenseSettingsAsync())));
|
||||
dlg.Commands.Add(new UICommand("No"));
|
||||
await dlg.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Activate Sensor Instance.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task/returns>
|
||||
public async Task ActivateAsync()
|
||||
{
|
||||
if (_activityMonitor == null)
|
||||
{
|
||||
await InitializeSensorAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
_activityMonitor.Enabled = true;
|
||||
_activityMonitor.ReadingChanged += activityMonitor_ReadingChanged;
|
||||
|
||||
await CallSensorCoreApiAsync(async () =>
|
||||
{
|
||||
await _activityMonitor.ActivateAsync();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deactivate sensor instance.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task/returns>
|
||||
public async Task DeactivateAsync()
|
||||
{
|
||||
if (_activityMonitor != null)
|
||||
{
|
||||
_activityMonitor.Enabled = false;
|
||||
_activityMonitor.ReadingChanged -= activityMonitor_ReadingChanged;
|
||||
await CallSensorCoreApiAsync(async () =>
|
||||
{
|
||||
await _activityMonitor.DeactivateAsync();
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when activity changes.
|
||||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="args">Event arguments</param>
|
||||
private async void activityMonitor_ReadingChanged(IActivityMonitor sender, ActivityMonitorReading args)
|
||||
{
|
||||
if (ReadingChanged != null)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
ReadingChanged(this, args.Mode);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update Summary.
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task/returns>
|
||||
/// <param name="DayOffset">Day Offset</param>
|
||||
public async Task UpdateSummaryAsync(uint DayOffset)
|
||||
{
|
||||
// Read current activity
|
||||
ActivityMonitorReading reading = null;
|
||||
|
||||
await CallSensorCoreApiAsync(async () =>
|
||||
{
|
||||
reading = await _activityMonitor.GetCurrentReadingAsync();
|
||||
});
|
||||
|
||||
if (reading != null)
|
||||
{
|
||||
ActivityData<Lumia.Sense.Activity>.Instance().CurrentActivity = reading.Mode;
|
||||
}
|
||||
|
||||
// Fetch activity history for the day
|
||||
DateTime startDate = DateTime.Today.Subtract(TimeSpan.FromDays(DayOffset));
|
||||
DateTime endDate = startDate + TimeSpan.FromDays(1);
|
||||
IList<ActivityMonitorReading> history = null;
|
||||
|
||||
await CallSensorCoreApiAsync(async () =>
|
||||
{
|
||||
history = await _activityMonitor.GetActivityHistoryAsync(startDate, TimeSpan.FromDays(1));
|
||||
});
|
||||
|
||||
// Create a dictionary to store data
|
||||
Dictionary<Activity, TimeSpan> activitySummary = new Dictionary<Activity, TimeSpan>();
|
||||
|
||||
// Initialize timespan for all entries
|
||||
var activityTypes = Enum.GetValues(typeof(Activity));
|
||||
foreach (var type in activityTypes)
|
||||
{
|
||||
activitySummary[(Activity)type] = TimeSpan.Zero;
|
||||
}
|
||||
|
||||
// Update the timespan for all activities in the dictionary
|
||||
if (history.Count > 0)
|
||||
{
|
||||
Activity currentActivity = history[0].Mode;
|
||||
DateTime currentDate = history[0].Timestamp.DateTime;
|
||||
foreach (var item in history)
|
||||
{
|
||||
if (item.Timestamp >= startDate)
|
||||
{
|
||||
TimeSpan duration = TimeSpan.Zero;
|
||||
if (currentDate < startDate)
|
||||
{
|
||||
// If first activity of the day started already yesterday, set start time to midnight.
|
||||
currentDate = startDate;
|
||||
}
|
||||
if (item.Timestamp > endDate)
|
||||
{
|
||||
// If last activity extends over to next day, set end time to midnight.
|
||||
duration = endDate - currentDate;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
duration = item.Timestamp - currentDate;
|
||||
}
|
||||
activitySummary[currentActivity] += duration;
|
||||
}
|
||||
currentActivity = item.Mode;
|
||||
currentDate = item.Timestamp.DateTime;
|
||||
}
|
||||
}
|
||||
|
||||
// Prepare the summary to add it to data source
|
||||
List<ActivityDuration<Lumia.Sense.Activity>> historyList = new List<ActivityDuration<Lumia.Sense.Activity>>();
|
||||
foreach (var activityType in activityTypes)
|
||||
{
|
||||
// For each entry in the summary add the type and duration to data source
|
||||
historyList.Add(new ActivityDuration<Lumia.Sense.Activity>((Activity)activityType, activitySummary[(Activity)activityType]));
|
||||
}
|
||||
|
||||
// Update the singleton instance of the data source
|
||||
ActivityData<Lumia.Sense.Activity>.Instance().History = historyList;
|
||||
ActivityData<Lumia.Sense.Activity>.Instance().Date = startDate;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Update Current Activity that's cached.
|
||||
/// </summary>
|
||||
/// <param name="args">Current acitivity value</param>
|
||||
public void UpdateCurrentActivity(object args)
|
||||
{
|
||||
ActivityData<Lumia.Sense.Activity>.Instance().CurrentActivity = (Lumia.Sense.Activity)args;
|
||||
}
|
||||
};
|
||||
}
|
|
@ -1,4 +1,16 @@
|
|||
<Application
|
||||
<!--
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
-->
|
||||
<Application
|
||||
x:Class="ActivitiesExample.App"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
|
|
|
@ -41,13 +41,6 @@ namespace ActivitiesExample
|
|||
/// </summary>
|
||||
private TransitionCollection transitions;
|
||||
|
||||
/// <summary>
|
||||
/// This event wraps HardwareButtons.BackPressed to allow other pages to override
|
||||
/// the default behavior by subscribing to this event and potentially
|
||||
/// handling the back button press a different way (e.g. dismissing dialogs).
|
||||
/// </summary>
|
||||
public event EventHandler<BackPressedEventArgs> BackPressed;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes the singleton application object. This is the first line of authored code
|
||||
/// executed, and as such is the logical equivalent of main() or WinMain().
|
||||
|
@ -56,7 +49,6 @@ namespace ActivitiesExample
|
|||
{
|
||||
this.InitializeComponent();
|
||||
this.Suspending += OnSuspending;
|
||||
HardwareButtons.BackPressed += this.HardwareButtons_BackPressed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -124,19 +116,14 @@ namespace ActivitiesExample
|
|||
/// </summary>
|
||||
/// <param name="sender">The source of the event. <see cref="HardwareButtons"/></param>
|
||||
/// <param name="e">Details about the back button press.</param>
|
||||
private void HardwareButtons_BackPressed( object sender, BackPressedEventArgs e )
|
||||
private void HardwareButtons_BackPressed( object sender, Windows.UI.Core.BackRequestedEventArgs e )
|
||||
{
|
||||
Frame frame = Window.Current.Content as Frame;
|
||||
if( frame == null )
|
||||
{
|
||||
return;
|
||||
}
|
||||
var handler = this.BackPressed;
|
||||
if( handler != null )
|
||||
{
|
||||
handler( sender, e );
|
||||
}
|
||||
if( frame.CanGoBack && !e.Handled )
|
||||
if( frame.CanGoBack)
|
||||
{
|
||||
frame.GoBack();
|
||||
e.Handled = true;
|
||||
|
@ -153,6 +140,7 @@ namespace ActivitiesExample
|
|||
var rootFrame = sender as Frame;
|
||||
rootFrame.ContentTransitions = this.transitions ?? new TransitionCollection() { new NavigationThemeTransition() };
|
||||
rootFrame.Navigated -= this.RootFrame_FirstNavigated;
|
||||
Windows.UI.Core.SystemNavigationManager.GetForCurrentView().BackRequested += HardwareButtons_BackPressed;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -54,30 +54,30 @@ namespace ActivitiesExample.Converters
|
|||
public object Convert( object value, Type targetType, object parameter, string language )
|
||||
{
|
||||
string hint = "";
|
||||
switch( (Activity)value )
|
||||
switch(value.ToString().ToLower())
|
||||
{
|
||||
case Activity.Moving:
|
||||
case "moving":
|
||||
hint = this._resourceLoader.GetString( "Hint/Moving" );
|
||||
break;
|
||||
case Activity.Idle:
|
||||
case "idle":
|
||||
hint = this._resourceLoader.GetString( "Hint/Idle" );
|
||||
break;
|
||||
case Activity.Stationary:
|
||||
case "stationary":
|
||||
hint = this._resourceLoader.GetString( "Hint/Stationary" );
|
||||
break;
|
||||
case Activity.Walking:
|
||||
case "walking":
|
||||
hint = this._resourceLoader.GetString( "Hint/Walking" );
|
||||
break;
|
||||
case Activity.Running:
|
||||
case "running":
|
||||
hint = this._resourceLoader.GetString( "Hint/Running" );
|
||||
break;
|
||||
case Activity.Biking:
|
||||
case "biking":
|
||||
hint = this._resourceLoader.GetString( "Hint/Biking" );
|
||||
break;
|
||||
case Activity.MovingInVehicle:
|
||||
case "invehicle":
|
||||
hint = this._resourceLoader.GetString( "Hint/MovingInVehicle" );
|
||||
break;
|
||||
case Activity.Unknown:
|
||||
case "unknown":
|
||||
hint = this._resourceLoader.GetString( "Hint/Unknown" );
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -20,6 +20,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using Windows.UI.Xaml.Data;
|
||||
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
/*
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2015 Microsoft
|
||||
|
||||
|
@ -20,7 +20,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
using Lumia.Sense;
|
||||
using Lumia.Sense;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
@ -32,18 +32,18 @@ namespace ActivitiesExample.Data
|
|||
/// <summary>
|
||||
/// Data class for storing activity data for displaying in UI
|
||||
/// </summary>
|
||||
public class ActivityData : INotifyPropertyChanged
|
||||
public class ActivityData<T> : INotifyPropertyChanged
|
||||
{
|
||||
#region Private members
|
||||
/// <summary>
|
||||
/// List of activities and durations
|
||||
/// </summary>
|
||||
private List<ActivityDuration> _listData = null;
|
||||
private List<ActivityDuration<T>> _listData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Current activity
|
||||
/// </summary>
|
||||
private Activity _currentActivity = Activity.Idle;
|
||||
private T _currentActivity;
|
||||
|
||||
/// <summary>
|
||||
/// Date of the data set
|
||||
|
@ -53,7 +53,7 @@ namespace ActivitiesExample.Data
|
|||
/// <summary>
|
||||
/// Singleton instance
|
||||
/// </summary>
|
||||
private static ActivityData _selfData;
|
||||
private static ActivityData<T> _selfData;
|
||||
#endregion
|
||||
|
||||
#region Events
|
||||
|
@ -82,18 +82,18 @@ namespace ActivitiesExample.Data
|
|||
/// </summary>
|
||||
private ActivityData()
|
||||
{
|
||||
_listData = new List<ActivityDuration>();
|
||||
_listData = new List<ActivityDuration<T>>();
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Create new instance of the class
|
||||
/// </summary>
|
||||
/// <returns>Data instance</returns>
|
||||
static public ActivityData Instance()
|
||||
static public ActivityData<T> Instance()
|
||||
{
|
||||
if( _selfData == null )
|
||||
{
|
||||
_selfData = new ActivityData();
|
||||
_selfData = new ActivityData<T>();
|
||||
}
|
||||
return _selfData;
|
||||
}
|
||||
|
@ -117,7 +117,7 @@ namespace ActivitiesExample.Data
|
|||
/// <summary>
|
||||
/// Current activity
|
||||
/// </summary>
|
||||
public Activity CurrentActivity
|
||||
public T CurrentActivity
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -133,7 +133,7 @@ namespace ActivitiesExample.Data
|
|||
/// <summary>
|
||||
/// Summary of activities for a day
|
||||
/// </summary>
|
||||
public List<ActivityDuration> History
|
||||
public List<ActivityDuration<T>> History
|
||||
{
|
||||
get
|
||||
{
|
||||
|
@ -150,14 +150,14 @@ namespace ActivitiesExample.Data
|
|||
/// <summary>
|
||||
/// Class containing activity type and duration
|
||||
/// </summary>
|
||||
public class ActivityDuration
|
||||
public class ActivityDuration<T>
|
||||
{
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
/// </summary>
|
||||
/// <param name="type">Activity type</param>
|
||||
/// <param name="duration">Activity duration</param>
|
||||
public ActivityDuration( Activity type, TimeSpan duration )
|
||||
public ActivityDuration( T type, TimeSpan duration )
|
||||
{
|
||||
// Split activity string by capital letter
|
||||
Duration = duration;
|
||||
|
@ -178,7 +178,7 @@ namespace ActivitiesExample.Data
|
|||
/// <summary>
|
||||
/// Activity type
|
||||
/// </summary>
|
||||
public Activity Type { get; set; }
|
||||
public T Type { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Activity duration
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using Lumia.Sense;
|
||||
/*
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
Copyright (c) 2015 Microsoft
|
||||
|
||||
|
@ -21,6 +20,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
using Lumia.Sense;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
|
@ -31,18 +31,18 @@ namespace ActivitiesExample.Data
|
|||
/// <summary>
|
||||
/// Data class for design mode
|
||||
/// </summary>
|
||||
public class ActivityDesignData : INotifyPropertyChanged
|
||||
public class ActivityDesignData<T> : INotifyPropertyChanged
|
||||
{
|
||||
#region Private members
|
||||
/// <summary>
|
||||
/// List of activities and durations
|
||||
/// </summary>
|
||||
private List<ActivityDuration> _listData = null;
|
||||
private List<ActivityDuration<T>> _listData = null;
|
||||
|
||||
/// <summary>
|
||||
/// Singleton instance
|
||||
/// </summary>
|
||||
private static ActivityDesignData _selfData;
|
||||
private static ActivityDesignData<T> _selfData;
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
|
@ -50,6 +50,11 @@ namespace ActivitiesExample.Data
|
|||
/// </summary>
|
||||
public event PropertyChangedEventHandler PropertyChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Current activity
|
||||
/// </summary>
|
||||
private T _currentActivity;
|
||||
|
||||
/// <summary>
|
||||
/// This method is called by the Set accessor of each property.
|
||||
/// The CallerMemberName attribute that is applied to the optional propertyName
|
||||
|
@ -69,29 +74,18 @@ namespace ActivitiesExample.Data
|
|||
/// </summary>
|
||||
public ActivityDesignData()
|
||||
{
|
||||
_listData = new List<ActivityDuration>();
|
||||
if( Windows.ApplicationModel.DesignMode.DesignModeEnabled )
|
||||
{
|
||||
_listData.Add( new ActivityDuration( Activity.Idle, TimeSpan.FromHours( 13 ) ) );
|
||||
_listData.Add( new ActivityDuration( Activity.Moving, TimeSpan.FromHours( 4 ) ) );
|
||||
_listData.Add( new ActivityDuration( Activity.Stationary, TimeSpan.FromHours( 1 ) ) );
|
||||
_listData.Add( new ActivityDuration( Activity.Walking, TimeSpan.FromHours( 2 ) ) );
|
||||
_listData.Add( new ActivityDuration( Activity.Running, TimeSpan.FromHours( 3 ) ) );
|
||||
_listData.Add( new ActivityDuration( Activity.Biking, TimeSpan.FromHours( 5 ) ) );
|
||||
_listData.Add( new ActivityDuration( Activity.MovingInVehicle, TimeSpan.FromHours( 1 ) ) );
|
||||
_listData.Add( new ActivityDuration( Activity.Unknown, TimeSpan.FromHours( 1 ) ) );
|
||||
}
|
||||
_listData = new List<ActivityDuration<T>>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create new instance of the class
|
||||
/// </summary>
|
||||
/// <returns>Design data instance</returns>
|
||||
static public ActivityDesignData Instance()
|
||||
static public ActivityDesignData<T> Instance()
|
||||
{
|
||||
if( _selfData == null )
|
||||
{
|
||||
_selfData = new ActivityDesignData();
|
||||
_selfData = new ActivityDesignData<T>();
|
||||
}
|
||||
return _selfData;
|
||||
}
|
||||
|
@ -99,18 +93,23 @@ namespace ActivitiesExample.Data
|
|||
/// <summary>
|
||||
/// Get the current activity
|
||||
/// </summary>
|
||||
public Activity CurrentActivity
|
||||
public T CurrentActivity
|
||||
{
|
||||
get
|
||||
{
|
||||
return Activity.Walking;
|
||||
return _currentActivity;
|
||||
}
|
||||
set
|
||||
{
|
||||
_currentActivity = value;
|
||||
NotifyPropertyChanged("CurrentActivity");
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the list of activities and durations
|
||||
/// </summary>
|
||||
public List<ActivityDuration> History
|
||||
public List<ActivityDuration<T>> History
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
|
@ -1,4 +1,16 @@
|
|||
<Page
|
||||
<!--
|
||||
//*********************************************************
|
||||
//
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
// This code is licensed under the MIT License (MIT).
|
||||
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
|
||||
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
|
||||
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
|
||||
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
|
||||
//
|
||||
//*********************************************************
|
||||
-->
|
||||
<Page
|
||||
x:Class="ActivitiesExample.MainPage"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
|
@ -38,14 +50,14 @@
|
|||
</Grid.RowDefinitions>
|
||||
<!-- current activity text -->
|
||||
<StackPanel Grid.Row="0" Margin="24,14,0,0" VerticalAlignment="Center" HorizontalAlignment="Left">
|
||||
<TextBlock x:Uid="CurrentActivityHeader" Text="_Current activity:" FontSize="{StaticResource TextStyleMediumFontSize}" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding Path=CurrentActivity, Mode=OneWay}" HorizontalAlignment="Left" FontSize="{StaticResource TextStyleExtraLargePlusFontSize}" Margin="12,0,0,0" VerticalAlignment="Center" />
|
||||
<TextBlock x:Uid="CurrentActivityHeader" Text="_Current activity:" FontSize="16" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding Path=CurrentActivity, Mode=OneWay}" HorizontalAlignment="Left" FontSize="29.86" Margin="12,0,0,0" VerticalAlignment="Center" />
|
||||
</StackPanel>
|
||||
<!-- current activity icon -->
|
||||
<Image Source="{Binding CurrentActivity, Converter={StaticResource ActivityToIcon}}" Grid.Row="2" Height="300" Width="300" Opacity="0.3"/>
|
||||
<!-- List of activities -->
|
||||
<TextBlock Text="{Binding Path=Date, Converter={StaticResource ResourceKey=DateToUiString}}" Grid.Row="1" Margin="24,0,0,6" FontSize="{StaticResource TextStyleMediumFontSize}"/>
|
||||
<ListView x:Name="ActivityListView" Grid.Row="2" Margin="24,0" ItemsSource="{Binding Path=History, Mode=OneWay}" Background="#3FFFFFFF" SelectionMode="None" MinHeight="310">
|
||||
<TextBlock Text="{Binding Path=Date, Converter={StaticResource ResourceKey=DateToUiString}}" Grid.Row="1" Margin="24,0,0,6" FontSize="16"/>
|
||||
<ListView x:Name="ActivityListView" Grid.Row="2" Margin="24,0" ItemsSource="{Binding Path=History, Mode=OneWay}" Background="#3FFFFFFF" SelectionMode="None">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<Grid Margin="0" Width="{Binding ActualWidth, ElementName=ActivityListView, Mode=OneWay}">
|
||||
|
@ -62,11 +74,11 @@
|
|||
</Grid.ColumnDefinitions>
|
||||
<!-- Activity name and durations -->
|
||||
<StackPanel Orientation="Horizontal" Grid.Row="1" Margin="12,0,0,0" >
|
||||
<TextBlock Text="{Binding Path=Name}" FontSize="{StaticResource TextStyleMediumFontSize}" Foreground="White" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding Path=Duration, Converter={StaticResource ResourceKey=TimeToString}}" FontSize="{StaticResource TextStyleMediumFontSize}" Foreground="White" Margin="12,0,0,0" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding Path=Name}" FontSize="16" Foreground="White" VerticalAlignment="Center"/>
|
||||
<TextBlock Text="{Binding Path=Duration, Converter={StaticResource ResourceKey=TimeToString}}" FontSize="16" Foreground="White" Margin="12,0,0,0" VerticalAlignment="Center"/>
|
||||
</StackPanel>
|
||||
<!-- Activity description -->
|
||||
<TextBlock Grid.Row="2" Text="{Binding Path=Type, Converter={StaticResource ResourceKey=ActivityToHint}}" FontSize="{StaticResource TextStyleSmallFontSize}" Foreground="White" VerticalAlignment="Center" Margin="12,0,0,0" TextWrapping="Wrap" />
|
||||
<TextBlock Grid.Row="2" Text="{Binding Path=Type, Converter={StaticResource ResourceKey=ActivityToHint}}" FontSize="10.66" Foreground="White" VerticalAlignment="Center" Margin="12,0,0,0" TextWrapping="Wrap" />
|
||||
<!-- Activity duration as a rectangle -->
|
||||
<Rectangle Grid.Row="3" Margin="0,6,0,0" Grid.Column="0" Width="{Binding Path=Duration, Converter={StaticResource ResourceKey=TimeToWidth}}" Height="6" Fill="White" VerticalAlignment="Top" HorizontalAlignment="Left"/>
|
||||
<!-- Ellipsis added to the end of rectangle if duration > 12h -->
|
||||
|
@ -87,16 +99,16 @@
|
|||
<ColumnDefinition Width="3*"/>
|
||||
<ColumnDefinition Width="2*"/>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="00h" Grid.Column="0" HorizontalAlignment="Left" FontSize="{StaticResource TextStyleMediumFontSize}"/>
|
||||
<TextBlock Text="03h" Grid.Column="1" HorizontalAlignment="Center" FontSize="{StaticResource TextStyleMediumFontSize}"/>
|
||||
<TextBlock Text="06h" Grid.Column="2" HorizontalAlignment="Center" FontSize="{StaticResource TextStyleMediumFontSize}"/>
|
||||
<TextBlock Text="09h" Grid.Column="3" HorizontalAlignment="Center" FontSize="{StaticResource TextStyleMediumFontSize}"/>
|
||||
<TextBlock Text="12h" Grid.Column="4" HorizontalAlignment="Right" FontSize="{StaticResource TextStyleMediumFontSize}"/>
|
||||
<TextBlock Text="00h" Grid.Column="0" HorizontalAlignment="Left" FontSize="16"/>
|
||||
<TextBlock Text="03h" Grid.Column="1" HorizontalAlignment="Center" FontSize="16"/>
|
||||
<TextBlock Text="06h" Grid.Column="2" HorizontalAlignment="Center" FontSize="16"/>
|
||||
<TextBlock Text="09h" Grid.Column="3" HorizontalAlignment="Center" FontSize="16"/>
|
||||
<TextBlock Text="12h" Grid.Column="4" HorizontalAlignment="Right" FontSize="16"/>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Page.BottomAppBar>
|
||||
<CommandBar Opacity="0.5">
|
||||
<CommandBar x:Name="cmdBar" Opacity="0.5" Opening="CommandBar_Opened" Closing="CommandBar_Closed">
|
||||
<AppBarButton x:Uid="PrevButton" x:Name="prevButton" Label="_previous" IsEnabled="True" Click="PrevButton_Click" >
|
||||
<AppBarButton.Icon>
|
||||
<BitmapIcon UriSource="/Assets/back.png"/>
|
||||
|
|
|
@ -20,19 +20,15 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
using Lumia.Sense;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Windows.ApplicationModel.Resources;
|
||||
using Windows.UI.Xaml;
|
||||
using Windows.UI.Xaml.Controls;
|
||||
using Windows.UI.Xaml.Navigation;
|
||||
using Windows.UI.Core;
|
||||
using Windows.UI.Popups;
|
||||
using System.Threading.Tasks;
|
||||
using Lumia.Sense;
|
||||
using System.Diagnostics;
|
||||
using ActivitiesExample.Data;
|
||||
using Windows.Security.ExchangeActiveSyncProvisioning;
|
||||
using Windows.ApplicationModel.Resources;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace ActivitiesExample
|
||||
{
|
||||
|
@ -43,14 +39,9 @@ namespace ActivitiesExample
|
|||
{
|
||||
#region Private members
|
||||
/// <summary>
|
||||
/// Activity monitor instance
|
||||
/// </summary>
|
||||
private IActivityMonitor _activityMonitor = null;
|
||||
|
||||
/// <summary>
|
||||
/// Check if running in emulator
|
||||
/// </summary>
|
||||
private bool _runningInEmulator = false;
|
||||
/// Activity Sensor instance
|
||||
/// </summary>
|
||||
private IActivitySensor _sensor = null;
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new ResourceLoader object
|
||||
|
@ -70,190 +61,40 @@ namespace ActivitiesExample
|
|||
{
|
||||
InitializeComponent();
|
||||
this.NavigationCacheMode = NavigationCacheMode.Required;
|
||||
DataContext = ActivityData.Instance();
|
||||
|
||||
// Using this method to detect if the application runs in the emulator or on a real device. Later the *Simulator API is used to read fake sense data on emulator.
|
||||
// In production code you do not need this and in fact you should ensure that you do not include the Lumia.Sense.Test reference in your project.
|
||||
EasClientDeviceInformation x = new EasClientDeviceInformation();
|
||||
if( x.SystemProductName.StartsWith( "Virtual" ) )
|
||||
{
|
||||
_runningInEmulator = true;
|
||||
}
|
||||
|
||||
Window.Current.VisibilityChanged += async ( sender, args ) =>
|
||||
{
|
||||
await CallSensorCoreApiAsync( async () =>
|
||||
if( !args.Visible )
|
||||
{
|
||||
if( !args.Visible )
|
||||
// Application put to background, deactivate sensor
|
||||
if(_sensor != null)
|
||||
{
|
||||
// Application put to background, deactivate sensor and unregister change observer
|
||||
if( _activityMonitor != null )
|
||||
{
|
||||
_activityMonitor.Enabled = true;
|
||||
_activityMonitor.ReadingChanged -= activityMonitor_ReadingChanged;
|
||||
await _activityMonitor.DeactivateAsync();
|
||||
}
|
||||
await _sensor.DeactivateAsync();
|
||||
}
|
||||
else
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create sensor instance if already not created
|
||||
if (_sensor == null)
|
||||
{
|
||||
// Make sure all necessary settings are enabled in order to run SensorCore
|
||||
await ValidateSettingsAsync();
|
||||
// Make sure sensor is activated
|
||||
if( _activityMonitor == null )
|
||||
{
|
||||
await InitializeSensorAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
await _activityMonitor.ActivateAsync();
|
||||
}
|
||||
_sensor = await ActivitySensorFactory.GetDefaultAsync();
|
||||
|
||||
// Enable change observer
|
||||
_activityMonitor.ReadingChanged += activityMonitor_ReadingChanged;
|
||||
_activityMonitor.Enabled = true;
|
||||
|
||||
// Update screen
|
||||
await UpdateSummaryAsync();
|
||||
// Bind data
|
||||
DataContext = _sensor.GetActivityDataInstance();
|
||||
}
|
||||
} );
|
||||
|
||||
// Register delegate to get reading changes
|
||||
_sensor.ReadingChanged += activity_ReadingChanged;
|
||||
|
||||
// Activate the sensor
|
||||
await _sensor.ActivateAsync();
|
||||
|
||||
// Update screen
|
||||
await UpdateSummaryAsync();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes activity monitor sensor
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task</returns>
|
||||
private async Task InitializeSensorAsync()
|
||||
{
|
||||
if( _runningInEmulator )
|
||||
{
|
||||
// await CallSensorCoreApiAsync( async () => { _activityMonitor = await ActivityMonitorSimulator.GetDefaultAsync(); } );
|
||||
}
|
||||
else
|
||||
{
|
||||
await CallSensorCoreApiAsync( async () => { _activityMonitor = await ActivityMonitor.GetDefaultAsync(); } );
|
||||
}
|
||||
if( _activityMonitor == null )
|
||||
{
|
||||
// Nothing to do if we cannot use the API
|
||||
Application.Current.Exit();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Makes sure necessary settings are enabled in order to use SensorCore
|
||||
/// </summary>
|
||||
/// <returns>Asynchronous task</returns>
|
||||
private async Task ValidateSettingsAsync()
|
||||
{
|
||||
if( !( await ActivityMonitor.IsSupportedAsync() ) )
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog( this._resourceLoader.GetString( "FeatureNotSupported/Message" ), this._resourceLoader.GetString( "FeatureNotSupported/Title" ) );
|
||||
await dlg.ShowAsync();
|
||||
Application.Current.Exit();
|
||||
}
|
||||
else
|
||||
{
|
||||
uint apiSet = await SenseHelper.GetSupportedApiSetAsync();
|
||||
MotionDataSettings settings = await SenseHelper.GetSettingsAsync();
|
||||
if( settings.Version < 2 )
|
||||
{
|
||||
// Device which has old Motion data settings which requires system location and Motion data be enabled in order to access
|
||||
// ActivityMonitor.
|
||||
if( !settings.LocationEnabled )
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog( "In order to recognize activities you need to enable location in system settings. Do you want to open settings now? If not, application will exit.", "Information" );
|
||||
dlg.Commands.Add( new UICommand( "Yes", new UICommandInvokedHandler( async ( cmd ) => await SenseHelper.LaunchLocationSettingsAsync() ) ) );
|
||||
dlg.Commands.Add( new UICommand( "No", new UICommandInvokedHandler( ( cmd ) => { Application.Current.Exit(); } ) ) );
|
||||
await dlg.ShowAsync();
|
||||
}
|
||||
else if( !settings.PlacesVisited )
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog( "In order to recognize activities you need to enable Motion data in Motion data settings. Do you want to open settings now? If not, application will exit.", "Information" );
|
||||
dlg.Commands.Add( new UICommand( "Yes", new UICommandInvokedHandler( async ( cmd ) => await SenseHelper.LaunchSenseSettingsAsync() ) ) );
|
||||
dlg.Commands.Add( new UICommand( "No", new UICommandInvokedHandler( ( cmd ) => { Application.Current.Exit(); } ) ) );
|
||||
await dlg.ShowAsync();
|
||||
}
|
||||
}
|
||||
else if( apiSet >= 3 )
|
||||
{
|
||||
if( !settings.LocationEnabled )
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog( "In order to recognize biking you need to enable location in system settings. Do you want to open settings now?", "Helpful tip" );
|
||||
dlg.Commands.Add( new UICommand( "Yes", new UICommandInvokedHandler( async ( cmd ) => await SenseHelper.LaunchLocationSettingsAsync() ) ) );
|
||||
dlg.Commands.Add( new UICommand( "No" ) );
|
||||
await dlg.ShowAsync();
|
||||
}
|
||||
else if( settings.DataQuality == DataCollectionQuality.Basic )
|
||||
{
|
||||
MessageDialog dlg = new MessageDialog( "In order to recognize biking you need to enable detailed data collection in Motion data settings. Do you want to open settings now?", "Helpful tip" );
|
||||
dlg.Commands.Add( new UICommand( "Yes", new UICommandInvokedHandler( async ( cmd ) => await SenseHelper.LaunchSenseSettingsAsync() ) ) );
|
||||
dlg.Commands.Add( new UICommand( "No" ) );
|
||||
await dlg.ShowAsync();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Performs asynchronous Sense SDK operation and handles any exceptions
|
||||
/// </summary>
|
||||
/// <param name="action">The function delegate to execute asynchronously when one task in the tasks completes</param>
|
||||
/// <returns><c>true</c> if call was successful, <c>false</c> otherwise</returns>
|
||||
private async Task<bool> CallSensorCoreApiAsync( Func<Task> action )
|
||||
{
|
||||
Exception failure = null;
|
||||
try
|
||||
{
|
||||
await action();
|
||||
}
|
||||
catch( Exception e )
|
||||
{
|
||||
failure = e;
|
||||
Debug.WriteLine( "Failure:" + e.Message );
|
||||
}
|
||||
if( failure != null )
|
||||
{
|
||||
try
|
||||
{
|
||||
MessageDialog dialog = null;
|
||||
switch( SenseHelper.GetSenseError( failure.HResult ) )
|
||||
{
|
||||
case SenseError.LocationDisabled:
|
||||
{
|
||||
dialog = new MessageDialog( "In order to recognize activities you need to enable location in system settings. Do you want to open settings now? If not, application will exit.", "Information" );
|
||||
dialog.Commands.Add( new UICommand( "Yes", new UICommandInvokedHandler( async ( cmd ) => await SenseHelper.LaunchLocationSettingsAsync() ) ) );
|
||||
dialog.Commands.Add( new UICommand( "No", new UICommandInvokedHandler( ( cmd ) => { Application.Current.Exit(); } ) ) );
|
||||
await dialog.ShowAsync();
|
||||
new System.Threading.ManualResetEvent( false ).WaitOne( 500 );
|
||||
return false;
|
||||
}
|
||||
case SenseError.SenseDisabled:
|
||||
{
|
||||
dialog = new MessageDialog( "In order to recognize activities you need to enable Motion data in Motion data settings. Do you want to open settings now? If not, application will exit.", "Information" );
|
||||
dialog.Commands.Add( new UICommand( "Yes", new UICommandInvokedHandler( async ( cmd ) => await SenseHelper.LaunchSenseSettingsAsync() ) ) );
|
||||
dialog.Commands.Add( new UICommand( "No", new UICommandInvokedHandler( ( cmd ) => { Application.Current.Exit(); } ) ) );
|
||||
await dialog.ShowAsync();
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
dialog = new MessageDialog( "Failure: " + SenseHelper.GetSenseError( failure.HResult ), "" );
|
||||
await dialog.ShowAsync();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
catch( Exception ex )
|
||||
{
|
||||
Debug.WriteLine( "Failed to handle failure. Message:" + ex.Message );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Called when navigating to this page
|
||||
/// </summary>
|
||||
|
@ -262,21 +103,12 @@ namespace ActivitiesExample
|
|||
{
|
||||
if( e.NavigationMode == NavigationMode.Back )
|
||||
{
|
||||
// Make sure all necessary settings are enabled in order to run SensorCore
|
||||
await ValidateSettingsAsync();
|
||||
// Make sure sensor is activated
|
||||
if( _activityMonitor == null )
|
||||
{
|
||||
await InitializeSensorAsync();
|
||||
}
|
||||
else
|
||||
{
|
||||
await _activityMonitor.ActivateAsync();
|
||||
}
|
||||
// Register for reading change notifications if we have already not registered.
|
||||
_sensor.ReadingChanged += activity_ReadingChanged;
|
||||
|
||||
// Activate the sensor
|
||||
await _sensor.ActivateAsync();
|
||||
|
||||
// Register change observer
|
||||
_activityMonitor.ReadingChanged += activityMonitor_ReadingChanged;
|
||||
_activityMonitor.Enabled = true;
|
||||
// Update screen
|
||||
await UpdateSummaryAsync();
|
||||
}
|
||||
|
@ -288,11 +120,12 @@ namespace ActivitiesExample
|
|||
/// <param name="e">Event arguments</param>
|
||||
protected async override void OnNavigatedFrom( NavigationEventArgs e )
|
||||
{
|
||||
if( _activityMonitor != null )
|
||||
if(_sensor != null )
|
||||
{
|
||||
_activityMonitor.Enabled = false;
|
||||
_activityMonitor.ReadingChanged -= activityMonitor_ReadingChanged;
|
||||
await _activityMonitor.DeactivateAsync();
|
||||
// Unregister from reading change notifications
|
||||
_sensor.ReadingChanged -= activity_ReadingChanged;
|
||||
// Deactivate sensor
|
||||
await _sensor.DeactivateAsync();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -301,12 +134,14 @@ namespace ActivitiesExample
|
|||
/// </summary>
|
||||
/// <param name="sender">Sender object</param>
|
||||
/// <param name="args">Event arguments</param>
|
||||
private async void activityMonitor_ReadingChanged( IActivityMonitor sender, ActivityMonitorReading args )
|
||||
private async void activity_ReadingChanged(object sender, object args)
|
||||
{
|
||||
await this.Dispatcher.RunAsync( CoreDispatcherPriority.Normal, () =>
|
||||
await this.Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
|
||||
{
|
||||
ActivityData.Instance().CurrentActivity = args.Mode;
|
||||
} );
|
||||
// Call into the actual sensor implementation to update data
|
||||
// source.
|
||||
((IActivitySensor)sender).UpdateCurrentActivity(args);
|
||||
});
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -315,68 +150,9 @@ namespace ActivitiesExample
|
|||
/// <returns>Asynchronous task</returns>
|
||||
private async Task UpdateSummaryAsync()
|
||||
{
|
||||
if( _activityMonitor != null )
|
||||
if ( _sensor != null )
|
||||
{
|
||||
if( !await CallSensorCoreApiAsync( async () =>
|
||||
{
|
||||
// Read current activity
|
||||
ActivityMonitorReading reading = await _activityMonitor.GetCurrentReadingAsync();
|
||||
if( reading != null )
|
||||
{
|
||||
ActivityData.Instance().CurrentActivity = reading.Mode;
|
||||
}
|
||||
|
||||
// Fetch activity history for the day
|
||||
DateTime startDate = DateTime.Today.Subtract( TimeSpan.FromDays( _dayOffset ) );
|
||||
DateTime endDate = startDate + TimeSpan.FromDays( 1 );
|
||||
var history = await _activityMonitor.GetActivityHistoryAsync( startDate, TimeSpan.FromDays( 1 ) );
|
||||
Dictionary<Activity, TimeSpan> activitySummary = new Dictionary<Activity, TimeSpan>();
|
||||
var activityTypes = Enum.GetValues( typeof( Activity ) );
|
||||
foreach( var type in activityTypes )
|
||||
{
|
||||
activitySummary[ (Activity)type ] = TimeSpan.Zero;
|
||||
}
|
||||
if( history.Count > 0 )
|
||||
{
|
||||
Activity currentActivity = history[ 0 ].Mode;
|
||||
DateTime currentDate = history[ 0 ].Timestamp.DateTime;
|
||||
foreach( var item in history )
|
||||
{
|
||||
if( item.Timestamp >= startDate )
|
||||
{
|
||||
TimeSpan duration = TimeSpan.Zero;
|
||||
if( currentDate < startDate )
|
||||
{
|
||||
// If first activity of the day started already yesterday, set start time to midnight.
|
||||
currentDate = startDate;
|
||||
}
|
||||
if( item.Timestamp > endDate )
|
||||
{
|
||||
// If last activity extends over to next day, set end time to midnight.
|
||||
duration = endDate - currentDate;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
duration = item.Timestamp - currentDate;
|
||||
}
|
||||
activitySummary[ currentActivity ] += duration;
|
||||
}
|
||||
currentActivity = item.Mode;
|
||||
currentDate = item.Timestamp.DateTime;
|
||||
}
|
||||
}
|
||||
List<ActivityDuration> historyList = new List<ActivityDuration>();
|
||||
foreach( var activityType in activityTypes )
|
||||
{
|
||||
historyList.Add( new ActivityDuration( (Activity)activityType, activitySummary[ (Activity)activityType ] ) );
|
||||
}
|
||||
ActivityData.Instance().History = historyList;
|
||||
ActivityData.Instance().Date = startDate;
|
||||
} ) )
|
||||
{
|
||||
Debug.WriteLine( "Reading the history failed." );
|
||||
}
|
||||
await _sensor.UpdateSummaryAsync(_dayOffset);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -433,5 +209,25 @@ namespace ActivitiesExample
|
|||
await UpdateSummaryAsync();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrease opacity of the command bar when closed
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of the event</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void CommandBar_Closed(object sender, object e)
|
||||
{
|
||||
cmdBar.Opacity = 0.5;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Increase opacity of command bar when opened
|
||||
/// </summary>
|
||||
/// <param name="sender">The sender of the event</param>
|
||||
/// <param name="e">Event arguments</param>
|
||||
private void CommandBar_Opened(object sender, object e)
|
||||
{
|
||||
cmdBar.Opacity = 1;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,43 +1,52 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/2010/manifest" xmlns:m2="http://schemas.microsoft.com/appx/2013/manifest" xmlns:m3="http://schemas.microsoft.com/appx/2014/manifest" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest">
|
||||
<Identity Name="NokiaDeveloper.ActivitiesLumiaSensorCoreSDKsample" Publisher="CN=4AD6DA08-6C39-4A10-98CC-3243374DA59C" Version="1.1.0.18" />
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
IgnorableNamespaces="uap mp">
|
||||
|
||||
|
||||
<Identity Name="NokiaDeveloper.ActivitiesLumiaSensorCoreSDKsample" Publisher="CN=4AD6DA08-6C39-4A10-98CC-3243374DA59C" Version="2.0.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="faa8e717-e1ec-436b-b32a-68b85c0550dd" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
|
||||
<Properties>
|
||||
<DisplayName>Activities – Lumia SensorCore SDK sample</DisplayName>
|
||||
<PublisherDisplayName>Lumia SDK</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
<Logo>Assets\StoreLogo-sdk.png</Logo>
|
||||
</Properties>
|
||||
<Prerequisites>
|
||||
<OSMinVersion>6.3.0</OSMinVersion>
|
||||
<OSMaxVersionTested>6.3.0</OSMaxVersionTested>
|
||||
</Prerequisites>
|
||||
<mp:PhoneIdentity PhoneProductId="2ced6ce9-b515-497f-a774-1038f33ce598" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.0.0" MaxVersionTested="10.0.0.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate" />
|
||||
<Resource Language="x-generate"/>
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="x74dcbd9ay3772y41a5yb7d4yf1e511e6b0cdx" Executable="$targetnametoken$.exe" EntryPoint="ActivitiesExample.App">
|
||||
<m3:VisualElements DisplayName="Activities – Lumia SensorCore SDK sample" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="Activities - example app for SensorCore's Activity Monitor API" ForegroundText="light" BackgroundColor="transparent" ToastCapable="false">
|
||||
<m3:DefaultTile Square71x71Logo="Assets\Square71x71Logo.png" Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
</m3:DefaultTile>
|
||||
<m3:ApplicationView MinWidth="width320" />
|
||||
<!--Used in XAML Designer. DO NOT REMOVE-->
|
||||
<m3:InitialRotationPreference>
|
||||
<m3:Rotation Preference="portrait" />
|
||||
</m3:InitialRotationPreference>
|
||||
</m3:VisualElements>
|
||||
<uap:VisualElements DisplayName="Activities – Lumia SensorCore SDK sample" Square150x150Logo="Assets\Square150x150Logo.png" Square44x44Logo="Assets\Square44x44Logo.png" Description="Activities - example app for SensorCore's Activity Monitor API" BackgroundColor="transparent">
|
||||
<uap:DefaultTile Square71x71Logo="Assets\Square71x71Logo.png" Wide310x150Logo="Assets\Wide310x150Logo.png">
|
||||
</uap:DefaultTile>
|
||||
<uap:SplashScreen Image="Assets\Square71x71Logo.png" />
|
||||
<uap:InitialRotationPreference>
|
||||
<uap:Rotation Preference="portrait" />
|
||||
</uap:InitialRotationPreference>
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<DeviceCapability Name="activity" />
|
||||
<DeviceCapability Name="location" />
|
||||
<m2:DeviceCapability Name="humaninterfacedevice">
|
||||
<m2:Device Id="vidpid:0421 0716">
|
||||
<m2:Function Type="usage:ffaa 0001" />
|
||||
<m2:Function Type="usage:ffee 0001" />
|
||||
<m2:Function Type="usage:ffee 0002" />
|
||||
<m2:Function Type="usage:ffee 0003" />
|
||||
<m2:Function Type="usage:ffee 0004" />
|
||||
</m2:Device>
|
||||
</m2:DeviceCapability>
|
||||
<DeviceCapability Name="humaninterfacedevice">
|
||||
<Device Id="vidpid:0421 0716">
|
||||
<Function Type="usage:ffaa 0001" />
|
||||
<Function Type="usage:ffee 0001" />
|
||||
<Function Type="usage:ffee 0002" />
|
||||
<Function Type="usage:ffee 0003" />
|
||||
<Function Type="usage:ffee 0004" />
|
||||
</Device>
|
||||
</DeviceCapability>
|
||||
</Capabilities>
|
||||
</Package>
|
||||
</Package>
|
||||
|
|
|
@ -10,7 +10,7 @@ using System.Runtime.InteropServices;
|
|||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("activities")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2014")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2015")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
|
@ -24,6 +24,6 @@ using System.Runtime.InteropServices;
|
|||
// You can specify all the values or you can default the Build and Revision Numbers
|
||||
// by using the '*' as shown below:
|
||||
// [assembly: AssemblyVersion("1.0.*")]
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
[assembly: AssemblyVersion("2.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("2.0.0.0")]
|
||||
[assembly: ComVisible(false)]
|
|
@ -179,6 +179,9 @@ The application will now exit.</value>
|
|||
<data name="Hint.Biking" xml:space="preserve">
|
||||
<value>Biking activity</value>
|
||||
</data>
|
||||
<data name="Hint.Fidgeting" xml:space="preserve">
|
||||
<value>User is stationary but is making minor movements</value>
|
||||
</data>
|
||||
<data name="Hint.Idle" xml:space="preserve">
|
||||
<value>The phone was laying still, for example, on a table.</value>
|
||||
</data>
|
||||
|
|
|
@ -1,52 +1,31 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{613082E5-767C-439B-93E1-0B7968ADE746}</ProjectGuid>
|
||||
<Platform Condition=" '$(Platform)' == '' ">x86</Platform>
|
||||
<ProjectGuid>{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}</ProjectGuid>
|
||||
<OutputType>AppContainerExe</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>ActivitiesExample</RootNamespace>
|
||||
<AssemblyName>activities</AssemblyName>
|
||||
<RootNamespace>Activities</RootNamespace>
|
||||
<AssemblyName>Activities</AssemblyName>
|
||||
<DefaultLanguage>en-US</DefaultLanguage>
|
||||
<TargetPlatformVersion>8.1</TargetPlatformVersion>
|
||||
<MinimumVisualStudioVersion>12</MinimumVisualStudioVersion>
|
||||
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
|
||||
<TargetPlatformVersion>10.0.10240.0</TargetPlatformVersion>
|
||||
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
|
||||
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
|
||||
<EnableDotNetNativeCompatibleProfile>true</EnableDotNetNativeCompatibleProfile>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<ProjectTypeGuids>{76F1466A-8B6D-4E39-A767-685A06062A39};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
|
||||
<AppxAutoIncrementPackageRevision>False</AppxAutoIncrementPackageRevision>
|
||||
<AppxSymbolPackageEnabled>False</AppxSymbolPackageEnabled>
|
||||
<AppxBundlePlatforms>arm</AppxBundlePlatforms>
|
||||
<PackageCertificateThumbprint>5F7524CDD75F3F41BAC31F01C368A249D987521B</PackageCertificateThumbprint>
|
||||
<PackageCertificateKeyFile>ActivityMonitorSample_WP_CSharp_TemporaryKey.pfx</PackageCertificateKeyFile>
|
||||
<NuGetPackageImportStamp>55367aa0</NuGetPackageImportStamp>
|
||||
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">.\</SolutionDir>
|
||||
<RestorePackages>true</RestorePackages>
|
||||
<AppxBundle>Never</AppxBundle>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
<RestorePackages>false</RestorePackages>
|
||||
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\ARM\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>ARM</PlatformTarget>
|
||||
|
@ -56,7 +35,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
|
||||
<OutputPath>bin\ARM\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE</DefineConstants>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
|
@ -64,11 +43,35 @@
|
|||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x64\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
|
||||
<OutputPath>bin\x64\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<PlatformTarget>x64</PlatformTarget>
|
||||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<OutputPath>bin\x86\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE</DefineConstants>
|
||||
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>full</DebugType>
|
||||
<PlatformTarget>x86</PlatformTarget>
|
||||
|
@ -78,7 +81,7 @@
|
|||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
|
||||
<OutputPath>bin\x86\Release\</OutputPath>
|
||||
<DefineConstants>TRACE;NETFX_CORE</DefineConstants>
|
||||
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UAP</DefineConstants>
|
||||
<Optimize>true</Optimize>
|
||||
<NoWarn>;2008</NoWarn>
|
||||
<DebugType>pdbonly</DebugType>
|
||||
|
@ -86,11 +89,13 @@
|
|||
<UseVSHostingProcess>false</UseVSHostingProcess>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<Prefer32Bit>true</Prefer32Bit>
|
||||
<UseDotNetNativeToolchain>true</UseDotNetNativeToolchain>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="AboutPage.xaml.cs">
|
||||
<DependentUpon>AboutPage.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Compile Include="ActivitySensor.cs" />
|
||||
<Compile Include="App.xaml.cs">
|
||||
<DependentUpon>App.xaml</DependentUpon>
|
||||
</Compile>
|
||||
|
@ -155,14 +160,10 @@
|
|||
<PRIResource Include="Strings\en-US\ActivateSensorCore.resw" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Help\LumiaSensorCoreSDK.chm" />
|
||||
<None Include="packages.config" />
|
||||
<None Include="project.json" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '12.0' ">
|
||||
<VisualStudioVersion>12.0</VisualStudioVersion>
|
||||
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' < '14.0' ">
|
||||
<VisualStudioVersion>14.0</VisualStudioVersion>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(TargetPlatformIdentifier)' == '' ">
|
||||
<TargetPlatformIdentifier>WindowsPhoneApp</TargetPlatformIdentifier>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\$(TargetPlatformVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
|
||||
</Project>
|
|
@ -1,3 +0,0 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
</packages>
|
|
@ -0,0 +1,16 @@
|
|||
{
|
||||
"dependencies": {
|
||||
"Microsoft.NETCore.UniversalWindowsPlatform": "5.0.0"
|
||||
},
|
||||
"frameworks": {
|
||||
"uap10.0": {}
|
||||
},
|
||||
"runtimes": {
|
||||
"win10-arm": {},
|
||||
"win10-arm-aot": {},
|
||||
"win10-x86": {},
|
||||
"win10-x86-aot": {},
|
||||
"win10-x64": {},
|
||||
"win10-x64-aot": {}
|
||||
}
|
||||
}
|
54
README.md
54
README.md
|
@ -3,9 +3,12 @@ Activities
|
|||
==========
|
||||
|
||||
Activities is a simple application demonstrating the use of the Activity Monitor,
|
||||
one of the four APIs offered by the Lumia SensorCore SDK.
|
||||
one of the four APIs offered by the Lumia SensorCore SDK. Starting with Windows 10,
|
||||
Activity Sensor support has been added to Windows.Devices.Sensors namespace.
|
||||
This sample checks if Activity Sensor is exposed through the underlying OS APIs in
|
||||
Windows.Devices.Sensors before trying to use the one exposed by Lumia SensorCore SDK.
|
||||
|
||||
With the phone collecting in the background information about user's activity the
|
||||
With the phone collecting background information about user's activity the
|
||||
application is able to access the recorded activities and build a statistic of the
|
||||
types of activities the user has performed during the current day (from 00:00 to
|
||||
current time). This data will be displayed as a list of activities and their
|
||||
|
@ -18,13 +21,12 @@ from the Lumia SensorCore and will display the change dynamically.
|
|||
--------------------------------------------------------------------------------
|
||||
|
||||
Learn about the Lumia SensorCore SDK from the Lumia Developer's Library. The
|
||||
example requires the Lumia SensorCore SDK's NuGet package but will retrieve it
|
||||
automatically (if missing) on first build.
|
||||
example requires the Lumia SensorCore SDK's NuGet package.
|
||||
|
||||
To build the application you need to have Windows 8.1 and Windows Phone SDK 8.1
|
||||
To build the application you need to have Windows 10 and Windows 10 SDK
|
||||
installed.
|
||||
|
||||
Using the Windows Phone 8.1 SDK:
|
||||
Using the Windows 10 SDK:
|
||||
|
||||
1. Open the SLN file: File > Open Project, select the file `activities.sln`
|
||||
2. Remove the "AnyCPU" configuration (not supported by the Lumia SensorCore SDK)
|
||||
|
@ -46,12 +48,16 @@ http://msdn.microsoft.com/en-us/library/gg588378%28v=vs.92%29.aspx
|
|||
|
||||
**Important files and classes:**
|
||||
|
||||
The core of this app's implementation is in MainPage.xaml.cs where the Activity
|
||||
Monitor API is initialized (if supported) with its production implementation
|
||||
ActivityMonitor() when the app runs on a real device or with is simulated
|
||||
alternative ActivityMonitorSimulator() when running on emulator.
|
||||
The core of this app's implementation is in MainPage.xaml.cs where it opens and
|
||||
initializes the activity sensor instance when the page is loaded.
|
||||
|
||||
The API is called through the CallSensorCoreApiAsync () helper function, which
|
||||
The main page does not directly talk to the SensorCore API but a wrapper in
|
||||
ActivitySensor.cs. The wrapper tries to use ActivitySensor exposed through Windows.
|
||||
Devices.Sensors before falling back to production implementation ActivityMonitor()
|
||||
when the app runs on a real device or with its simulated alternative
|
||||
ActivityMonitorSimulator() when running on emulator.
|
||||
|
||||
All APIs are called through the CallSensorCoreApiAsync () helper function, which
|
||||
helps handling the typical errors, like required features being disabled in the
|
||||
system settings.
|
||||
|
||||
|
@ -60,23 +66,27 @@ implementation (MyDesignData) used in IDE's design mode.
|
|||
|
||||
**Required capabilities:**
|
||||
|
||||
The SensorSore SDK (via its NuGet package) automatically inserts in the manifest
|
||||
file the capabilities required for it to work:
|
||||
These are present by default in the manifest file
|
||||
|
||||
<DeviceCapability Name="activity" />
|
||||
<DeviceCapability Name="location" />
|
||||
<m2:DeviceCapability Name="humaninterfacedevice">
|
||||
<m2:Device Id="vidpid:0421 0716">
|
||||
<m2:Function Type="usage:ffaa 0001" />
|
||||
<m2:Function Type="usage:ffee 0001" />
|
||||
<m2:Function Type="usage:ffee 0002" />
|
||||
<m2:Function Type="usage:ffee 0003" />
|
||||
<m2:Function Type="usage:ffee 0004" />
|
||||
</m2:Device>
|
||||
</m2:DeviceCapability>
|
||||
<DeviceCapability Name="humaninterfacedevice">
|
||||
<Device Id="vidpid:0421 0716">
|
||||
<Function Type="usage:ffaa 0001" />
|
||||
<Function Type="usage:ffee 0001" />
|
||||
<Function Type="usage:ffee 0002" />
|
||||
<Function Type="usage:ffee 0003" />
|
||||
<Function Type="usage:ffee 0004" />
|
||||
</Device>
|
||||
</DeviceCapability>
|
||||
|
||||
|
||||
3. Version history
|
||||
--------------------------------------------------------------------------------
|
||||
* Version 2.0:
|
||||
* Refactoring the sample to use ActivitySensor from Windows.Devices.Sensors namespace
|
||||
(if it's available). The sample will fallback to SensorCore if there is no
|
||||
ActivitySensor surfaced by the OS.
|
||||
* Version 1.1.0.17:
|
||||
* Updated to use latest Lumia SensorCore SDK 1.1 Preview
|
||||
* Version 1.1.0.13:
|
||||
|
|
|
@ -1,30 +1,38 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 2013
|
||||
VisualStudioVersion = 12.0.30723.0
|
||||
# Visual Studio 14
|
||||
VisualStudioVersion = 14.0.22820.0
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "activities", "Activities\activities.csproj", "{613082E5-767C-439B-93E1-0B7968ADE746}"
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Activities", "Activities\Activities.csproj", "{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|ARM = Debug|ARM
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|ARM = Release|ARM
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Debug|x86.Build.0 = Debug|x86
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Release|ARM.Build.0 = Release|ARM
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Release|x86.ActiveCfg = Release|x86
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Release|x86.Build.0 = Release|x86
|
||||
{613082E5-767C-439B-93E1-0B7968ADE746}.Release|x86.Deploy.0 = Release|x86
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.ActiveCfg = Debug|ARM
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Build.0 = Debug|ARM
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|ARM.Deploy.0 = Debug|ARM
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Build.0 = Debug|x64
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Build.0 = Debug|x86
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Debug|x86.Deploy.0 = Debug|x86
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.ActiveCfg = Release|ARM
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Build.0 = Release|ARM
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|ARM.Deploy.0 = Release|ARM
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.ActiveCfg = Release|x64
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Build.0 = Release|x64
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x64.Deploy.0 = Release|x64
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.ActiveCfg = Release|x86
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Build.0 = Release|x86
|
||||
{DC30CE66-DAEE-4CCF-BD02-8837FE918B6F}.Release|x86.Deploy.0 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
|
Загрузка…
Ссылка в новой задаче