Digital-Watch Sample Overview
The Digital-Watch sample demonstrates how you can create a watch application using the Watch Application API.
The following figure illustrates the main screen of the Digital-Watch application.
Figure: Digital-Watch screen
If the Digital-Watch application is successfully installed, you can see your Digital-Watch UI in the watch setting's Clock menu.
Implementation
To implement the watch application:
- Add the header file.
The Watch Application API provides functions to manage the watch application life-cycle, represent the current date and time accurately, and get a watch application window. 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>
- Add the watch-application element to the manifest file:
<watch-application appid="$(packageName)" exec="$(appName)" ambient-support="true">
- Create the main function for the watch application.
An application starts with the main() function. It initializes the watch application and starts it. The watch_app_main() function is used to start the event loop. Before calling this function, set up the watch_app_lifecycle_callback_s structure variable, which is passed to the function.
int main(int argc, char *argv[]) { appdata_s ad = {0,}; int ret = 0; watch_app_lifecycle_callback_s event_callback = {0,}; event_callback.create = app_create; event_callback.time_tick = app_time_tick; event_callback.ambient_tick = app_ambient_tick; event_callback.ambient_changed = app_ambient_changed; ret = watch_app_main(argc, argv, &event_callback, &ad); if (ret != APP_ERROR_NONE) { _E("watch_app_main() is failed. err = %d", ret); } return ret; }
- Register life-cycle callbacks:
static bool app_create(int width, int height, void* user_data) { appdata_s *ad = user_data; app_event_handler_h handlers[5] = {NULL,}; watch_time_h watch_time = NULL; // Register callbacks for each system event if (watch_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, lang_changed, NULL) != APP_ERROR_NONE) { dlog_print(DLOG_ERROR, LOG_TAG, "watch_app_add_event_handler () is failed"); } _create_base_gui(ad); _set_info_time_and_date(ad, watch_time); return true; }
- Create the watch UI.
After registering the event callback, you have to draw the watch UI. To do this, you need to get the window object of the idle screen and the current time handler. Using the current time handler, you can get specific time information which is displayed on the idle screen.
static void _create_base_gui(appdata_s *ad) { // Window ad->win = _create_win(ad); ret_if(!ad->win); // Layout ad->layout = _create_layout(ad); ret_if(!ad->layout); // Background image ad->image = _create_background(ad); }
- Create the window.
You can get the window object with the watch_app_get_elm_win() function:
static Evas_Object * _create_win(appdata_s *ad) { Evas_Object *win = NULL; int ret = 0; ret = watch_app_get_elm_win(&win); if (ret != APP_ERROR_NONE) { _E("failed to get window. err = %d", ret); return NULL; } elm_win_title_set(win, "digital-watch"); elm_win_borderless_set(win, EINA_TRUE); elm_win_alpha_set(win, EINA_FALSE); elm_win_indicator_mode_set(win, ELM_WIN_INDICATOR_HIDE); elm_win_indicator_opacity_set(win, ELM_WIN_INDICATOR_BG_TRANSPARENT); elm_win_prop_focus_skip_set(win, EINA_TRUE); elm_win_role_set(win, "no-effect"); evas_object_resize(win, ad->w, ad->h); evas_object_show(win); return win; }
- Create the layout using EDC:
static Evas_Object * _create_layout(appdata_s *ad) { Evas_Object *layout = NULL; layout = elm_layout_add(ad->win); elm_layout_file_set(layout, EDJ_FILE_PATH, "layout_digital_watch"); evas_object_size_hint_weight_set(layout, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND); elm_object_content_set(ad->win, ad->layout); evas_object_size_hint_align_set(layout, EVAS_HINT_FILL, EVAS_HINT_FILL); evas_object_size_hint_min_set(layout, ad->w, ad->h); evas_object_resize(layout, ad->w, ad->h); evas_object_show(layout); return layout; }
- Create a background image:
static Evas_Object * _create_background(appdata_s *ad) { Evas_Object *bg = NULL; Eina_Bool ret = EINA_TRUE; bg = elm_bg_add(ad->layout); ret = elm_bg_file_set(bg, IMG_DIR"bg.jpg", NULL); retvm_if(!ret, NULL, "Fail to set the background image"); elm_bg_option_set(bg, ELM_BG_OPTION_CENTER); elm_object_part_content_set(ad->layout, "bg_image", bg); evas_object_show(bg); return bg; }
- Set the time and date information.
You can get the current time's watch_time_h handle with the watch_time_get_current_time() function:
Eina_Bool _set_info_time_and_date(void *data, watch_time_h watch_time) { const char *DAY_OF_WEEK_STR[7] = {"Sun", "Mon", "Tue", "Wed", "Thur", "Fri", "Sat"}; const char *MONTH_STR[12] = {"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"}; appdata_s *ad = data; char time_str[BUFFER_LENGTH] = {0}; char date_str[BUFFER_LENGTH] = {0}; char ampm_str[BUFFER_LENGTH] = {0}; char *time_str_p = NULL; int hour24 = 0; int minute = 0; int day_of_week = 0; int month = 0; int day = 0 ; retvm_if(!watch_time, EINA_FALSE, "watch_time is NULL"); retvm_if(!ad, EINA_FALSE, "appdata is NULL"); int ret = watch_time_get_current_time(&watch_time); if (ret != APP_ERROR_NONE) { _E("failed to get current time. err = %d", ret); } watch_time_get_hour24(watch_time, &hour24); watch_time_get_minute(watch_time, &minute); watch_time_get_day_of_week(watch_time, &day_of_week); watch_time_get_month(watch_time, &month); watch_time_get_day(watch_time, &day); // Time if (hour24 >= 0 && hour24 < 12) { snprintf(ampm_str, sizeof(ampm_str), "%s", "AM"); } else { snprintf(ampm_str, sizeof(ampm_str), "%s", "PM"); } sprintf(time_str, "%d:%02d", hour24%12, minute); time_str_p = g_strdup_printf("%s<font_size=24><font=Tizen:style=Bold>%s</font></font_size>", time_str, ampm_str); elm_object_part_text_set(ad->layout, "textblock_time", time_str_p); if (!time_str_p) { g_free(time_str_p); } // Date sprintf(date_str, "%s %d %s", DAY_OF_WEEK_STR[day_of_week-1], day, MONTH_STR[month-1]); elm_object_part_text_set(ad->layout, "default_text_date", date_str); return ECORE_CALLBACK_RENEW; }
- Add the time tick and ambient tick callbacks.
The time tick callback is called at least once per second. Watch applications can get the current time from the watch_time handle and draw the normal watch UI. The ambient tick callback is called at least once per minute, or when the device enters the ambient mode.
void app_time_tick(watch_time_h watch_time, void* user_data) { appdata_s *ad = user_data; _set_info_time_and_date(ad, watch_time); } void app_ambient_tick(watch_time_h watch_time, void* user_data) { appdata_s *ad = user_data; _set_info_time_and_date(ad, watch_time); }