Development

Step 1: Creating a new project

Open Visual Studio IDE to create a new Tizen Wearable Xaml App.

  1. Go to File > New > Project to open the New Project window.

  2. In the New Project window do the following steps:

    a. Select Installed > Visual C# > Tizen 4.0 platform.

    b. Select Tizen Wearable Xaml App project type.

    c. Specify the project Name (SmartLevel).

    d. Set the project Location.

    e. Click the OK button to start creating a new project.

  3. Project structure should look like below (Solution Explorer window):


Step 2: Adding assets

  1. 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)

    • Level indicator image file (res/ball.png)

    • Custom application icon - existing file should be replaced (shared/res/SmartLevel.png). Please notice that application icon filename will be different if you choose your own name for the project. In such case, make sure you update icon tag in tizen-manifest.xml file.

  2. Select the unpacked folders, res and shared, and copy them using context menu or press Control + C. Next, make a left mouse click on the project name SmartLevel in Solution Explorer and press Control + V to paste copied folders directly to the SmartLevel project.

  3. Confirm following pop-ups to replace the content of the res and shared folders of the project.


Step 3: Creating the view

  1. Go to Solution Explorer window and open the MainPage.xaml file.

  2. Remove the StackLayout element, which has been prepared by default, and add an empty AbsoluteLayout element.

    <?xml version="1.0" encoding="utf-8" ?>
    <c:CirclePage xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    xmlns:c="clr-namespace:Tizen.Wearable.CircularUI.Forms;assembly=Tizen.Wearable.CircularUI.Forms"
                    x:Class="SmartLevel.MainPage">
        <c:CirclePage.Content>
            <AbsoluteLayout>
    
            </AbsoluteLayout>
        </c:CirclePage.Content>
    </c:CirclePage>
    
  3. Add the content of the page with two image elements positioned in the Absolute Layout:

    • Image element for the application background (background.png)
    • Image element for the level ball indication (ball.png)
    <?xml version="1.0" encoding="utf-8" ?>
    <c:CirclePage xmlns="http://xamarin.com/schemas/2014/forms"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    xmlns:c="clr-namespace:Tizen.Wearable.CircularUI.Forms;assembly=Tizen.Wearable.CircularUI.Forms"
                      x:Class="SmartLevel.MainPage">
        <c:CirclePage.Content>
            <AbsoluteLayout>
                <Image Source="background.png"
                        AbsoluteLayout.LayoutFlags="PositionProportional"
                        AbsoluteLayout.LayoutBounds="0.5, 0.5, 360, 360" />
                <Image Source="ball.png"
                        AbsoluteLayout.LayoutFlags="PositionProportional"
                        AbsoluteLayout.LayoutBounds="0.5, 0.5, 40, 40"
                        Aspect="AspectFit"
                        x:Name="ball" />
            </AbsoluteLayout>
        </c:CirclePage.Content>
    </c:CirclePage>
    

Notice that we have set name ball for the image which displays level ball indication, which would be used in the code in the next section.


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: Reading data from accelerometer sensor

  1. Go to Solution Explorer window and open the MainPage.xaml.cs file.

  2. Add two lines of code:

    • A using statement for the Tizen.Sensor namespace.
    • A private field, which will store an instance of the Accelerometer class.
    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.Sensor;
    
    namespace SmartLevel
    {
        [XamlCompilation(XamlCompilationOptions.Compile)]
        public partial class MainPage : CirclePage
        {
            private Accelerometer _accelerometer;
    
            public MainPage()
            {
                InitializeComponent();
            }
        }
    }
    
  3. Add InitializeAccelerometer() method, which creates instance of Accelerometer class, initializes it and starts reading data from the accelerometer. Use this method in the MainPage constructor.

    public partial class MainPage : CirclePage
    {
        private Accelerometer _accelerometer;
    
        public MainPage()
        {
            InitializeComponent();
            InitializeAccelerometer();
        }
    
        private void InitializeAccelerometer()
        {
            _accelerometer = new Accelerometer();
            _accelerometer.Interval = 20;
            _accelerometer.DataUpdated += OnAccelerometerDataUpdated;
            _accelerometer.Start();
        }
    }
    
  4. Add OnAccelerometerDataUpdated method. It will handle DataUpdated event of the accelerometer instance by updating position of the level ball indicator.

    public partial class MainPage : CirclePage
    {
        private Accelerometer _accelerometer;
    
        public MainPage()
        {
            InitializeComponent();
            InitializeAccelerometer();
        }
    
        private void InitializeAccelerometer()
        {
            _accelerometer = new Accelerometer();
            _accelerometer.Interval = 20;
            _accelerometer.DataUpdated += OnAccelerometerDataUpdated;
            _accelerometer.Start();
        }
    
        private void OnAccelerometerDataUpdated(object sender, AccelerometerDataUpdatedEventArgs e)
        {
            double x = (e.X + 10) / 20;
            double y = (e.Y + 10) / 20;
    
            var position = new Rectangle(x, 1 - y, 40, 40);
            AbsoluteLayout.SetLayoutBounds(ball, position);
        }
    }
    

At this point, you have an application which moves level ball indicator every 20 milliseconds. In the next section, you will learn how to easily average the recent accelerometer data to smooth level ball indicator movement.

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.

Please try to pitch and roll your watch device to see level ball indication moving on the screen.

Step 5: Calculating average position based on latest data

  1. Open the MainPage.xaml.cs file. Add generic Queue collection called _positions, which stores tuple - pair of two double values. Those values are the recent positions of the level ball indicator on the watch screen.

    public partial class MainPage : CirclePage
    {
        private Accelerometer _accelerometer;
        private Queue<(double x, double y)> _positions = new Queue<(double x, double y)>();
    
        public MainPage()
        {
            InitializeComponent();
            InitializeAccelerometer();
        }
    
        // (...)
    }
    
  2. Inside OnAcceletometerDataUpdated method add code which:

    • Adds (Enqueue) the latest data sample read from the accelerometer.

    • Removes (Dequeue) the oldest data sample, but only if there are more than 25 samples in the queue _positions.

    private void OnAccelerometerDataUpdated(object sender, AccelerometerDataUpdatedEventArgs e)
    {
        double x = (e.X + 10) / 20;
        double y = (e.Y + 10) / 20;
    
        _positions.Enqueue((x, y));
        if (_positions.Count > 25)
            _positions.Dequeue();
    
        var position = new Rectangle(x, 1 - y, 40, 40);
        AbsoluteLayout.SetLayoutBounds(ball, position);
    }
    
  3. Use LINQ method Average() to calculate average value of the position based on x and y values stored in the _positions collection.

    private void OnAccelerometerDataUpdated(object sender, AccelerometerDataUpdatedEventArgs e)
    {
        double x = (e.X + 10) / 20;
        double y = (e.Y + 10) / 20;
    
        _positions.Enqueue((x, y));
        if (_positions.Count > 25)
            _positions.Dequeue();
    
        double xAverage = _positions.Average(item => item.x);
        double yAverage = _positions.Average(item => item.y);
    
        var position = new Rectangle(x, 1 - y, 40, 40);
        AbsoluteLayout.SetLayoutBounds(ball, position);
    }
    
  4. Use newly calculated xAverage and yAverage values (instead of the latest x and y) to create new position object.

    private void OnAccelerometerDataUpdated(object sender, AccelerometerDataUpdatedEventArgs e)
    {
        double x = (e.X + 10) / 20;
        double y = (e.Y + 10) / 20;
    
        _positions.Enqueue((x, y));
        if (_positions.Count > 25)
            _positions.Dequeue();
    
        double xAverage = _positions.Average(item => item.x);
        double yAverage = _positions.Average(item => item.y);
    
        var position = new Rectangle(xAverage, 1 - yAverage, 40, 40);
        AbsoluteLayout.SetLayoutBounds(ball, position);
    }
    

At this point, you have an application which displays level ball indicator based on latest 25 data samples read from accelerometer. Notice that the level ball indicator moves slowly and smoothly when the watch is rolled and/or pitched.

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.

Try to pitch and roll your watch device to see level ball indication moving on the screen. Notice that now the level ball indicator moves are smooth!

You're done!

Congratulations! You have successfully achieved the goal of this Code Lab activity. Now, you can create your own Tizen app for your Galaxy Watch by yourself! But, if you're having trouble, you may check out the link below.

Smart Level Complete Code1.53MB