Published on 25th of October 2017
Watch Application

Let’s start creating the 5th demo application. We will teach you how to create a watch application, in which you can change the style. Moreover, there is a possibility, by using special module, to save information about its settings in the system. In this lesson we will analyze the watch application. We will take the standard template and by removing unnecessary elements, we will prepare it for the demo application.

What is Watch Application?

Till this lesson, we've been talking about how to create UI applications in your demos, now we'll show you how to create a watch application.

From the name it can be assumed that the application should serve as a time indicator. Still this does not limit the functionality of this application. You can use it as a full-fledged app with interesting additional functions, whether it is a map displayed as a background or some other functional different from watch app. It may seem that there are some serious differences between UI and watch application, but in fact it is not.

The watch application is created in the same way as regular applications with a user interface. There are some differences in creating a base window for the watch app, because it is in a special place in the graphical shell of the device, in the rest, this is usual application. Here you can use the same widgets, services and sensors (GPS, light sensor, etc.), cause the device to vibrate, send notifications and so on.

In the watch application is a limitation on using the bezel and the Back button. In the following lessons, when we move on to the advance topics, we'll show you how to get around this ban by creating an additional window.

The life cycle of the watch application provides a special Time Tick event, which fires every second. Thus, in the event handler, you should perform an update (update the digits or change the corners of the arrows if the watch has an analog style).

Creating a Watch App Pattern

In Tizen Studio there is watch application template. Let's see how it can be created.

Open FileNewTizen Project.

Choose Template and click Next >.

nw_028_01_en

Select the Wearable profile and platform version 2.3.2 and click Next>.

nw_028_02_en

Select Native Application and click Next>.

nw_028_03_en

Then select the project: the Watch template and click Next>.

nw_028_04_en

Enter the name of the project and the name of the package with which the watch app will be build and click Finish.

nw_028_05_en
Running Watch Applications

Unlike UI applications, which you have already created in previous lessons, watch applications do not run right after installation on the device or emulator. On emulators with version 2.3.2 and below, the watch applications are set via the watch app menu in the application settings as it shown in the video.

On a real device you should press on the watch screen, to call the window for choosing the watch app, where you can set your own application, below you may see how to do it.

Preparing the Watch App for the Demo Application

As it was mentioned earlier, some templates have extra elements. Therefore, to make code more understandable, we are going to show how it can be simplified as much as possible, by throwing out unnecessary elements. In the example below the header file was deleted from the project, and the files necessary for turned on were transferred to the implementation file. Also, the conformant and extra empty event handlers were removed, as they are not needed for this demo.

#include <watch_app.h>
#include <Elementary.h>
#include <watch_app_efl.h>

typedef struct _UIData
{
   Evas_Object *win;
   Evas_Object *label;
} UIData;

static void
_ui_update(UIData *ui, watch_time_h watch_time)
{
   const int BUF_SIZE  = 256;
   char text[BUF_SIZE] = {0,};
   int hour24          = 0;
   int minute          = 0;
   int second          = 0;

   watch_time_get_hour24(watch_time, &hour24);
   watch_time_get_minute(watch_time, &minute);
   watch_time_get_second(watch_time, &second);

   snprintf(text,
            BUF_SIZE,
            "<font font_size=80><align=center>%02d:%02d:%02d</align></font>",
            hour24,
            minute,
            second);

   elm_object_text_set(ui->label, text);
}

static void
_watch_update(UIData *ui, watch_time_h watch_time)
{
   if (watch_time == NULL)
     {
        watch_time_get_current_time(&watch_time);
        _ui_update(ui, watch_time);
        watch_time_delete(watch_time);
     }
   else
     _ui_update(ui, watch_time);
}

static void
_label_create(UIData *ui, int width, int height)
{
   ui->label = elm_label_add(ui->win);

   const int label_heigh = 80;
   evas_object_resize(ui->label, width, label_heigh);
   evas_object_move(ui->label, 0, height / 2 - label_heigh / 2);

   evas_object_show(ui->label);
}

static void
_window_create(UIData *ui, int width, int height)
{
   watch_app_get_elm_win(&ui->win);

   evas_object_resize(ui->win, width, height);

   _label_create(ui, width, height);

   evas_object_show(ui->win);
}

static bool
_app_create(int width, int height, void *data)
{
   UIData *ui = data;

   _window_create(ui, width, height);

   _watch_update(ui, NULL);

   return true;
}

static void
_app_terminate(void *data)
{
   UIData *ui = data;
   evas_object_del(ui->win);
}

static void
_app_time_tick(watch_time_h watch_time, void *data)
{
   UIData *ui = data;
   _watch_update(ui, watch_time);
}

int
main(int argc, char *argv[])
{
   UIData ui = {0,};

   watch_app_lifecycle_callback_s lifecycle_callbacks = {0,};

   lifecycle_callbacks.create    = _app_create;
   lifecycle_callbacks.terminate = _app_terminate;
   lifecycle_callbacks.time_tick = _app_time_tick;

   return watch_app_main(argc, argv, &lifecycle_callbacks, &ui);
}

So, now you can see 8 small functions, let's analyze what each of them does.

As in any other program, everything starts with the main() function.

int
main(int argc, char *argv[])
{
   UIData ui = {0,};

   watch_app_lifecycle_callback_s lifecycle_callbacks = {0,};

   lifecycle_callbacks.create    = _app_create;
   lifecycle_callbacks.terminate = _app_terminate;
   lifecycle_callbacks.time_tick = _app_time_tick;

   return watch_app_main(argc, argv, &lifecycle_callbacks, &ui);
}

In main() create a structure object with interface elements; initialize the handlers of some events of the watch life cycle, namely: creation, event of time change, and completion. And at the end, run the main loop of the watch application with the watch_app_main() function. In the _app_terminate() handler, delete the window, which is the root widget, so it will take care of deleting the entire hierarchy of widgets that will be created.

static void
_app_terminate(void *data)
{
   UIData *ui = data;
   evas_object_del(ui->win);
}

In the _app_create() handler, create your root window and all widgets of the watch app, and after that call the application update with accordance to the current time. As it was mentioned earlier, creating a watch window differs from the creating a window in a UI application. Here you have to call watch_app_get_elm_win() instead of elm_win_util_standard_add(). And pass there the pointer on the pointer of Evas object, in which it is necessary to save the created window. Also in this application, the arguments of the handler are different from the arguments of the usual UI application, here the width and height of the area to which the watch will be placed come into function. Therefore after its creation, we explicitly set the size of the window in accordance with the arguments.

static void
_window_create(UIData *ui, int width, int height)
{
   watch_app_get_elm_win(&ui->win);

   evas_object_resize(ui->win, width, height);

   _label_create(ui, width, height);

   evas_object_show(ui->win);
}

static bool
_app_create(int width, int height, void *data)
{
   UIData *ui = data;

   _window_create(ui, width, height);

   watch_time_h watch_time = NULL;
   watch_time_get_current_time(&watch_time);
   _watch_update(ui, watch_time);
   watch_time_delete(watch_time);

   return true;
}

Below is a function in which a text widget for time displaying is created

static void
_label_create(UIData *ui, int width, int height)
{
   ui->label = elm_label_add(ui->win);

   const int label_heigh = 80;
   evas_object_resize(ui->label, width, label_heigh);
   evas_object_move(ui->label, 0, height / 2 - label_heigh / 2);

   evas_object_show(ui->label);
}

Containers for markup will not be used in this demo application, and geometry will be explicitly specified by widgets. This is reasonable, since this interface is simple and will consist of a background widget and a text widget. To the text widget was set a height of 80 pixels and it was placed in the middle of the screen (relative to its height and width). After widgets creation, function, which you have written for the watch updating, is called. In this function the interface is updated with the passed or with the current time. In the interface update function, we change the text widget according to the time object passed there. A string is formed with some parameters of the style, to increase the text size and center it horizontally. We’ve described in detail the styles for the text widget in the lesson 16.

static void
_ui_update(UIData *ui, watch_time_h watch_time)
{
   const int BUF_SIZE  = 256;
   char text[BUF_SIZE] = {0,};
   int hour24          = 0;
   int minute          = 0;
   int second          = 0;

   watch_time_get_hour24(watch_time, &hour24);
   watch_time_get_minute(watch_time, &minute);
   watch_time_get_second(watch_time, &second);

   snprintf(text,
            BUF_SIZE,
            "<font font_size=80><align=center>%02d:%02d:%02d</align></font>",
            hour24,
            minute,
            second);

   elm_object_text_set(ui->label, text);
}

static void
_watch_update(UIData *ui, watch_time_h watch_time)
{
   if (watch_time == NULL)
     {
        watch_time_get_current_time(&watch_time);
        _ui_update(ui, watch_time);
        watch_time_delete(watch_time);
     }
   else
     _ui_update(ui, watch_time);
}

Note that for work with time, there is a special type of object - watch_time_h.

There is a user friendly interface, although nobody forbids you to work with struct tm from "time.h".

The last function _app_time_tick() is a handler for the time change event, it is called every second. In this function you can rotate the arrows or change the digits that represent the time. So that’s what will be done, using the function of updating the watch app, created above.

static void
_app_time_tick(watch_time_h watch_time, void *data)
{
   UIData *ui = data;
   _watch_update(ui, watch_time);
}

In this handler, the first parameter is information about the system current time; pass it to the watch app updating function. Let's install and run our application and see what happens.

The full code of this example is available for downloading here WearLesson028

In the next lessons we will teach you how to implement other watch applications as demo applications and probably you would not need a text widget, so it was deleted, instead was prepared an empty template for the watch demo applications, you can download it here WearWatchTemplate. You can also use it to create your own watch applications instead of the standard template from the development environment.

Leave a Reply

Your email address will not be published. Required fields are marked *