Watch Application: Creating a Watch Application
This tutorial demonstrates how you can create a watch application, set the time, and use the ambient mode.
This feature is supported in wearable applications only.
Warm-up
Become familiar with the Watch Application API basics by learning about:
-
Initializing the Watch Application
Initialize a watch application for use.
-
Managing Life-cycle Callbacks
Set the necessary callbacks for application life-cycle management.
-
Managing System-related Callbacks
Manage the callbacks that monitor system status changes.
-
Drawing the Watch UI
Manage the time handle and retrieve the window object for the watch UI.
-
Getting the Current Time
Get the current time or time zone.
-
Using the Ambient Mode
Use the ambient mode to show limited information on the screen.
Initializing the Watch Application
To initialize the watch application:
- To use the functions and data types of the Watch Application API, include the <watch_app.h> header file in your application:
#include <watch_app.h>
- To use the watch_app_ambient_tick_cb() callback in the ambient mode, declare the http://tizen.org/privilege/alarm.set privilege in the manifest file.
Managing Life-cycle Callbacks
To manage the life-cycle callbacks:
-
Register the necessary callbacks:
- The create callback is called before the application main loop starts. In this callback, you can initialize the application resources, such as create windows and data structures.
bool app_create(int width, int height, void* user_data) { // Hook to take necessary actions before the main event loop starts // This usually means initializing the UI and application data return true; }
- The app_control callback is called when another application sends a launch request to the application.
void app_control(app_control_h app_control, void* user_data) { // Handle the launch request, show the user the task requested through the "app_control" parameter }
- The pause callback is called when the application is completely obscured by another application and becomes invisible.
void app_pause(void* user_data) { // Take necessary actions when application becomes invisible // Release the resources needed to draw the normal watch }
- The resume callback is called when the application becomes visible.
void app_resume(void* user_data) { // Take the necessary actions when application becomes visible // Acquire the resources needed to draw the normal watch }
- The terminate callback is called when the application main loop exits.
void app_terminate(void* user_data) { // Release all resources }
- The time_tick callback is called at least once per second. The watch applications can get the current time from the watch_time time handle to draw a normal watch.
void app_time_tick(watch_time_h watch_time, void* user_data) { // Called at least once per second // Draw a normal watch with the hour, minute, and second }
- The create callback is called before the application main loop starts. In this callback, you can initialize the application resources, such as create windows and data structures.
- Set the event callbacks in the watch_app_lifecycle_callback_s structure, and pass the structure to the watch_app_main() function that starts the watch application event loop:
int main(int argc, char* argv[]) { appdata ad = {0,}; watch_app_lifecycle_callback_s callback = {0,}; callback.create = app_create; callback.app_control = app_control; callback.terminate = app_terminate; callback.pause = app_pause; callback.resume = app_resume; callback.time_tick = app_time_tick; // Ambient mode callbacks int ret = watch_app_main(argc, argv, &callback, &ad); if (ret != APP_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_main() is failed. err = %d", ret); } return ret; }
Managing System-related Callbacks
To manage the callbacks related to system status changes:
-
Define the following callback functions:
- lang_changed: Triggered when the system language changes and the messages are translated.
- region_changed: Triggered when the time zone changes.
- low_memory: Triggered when the system is running low on memory. Use the callback to save the current work and release resources; if this is not enough, the platform frees resources automatically and can even kill some applications.
- low_battery: Triggered when the system is running low on battery (less than 5%). Use the callback to save the current work and avoid battery-draining workloads.
void lang_changed(app_event_info_h event_info, void* user_data) { // Take the necessary actions when the language setting changes } void region_changed(app_event_info_h event_info, void* user_data) { // Take the necessary actions when the region setting changes } void low_battery(app_event_info_h event_info, void* user_data) { // Take the necessary actions when the system is running low on battery watch_app_exit(); } void low_memory(app_event_info_h event_info, void* user_data) { // Take the necessary actions when the system is running low on memory watch_app_exit(); }
-
Register the callback functions:
bool app_create(void *user_date) { // Register callbacks for each system event if (watch_app_add_event_handler(&handler, APP_EVENT_LANGUAGE_CHANGED, lang_changed, NULL) != APP_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler() is failed"); } if (watch_app_add_event_handler(&handler, APP_EVENT_REGION_FORMAT_CHANGED, region_changed, NULL) != APP_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler() is failed"); } if (watch_app_add_event_handler(&handler, APP_EVENT_LOW_BATTERY, low_battery, NULL) != APP_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler() is failed"); } if (watch_app_add_event_handler(&handler, APP_EVENT_LOW_MEMORY,low_ memory, NULL) != APP_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler() is failed"); } return true; }
Drawing the Watch UI
To draw the watch UI, you need the current time handle and the window object of the idle screen:
- Get the window object with the watch_app_get_elm_win() function:
#include <watch_app_efl.h> typedef struct { Evas *evas; Evas_Object *win; Evas_Object *conform; Evas_Object *label; } appdata; static void __create_base_gui(appdata *ad, int width, int height) { int ret; watch_time_h watch_time = NULL; ret = watch_app_get_elm_win(&ad->win); if (ret != APP_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "failed to get window. err = %d", ret); return; } evas_object_resize(ad->win, width, height); ad->conform = elm_conformant_add(ad->win); evas_object_size_hint_weight_set(ad->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_win_resize_object_add(ad->win, ad->conform); evas_object_show(ad->conform); ad->label = elm_label_add(ad->conform); evas_object_resize(ad->label, width, height / 3); evas_object_move(ad->label, 0, height / 3); evas_object_show(ad->label);
- Get the time handle for the current time with the watch_time_get_current_time() function:
ret = watch_time_get_current_time(&watch_time); if (ret != APP_ERROR_NONE) dlog_print(DLOG_ERROR, LOG_TAG, "failed to get current time. err = %d", ret); __update_watch(ad, watch_time); } bool app_create(void *user_date) { // Define system callbacks appdata *ad = data; __create_base_gui(ad, width, height); return true; }
- When you no longer need the watch_time_h time handle, release it with the watch_time_delete() function.
Getting the Current Time
You can get the current local time in various formats using the Watch Application methods and the time handle. When retrieving the current local time, the time handle parameter cannot be NULL.
For example, you can use the int watch_time_get_minute() method to retrieve the current minute value.
static void __update_watch(appdata *ad, watch_time_h watch_time) { watch_text[TEXT_BUF_SIZE]; int hour24, minute, second; if (watch_time == NULL) return; watch_time_get_hour24(watch_time, &hour24); watch_time_get_minute(watch_time, &minute); watch_time_get_second(watch_time, &second); snprintf(watch_text, TEXT_BUF_SIZE, "<align=center>Hello Watch<br/>%02d:%02d:%02d</align>", hour24, minute, second); elm_object_text_set(ad->label, watch_text); } static void __create_base_gui(appdata *ad, int width, int height) { // Get the window object and time handle __update_watch(ad, watch_time); }
You can also get the UTC time and time zone, if needed, using the watch_time_get_utc_time(), watch_time_get_utc_timestamp(), and watch_time_get_time_zone() functions.
Using the Ambient Mode
To use the ambient mode:
- Define the ambient mode callbacks.
The watch_app_ambient_changed_cb() callback is triggered when the ambient mode is enabled or disabled in the device. You can use the callback to initialize your ambient mode UI.
The watch_app_ambient_tick_cb() callback is triggered every minute while the device is in the ambient mode. You can use the callback to update the time on your watch application in the ambient mode. In this callback, do not perform time-consuming task and always update the UI as fast as possible. The platform can put the device to sleep shortly after the ambient tick expires.
void app_ambient_tick(watch_time_h watch_time, void* user_data) { appdata *ad = user_data; __update_watch(ad, watch_time); } void app_ambient_changed(bool ambient_mode, void* user_data) { if (ambient_mode) { // Prepare to enter the ambient mode } else { // Prepare to exit the ambient mode } }
- Register the ambient mode callbacks:
int main(int argc, char* argv[]) { appdata ad = {0,}; watch_app_lifecycle_callback_s callback = {0,}; // Other life-cycle callbacks callback.ambient_tick = app_ambient_tick; callback.ambient_changed = app_ambient_changed; int ret = watch_app_main(argc, argv, &callback, &ad); if (ret != APP_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_main() is failed. err = %d", ret); } return ret; }