Mobile native Wearable native

Widget Application: Creating Widget Applications

This tutorial demonstrates how you can create a widget application.

Warm-up

Become familiar with the Widget Application API basics by learning about:

Initializing the Widget Application

To initialize the widget application:

  1. To use the functions and data types of the Widget Application API (in mobile and wearable applications), include the <widget_app.h> header file in your application:
    #include <widget_app.h>
    
  2. Edit the widget application settings in the manifest file.

Creating the Widget Application

To create the widget application:

  1. Start and initialize the application with the main() function.

    Set up the widget_app_lifecycle_callback_s structure variable for the widget application life-cycle callbacks, define the functions themselves (widget_app_create() for initialization and widget_app_terminate() for termination), and call the widget_app_main() function to start the application event loop.

    int
    main(int argc, char *argv[])
    {
       widget_app_lifecycle_callback_s ops = {0,};
       int ret;
    
       ops.create = widget_app_create;
       ops.terminate = widget_app_terminate;
    
       ret = widget_app_main(argc, argv, &ops, NULL);
       if (ret != WIDGET_ERROR_NONE) 
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "widget_app_main() failed. err = %d", ret);
       }
    
       return ret;
    } 
    
  2. Use the widget_app_create() life-cycle function to initialize any resources that can be shared among widget instances. This function is called before the main event loop starts.
    widget_class_h widget_app_create(void *user_data)
    {
       // Hook to take necessary actions before main event loop starts
       widget_instance_lifecycle_callback_s obj_callback = {0,};
       app_event_handler_h handlers[5] = {NULL,};
    
       // Register the callback functions for the widget instance life-cycle
    
  3. Register the callback functions for the system events.

    At the end of the widget_app_create() function, remember to create a widget instance class and return a handle for it, so that the handle can be used for making widget instances.

       // Register the callback functions for system events
       widget_app_add_event_handler(&handlers[APP_EVENT_LOW_BATTERY], APP_EVENT_LOW_BATTERY, 
                                    widget_app_low_battery, NULL);
       widget_app_add_event_handler(&handlers[APP_EVENT_LOW_MEMORY], APP_EVENT_LOW_MEMORY, 
                                    widget_app_low_memory, NULL);
       widget_app_add_event_handler(&handlers[APP_EVENT_LANGUAGE_CHANGED], APP_EVENT_LANGUAGE_CHANGED, 
                                    widget_app_lang_changed, NULL);
       widget_app_add_event_handler(&handlers[APP_EVENT_REGION_FORMAT_CHANGED], 
                                    APP_EVENT_REGION_FORMAT_CHANGED, widget_app_region_changed, NULL);
    
       return widget_app_class_create(obj_callback, user_data);
    }
    

    When the system-related callback are no longer needed, remove them with the widget_app_remove_event_handler() function.

  4. Define the callback functions for the system events:
    void 
    widget_app_lang_changed(app_event_info_h event_info, void* user_data)
    {
       // Take actions when language setting changes and messages must be translated
       char *locale = NULL;
       app_event_get_language(event_info, &locale);
       elm_language_set(locale);
       free(locale);
    }
    
    void 
    widget_app_region_changed(app_event_info_h event_info, void* user_data)
    {
       // Take actions when the time zone changes
    }
    
    void 
    widget_app_low_battery(app_event_info_h event_info, void* user_data)
    {
       // Take actions when system is running low on battery (less than 5%)
       // Save the work and avoid battery-intensive processes
       widget_app_exit();
    }
    
    void 
    widget_app_low_memory(app_event_info_h event_info, void* user_data)
    {
       // Take actions when system is running on low memory
       // Save the work and release resources; if necessary, some apps can be killed
       widget_app_exit();
    }
    
  5. When you no longer need the widget application, release the resources and terminate the application:
    static void
    widget_app_terminate(void *user_data)
    {
       // Release all resources
    } 
    

Managing Widget Instance Life-cycle Callbacks

To manage the widget instance life-cycle:

  1. Define the widget instance life-cycle callbacks:
    • This callback is triggered when the widget instance is created.

      Initialize resources for this widget instance and draw the UI. If bundle content is not NULL, restore the previous status.

      int 
      widget_instance_create(widget_context_h context, bundle *content, int w, int h, void *user_data)
      {
         widget_instance_data_s *wid = (widget_instance_data_s*) malloc(sizeof(widget_instance_data_s));
         int ret;
      
         if (content != NULL) 
         {
            // Recover the previous status with the bundle object
         }
      
         // Create the UI
      
         return WIDGET_ERROR_NONE;
      }
      
    • This callback is triggered when the widget instance is destroyed.

      Release all widget resources. If the reason for the termination is not WIDGET_APP_DESTROY_TYPE_PERMANENT, store the current status with the incoming bundle.

      int 
      widget_instance_destroy(widget_context_h context, widget_app_destroy_type_e reason, 
                              bundle *content, void *user_data)
      {
         if (reason != WIDGET_APP_DESTROY_TYPE_PERMANENT) 
         {
            // Save the current status at the bundle object
         }
      
         return WIDGET_ERROR_NONE;
      } 
      
    • This callback is triggered when the widget instance is paused.

      Take the necessary actions since the widget instance becomes invisible. The framework can destroy a paused widget instance.

      int 
      widget_instance_pause(widget_context_h context, void *user_data)
      {
         return WIDGET_ERROR_NONE;
      }
      
    • This callback is triggered when the widget instance is resumed.

      Take the necessary actions since the widget instance becomes visible.

      int 
      widget_instance_resume(widget_context_h context, void *user_data)
      {
         return WIDGET_ERROR_NONE;
      }
      
    • This callback is triggered before the widget instance is resized.

      Take the necessary actions to accommodate the new size.

      int 
      widget_instance_resize(widget_context_h context, int w, int h, void *user_data)
      {
         return WIDGET_ERROR_NONE;
      } 
      
    • This callback is triggered when a widget update event is received.

      Take the necessary actions for the widget update. If the force parameter is true, the widget can be updated even in the pause state.

      int 
      widget_instance_update(widget_context_h context, bundle *content, int force, void *user_data)
      {
         return WIDGET_ERROR_NONE;
      }
      
  2. Register the callbacks in the widget_instance_lifecycle_callback_s structure during the widget application initialization:
    widget_class_h widget_app_create(void *user_data)
    {
       widget_instance_lifecycle_callback_s obj_callback = {0,};
       // Register the callback functions
       obj_callback.create = widget_instance_create;
       obj_callback.destroy = widget_instance_destroy;
       obj_callback.pause = widget_instance_pause;
       obj_callback.resume = widget_instance_resume;
       obj_callback.resize = widget_instance_resize;
       obj_callback.update = widget_instance_update;
    
       // Register system-related callbacks
    
       return widget_app_class_create(obj_callback, user_data);
    }
    

Drawing the Widget UI

To draw the widget UI, you must get a window object with the widget_app_get_elm_win() function and create the UI on the home screen:

#include <widget_app_efl.h>

typedef struct 
widget_instance_data 
{
   Evas_Object *win;
   Evas_Object *conform;
   Evas_Object *label;
} widget_instance_data_s;

static int
widget_instance_create(widget_context_h context, bundle *content, int w, int h, void *user_data)
{
   widget_instance_data_s *wid = (widget_instance_data_s*) malloc(sizeof(widget_instance_data_s));

   int ret;
   if (content != NULL) 
   {
      // Recover the previous status with the bundle object
   }

   // Window 
   ret = widget_app_get_elm_win(context, &wid->win);
   if (ret != WIDGET_ERROR_NONE) 
   {
      dlog_print(DLOG_ERROR, LOG_TAG, "failed to get window. err = %d", ret);

      return WIDGET_ERROR_FAULT;
   }

   evas_object_resize(wid->win, w, h);

   // Conformant
   wid->conform = elm_conformant_add(wid->win);
   evas_object_size_hint_weight_set(wid->conform, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
   elm_win_resize_object_add(wid->win, wid->conform);
   evas_object_show(wid->conform);

   // Label
   wid->label = elm_label_add(wid->conform);
   evas_object_resize(wid->label, w, h / 3);
   evas_object_move(wid->label, 0, h / 3);
   evas_object_show(wid->label);
   elm_object_text_set(wid->label, "Hello widget");

   // Show the window after the base GUI is set up
   evas_object_show(wid->win);

   widget_app_context_set_tag(context, wid);

   return WIDGET_ERROR_NONE;
} 

int
widget_instance_destroy(widget_context_h context, widget_app_destroy_type_e reason, 
                        bundle *content, void *user_data)
{
   if (reason != WIDGET_APP_DESTROY_TYPE_PERMANENT)
   {
      // Save the current status at the bundle object
   }

   widget_instance_data_s *wid = NULL;
   widget_app_context_get_tag(context, (void**)&wid);

   if (wid->win)
      evas_object_del(wid->win);

   free(wid);

   return WIDGET_ERROR_NONE;
}

Managing the Widget Instance

To manage the widget instance:

  1. You can set a customized widget instance with the widget_app_context_set_tag() function when the instance is created. To update or destroy the customized widget, get the instance with the widget_app_context_get_tag() function.
    typedef struct 
    {
       int val1;
    } user_defined_s;
    
    
    int 
    widget_instance_create(widget_context_h context, bundle *content, int w, int h, void *user_data)
    {
       user_defined_s *uds = (user_defined_s*)malloc(sizeof(user_defined_s));
       uds->val1 = 0;
       widget_app_context_set_tag(context, uds);
    }
    
    int 
    widget_instance_destroy(widget_context_h context, widget_destroy_type_e reason, 
                            bundle *content, void *user_data)
    {
       user_defined_s *uds = NULL;
       widget_app_context_get_tag(context, (void**)&uds);
       free(uds);
    }
    
    int 
    widget_instance_update(widget_context_h context, bundle *content, int force, void *user_data)
    {
       user_defined_s *uds = NULL;
       widget_app_context_get_tag(context, (void**)&uds);
       uds->val1 = 1;
    }
    
  2. Get the widget instance ID:
    int 
    widget_instance_update(widget_context_h context, bundle *content, int force, void *user_data)
    {
       const char *inst_id = NULL;
       inst_id = widget_app_get_id(context);
    }
    
Go to top