Development
Step 1: Preparing the area
Open Visual Studio IDE to create a new Tizen Wearable App.
-
Go to File > New > Project to open the New Project window.
-
In the New Project window do the following steps:
a. Select Installed > Visual C# > Tizen platform.
b. Select Tizen Wearable App project type.
c. Specify the project Name.
d. Set the project Location.
e. Click the OK button to start creating a new project.
-
Project structure should look like the following one (Solution Explorer window).
Step 2: Adding assets
-
Download and unpack the assets for the application.
The assets pack consists of two folders...
... which contain the following set of images:
-
background image file (res/
background.png
) -
on-going measurement indicator image file (res/
heart.png
) -
Custom application icon - existing file should be replaced (shared/res/
PulsometerSDC.png
). Note that the application icon file name will be different if you choose own name for the project.
-
-
Select and copy the unpacked folders and paste them directly to the PulsometerSDC project.
-
Confirm following pop-ups to replace the content of the res and shared folders of the project.
Step 3: Creating the view
-
Go to Solution Explorer window, right-click on the project and select Add > New Item from the context menu.
-
The "Add New Item" window will appear. Create
MainPage.xaml
file:a. Select Installed > Visual C# Items >
Xamarin.Forms
item type.b. Select Content Page file type.
c. Specify file name –
MainPage.xaml
.d. Click the Add button to confirm.
-
Open
MainPage.xaml
file. Add an XML namespace forTizen.Circular.UI
library and replace theContentPage
with aCirclePage
from the cui namespace.<?xml version="1.0" encoding="utf-8" ?> <cui:CirclePage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:cui="clr-namespace:Tizen.Wearable.CircularUI.Forms;assembly=Tizen.Wearable.CircularUI.Forms" x:Class="PulsometerSDC.MainPage"> <cui:CirclePage.Content> <StackLayout> <Label Text="Welcome to Xamarin.Forms!" VerticalOptions="CenterAndExpand" HorizontalOptions="CenterAndExpand" /> </StackLayout> </cui:CirclePage.Content> </cui:CirclePage>
-
Replace the content of the page with three elements positioned in absolute layout:
-
Image element for the application background (
background.png
) -
Image element for the on-going measurement indicator (
heart.png
) -
Label element displaying current heart rate value
<?xml version="1.0" encoding="utf-8" ?> <cui:CirclePage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:cui="clr-namespace:Tizen.Wearable.CircularUI.Forms;assembly=Tizen.Wearable.CircularUI.Forms" x:Class="PulsometerSDC.MainPage"> <cui:CirclePage.Content> <AbsoluteLayout> <Image AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" Source="background.png" /> <Image x:Name="measuringIndicator" AbsoluteLayout.LayoutFlags="None" AbsoluteLayout.LayoutBounds="155, 64, 50, 44" Source="heart.png" IsVisible="False" /> <Label x:Name="hrValue" TextColor="#454545" FontSize="20" AbsoluteLayout.LayoutFlags="None" AbsoluteLayout.LayoutBounds="127, 169, 104, 48" HorizontalTextAlignment="Center" Text="0" /> </AbsoluteLayout> </cui:CirclePage.Content> </cui:CirclePage>
-
-
Add an ActionButton element to the page. It will be starting and stopping the heart rate measurement.
<?xml version="1.0" encoding="utf-8" ?> <cui:CirclePage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" xmlns:cui="clr-namespace:Tizen.Wearable.CircularUI.Forms;assembly=Tizen.Wearable.CircularUI.Forms" x:Class="PulsometerSDC.MainPage"> <cui:CirclePage.Content> <AbsoluteLayout> <Image AbsoluteLayout.LayoutFlags="All" AbsoluteLayout.LayoutBounds="0, 0, 1, 1" Source="background.png" /> <Image x:Name="measuringIndicator" AbsoluteLayout.LayoutFlags="None" AbsoluteLayout.LayoutBounds="155, 64, 50, 44" Source="heart.png" IsVisible="False" /> <Label x:Name="hrValue" TextColor="#454545" FontSize="20" AbsoluteLayout.LayoutFlags="None" AbsoluteLayout.LayoutBounds="127, 169, 104, 48" HorizontalTextAlignment="Center" Text="0" /> </AbsoluteLayout> </cui:CirclePage.Content> <cui:CirclePage.ActionButton> <cui:ActionButtonItem Text="MEASURE" x:Name="actionButton" Clicked="OnActionButtonClicked" /> </cui:CirclePage.ActionButton> </cui:CirclePage>
-
Open the
MainPage.xaml.cs
file (code behind file of theMainPage.xaml
file). Add a using statement for theTizen.CircularUI
library and replace base class of the page with the CirclePage.using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Forms; using Xamarin.Forms.Xaml; using Tizen.Wearable.CircularUI.Forms; namespace PulsometerSDC { [XamlCompilation(XamlCompilationOptions.Compile)] public partial class MainPage : CirclePage { public MainPage() { InitializeComponent(); } } }
-
Add an empty click handler to the action button we created earlier.
public partial class MainPage : CirclePage { public MainPage() { InitializeComponent(); } private void OnActionButtonClicked(object sender, EventArgs e) { } }
-
Open the
App.cs
file. Replace the MainPage property assignment with new instance of the class we created earlier.public class App : Application { public App() { // The root page of your application MainPage = new MainPage(); } protected override void OnStart() { // Handle when your app starts } protected override void OnSleep() { // Handle when your app sleeps } protected override void OnResume() { // Handle when your app resumes } }
To build and run this application on the device, follow the steps below:
-
Press Ctrl+Shift+B keys to build the project.
-
Press Ctrl+F5 keys to start installing the application.
The application should now look like the one below:
Step 4: Handling privileges
-
Open
tizen-manifest.xml
file (configuration editor should appear):a. Select the Privileges tab.
b. Click Add button and select the "http://tizen.org/privilege/healthinfo" privilege from the list. Click the OK button to confirm.
c. The privilege should appear on the list.
Note :Do not forget to save the file (File > Save Selected Items).
-
Open the
MainPage.xaml.cs
file. Add a using statement for theTizen.Security
namespace.using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using Xamarin.Forms; using Xamarin.Forms.Xaml; using Tizen.Wearable.CircularUI.Forms; using Tizen.Security;
-
Create the
CheckPrivileges
method and two callbacks -OnPrivilegesGranted
andOnPrivilegesDenied
. Call the method in the page constructor.The
CheckPrivileges
method checks the status of user's approval for the "http://tizen.org/privilege/healthinfo" privilege. It may get the status instantly (user already allowed or denied granting the privilege and his/her choice was remembered) or have to ask the user before proceeding. Finally it calls one of two callbacks -OnPrivilegesGranted
andOnPrivilegesDenied
.The
OnPrivilegesGranted
callback is empty for now and will be implemented later.The
OnPrivilegesDenied
callback closes the application because the measurement cannot be done.public partial class MainPage : CirclePage { public MainPage() { InitializeComponent(); CheckPrivileges(); } private void CheckPrivileges() { // check permission status (allow, deny, ask) to determine action which has to be taken string privilege = "http://tizen.org/privilege/healthinfo"; CheckResult result = PrivacyPrivilegeManager.CheckPermission(privilege); if (result == CheckResult.Allow) { OnPrivilegesGranted(); } else if (result == CheckResult.Deny) { OnPrivilegesDenied(); } else // the user must be asked about granting the privilege { PrivacyPrivilegeManager.GetResponseContext(privilege).TryGetTarget(out var context); if (context != null) { context.ResponseFetched += (sender, e) => { if (e.cause == CallCause.Answer && e.result == RequestResult.AllowForever) { OnPrivilegesGranted(); } else { OnPrivilegesDenied(); } }; } PrivacyPrivilegeManager.RequestPermission(privilege); } } private void OnPrivilegesGranted() { } private void OnPrivilegesDenied() { // close the application Tizen.Applications.Application.Current.Exit(); } private void OnActionButtonClicked(object sender, EventArgs e) { } }
Step 5: Performing the measurement
-
Open the
MainPage.xaml.cs
file. Add ausing
statement for theTizen.Sensor
namespace.using Tizen.Wearable.CircularUI.Forms; using Tizen.Security; using Tizen.Sensor;
-
Add two private fields. The first one stores an instance of the
HeartRateMonitor
class, while the second one is a flag indicating if there is on-going measurement.public partial class MainPage : CirclePage { private HeartRateMonitor _monitor; private bool _measuring = false; public MainPage() { InitializeComponent(); CheckPrivileges(); } // (...) }
-
Create and configure an instance of the monitor (in
OnPrivilegesGranted
method).private void OnPrivilegesGranted() { // create an instance of the monitor _monitor = new HeartRateMonitor(); // specify frequency of the sensor data event by setting the interval value (in milliseconds) _monitor.Interval = 1000; }
-
Add
OnMonitorDataUpdated
callback method. It will handleDataUpdated
event of the monitor by updating the label displaying current heart rate value. We will use it in the next step.private void OnPrivilegesDenied() { // close the application Tizen.Applications.Application.Current.Exit(); } private void OnMonitorDataUpdated(object sender, HeartRateMonitorDataUpdatedEventArgs e) { // update displayed value hrValue.Text = e.HeartRate > 0 ? e.HeartRate.ToString() : "0"; }
-
Add methods responsible for starting and stopping the measurement.
If the measurement needs to be started:
-
listener method (
OnMonitorDataUpdated
) is registered to theDataUpdated
event of the monitor -
Start method of the monitor (
HeartRateMonitor
) is called -
action button text is changed to STOP
-
measuring indicator element (heart image) is shown
If the measurement needs to be stopped:
-
listener method (
OnMonitorDataUpdated
) is unregistered from theDataUpdated
event of the monitor -
Stop method of the monitor (
HeartRateMonitor
) is called -
action button text is changed to MEASURE
-
measuring indicator element (heart image) is hidden
private void OnMonitorDataUpdated(object sender, HeartRateMonitorDataUpdatedEventArgs e) { // update displayed value hrValue.Text = e.HeartRate > 0 ? e.HeartRate.ToString() : "0"; } private void StartMeasurement() { _monitor.DataUpdated += OnMonitorDataUpdated; _monitor.Start(); _measuring = true; // update the view actionButton.Text = "STOP"; measuringIndicator.IsVisible = true; } private void StopMeasurement() { _monitor.DataUpdated -= OnMonitorDataUpdated; _monitor.Stop(); _measuring = false; // update the view actionButton.Text = "MEASURE"; measuringIndicator.IsVisible = false; }
-
-
Implement the action button click handler. It starts or stops the measurement depending on the current state (
_measuring
flag).private void OnActionButtonClicked(object sender, EventArgs e) { if (_measuring) { StopMeasurement(); } else { StartMeasurement(); } }
Step 6: Customizing the life cycle
The last thing, we want to do, is stopping the measurement when the application goes into the background (home button is pressed).
-
Open the
App.cs
file. We will useMessagingCenter
class to notify other modules that the application enters the sleeping state.protected override void OnSleep() { // Handle when your app sleeps MessagingCenter.Send(this, "sleep"); }
-
Go to the
MainPage.xaml.cs
file. Extend theOnPrivilegesGranted
method by subscribing to message sent in theApp.cs
file. The handler will stop the measurement if it is necessary.private void OnPrivilegesGranted() { // create an instance of the monitor _monitor = new HeartRateMonitor(); // specify frequency of the sensor data event by setting the interval value (in milliseconds) _monitor.Interval = 1000; // stop the measurement when the application goes background MessagingCenter.Subscribe(this, "sleep", (sender) => { if (_measuring) { StopMeasurement(); } }); }
Step 7: Testing the application
-
Connect the target device and select Build > Build Solution or F6 as a shortcut to build it and then select Debug > Start Without Debugging from the Visual Studio menu or use Ctrl + F5 shortcut to run on the target device.
The application should launch.
-
Put the watch on your hand and press the MEASURE button. Wait for a while until the measurement is done. It takes about 10 seconds for the first results to show up.
Learn more by watching the video
You're done!
Congratulations! You have successfully achieved the goal of this Code Lab activity. Now, you can create a pulsometer app using Tize C# by yourself! But, if you're having trouble, you may check out the link below.