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:
kartelan 2015-10-08 17:08:59 -07:00
Родитель a1c3fb53c5 195fdfe6ea
Коммит fdab69c6b1
22 изменённых файлов: 1042 добавлений и 794 удалений

178
.gitignore поставляемый
Просмотреть файл

@ -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)' &lt; '12.0' ">
<VisualStudioVersion>12.0</VisualStudioVersion>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '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>

16
Activities/project.json Normal file
Просмотреть файл

@ -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": {}
}
}

Просмотреть файл

@ -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