Taskmanager Sample Overview

Mobile native

The Taskmanager sample demonstrates how to retrieve installed application information using the Application Manager API. You can filter the information, and resume or terminate applications running in the background. The Taskmanager displays all running applications (except itself) in a genlist. You can tap an item to resume the application, or swipe left or right to terminate it and remove it from the genlist.

Figure: Taskmanager screen

Taskmanager default screen Taskmanager swipe screen Taskmanager after swipe screen

Prerequisites

To ensure proper application execution, the following privileges must be set:

  • http://tizen.org/privilege/packagemanager.info
  • http://tizen.org/privilege/appmanager.kill.bgapp
  • http://tizen.org/privilege/appmanager.launch

Implementation

Application Manager Module

The application manager module allows you to iterate through all installed applications to retrieve their data. The Taskmanager, however, only needs information about applications that are both running and displayable. Instead of checking the nodisplay flag of each installed application, you can set up a filter that automatically retrieves applications of a specified type only:

  1. Create the filter using the app_info_filter_create() function.

    To specify the filter, call the app_info_filter_add_bool() function to add a boolean filter property to a given filter handle. In this sample, the PACKAGE_INFO_PROP_APP_NODISPLAY property is set to false. It filters out all applications that have the nodisplay property set to true and leaves only those that are displayable.

    if (app_info_filter_create(&appmgr_data.app_info_filter) != APP_MANAGER_ERROR_NONE) 
    {
       // Error handling
    }
    
    if (app_info_filter_add_bool(appmgr_data.app_info_filter, PACKAGE_INFO_PROP_APP_NODISPLAY, false) != APP_MANAGER_ERROR_NONE) 
    {
       // Error handling
    }
    
  2. Use the filter to execute the supplied callback function (__app_info_cb()) for each application that satisfies the filter condition using the app_info_filter_foreach_appinfo() function. The function takes the filter handle, callback function, and user defined data as parameters.

    if (app_info_filter_foreach_appinfo(appmgr_data.app_info_filter, __app_info_cb, NULL) != APP_MANAGER_ERROR_NONE) 
    {
       // Error handling
    }
    
  3. The callback function retrieves the application data. Its first parameter (app_info) is used to retrieve various information with the following functions:

    • app_info_get_app_id(): Get the application ID
    • app_info_get_icon(): Get the application icon path
    • app_manager_is_running(): Get the running state of the application (the Taskmanager only displays running applications)

    If the application is running and its ID does not match the Taskmanager ID, it is saved in the application list. The Taskmanager ID was retrieved earlier using the app_get_id() function from the Tizen App Common API.

    static bool
    __app_info_cb(app_info_h app_info, void *user_data)
    {
       // Variable declaration and initialization
    
       if (app_info_get_app_id(app_info, &app_id) != APP_MANAGER_ERROR_NONE) 
       {
          // Error handling
       }
    
       if (app_info_get_icon(app_info, &app_icon) != APP_MANAGER_ERROR_NONE) 
       {
          // Error handling
       }
    
       if (app_manager_is_running(app_id, &running) != APP_MANAGER_ERROR_NONE) 
       {
          // Error handling
       }
    
       if (running && __compare_strings(app_id, appmgr_data.taskmgr_id)) 
       {
          new_item = item_create(app_id, app_icon);
          if (!new_item) 
          {
             // Error handling
          }
    
          appmgr_data.apps_list = eina_list_append(appmgr_data.apps_list, new_item);
       }
    
       return true;
    }
    
    static int
    __compare_strings(char *app_id1, char *app_id2)
    {
       int ret = strncmp(app_id1, app_id2, ITEM_APP_ID_STR_MAX_LENGTH);
    
       if (strlen(app_id1) == strlen(app_id2) && !ret) 
       {
          return 0;
       } 
       else 
       {
          return ret > 0 ? 1 : -1;
       }
    }
    
  4. After all applications with the nodisplay flag set to false has been checked, the application list is sorted using the eina_list_sort() function:

    The function takes the Eina_List component as the first parameter. The second parameter defines the maximum number of list elements to sort. If it is set to 0, all elements are sorted. The last parameter is a pointer to a function that handles list data comparisons. It compares data1 and data2, and returns 0 if they are equal, -1 if the first data is smaller, and 1 if it is bigger.

    appmgr_data.apps_list = eina_list_sort(appmgr_data.apps_list, 0, __compare_items_cb);
    
    static int
    __compare_items_cb(const void *data1, const void *data2)
    {
       app_item_t *item1 = NULL;
       app_item_t *item2 = NULL;
    
       if (!data1 || !data2) 
       {
          // Error handling
       }
    
       item1 = (app_item_t *)data1;
       item2 = (app_item_t *)data2;
    
       return __compare_strings(item1->app_id, item2->app_id);
    }
    

    After all comparisons are done, the sorted list is returned to be handled by the view module.

Apart from retrieving application data, the Taskmanager also enables the user to resume or terminate an application running in the background:

  1. Before the resume or terminate actions can be performed, the application context must be acquired using the app_manager_get_app_context() function with the application ID as a parameter.
  2. Use the app_manager_resume_app() and app_manager_request_terminate_bg_app() functions cto resume or terminate the application.

    Both functions take the application context as a parameter.

  3. After the context is no longer needed, destroy it using the app_context_destroy() function.

The following example shows the application_mgr_resume_app() and application_mgr_terminate_app() functions:

bool
application_mgr_resume_app(char *app_id)
{
   app_context_h app_context = NULL;

   // Error handling

   if (app_manager_get_app_context(app_id, &app_context) != APP_MANAGER_ERROR_NONE) 
   {
      // Error handling
   }

   if (app_manager_resume_app(app_context) != APP_MANAGER_ERROR_NONE) 
   {
      // Error handling
   }

   if (app_context_destroy(app_context) != APP_MANAGER_ERROR_NONE) 
   {
      // Error handling
   }

   return true;
}

bool
application_mgr_terminate_app(char *app_id)
{
   app_context_h app_context = NULL;

   // Error handling

   if (app_manager_get_app_context(app_id, &app_context) != APP_MANAGER_ERROR_NONE) 
   {
      // Error handling
   }

   if (app_manager_request_terminate_bg_app(app_context) != APP_MANAGER_ERROR_NONE) 
   {
      // Error handling
   }

   if (app_context_destroy(app_context) != APP_MANAGER_ERROR_NONE) 
   {
      // Error handling
   }

    __remove_app_from_list(app_id);

   return true;
}

When all Taskmanager resources are released, use the app_info_filter_destroy() function to destroy the application manager filter created earlier. The application list as well as each list item also have to be released. The application_mgr_destroy() function is called when the Taskmanager application is terminated.

bool
application_mgr_destroy(void)
{
   if (app_info_filter_destroy(appmgr_data.app_info_filter) != APP_MANAGER_ERROR_NONE) 
   {
      // Error handling
   }

   appmgr_data.app_info_filter = NULL;

   _clear_application_list();

   return true;
}

View Manager Module

The base GUI is created from the Tizen IDE template for developing UI applications with EDC. It consists of a window, a conformant, and an EDC layout. The layout has 2 parts:

  • swallow: Takes up all the layout space where the application genlist is inserted.
  • text: Placed at the center where the "No applications" string is displayed if the application list is empty.

To create the genlist:

  1. The genlist is created using the elm_genlist_add() function. For the genlist to be displayed properly, a genlist item class has to be created and defined with the elm_genlist_item_class_new() function. The following code snippet demonstrates how to set the item class properties. The full style means that the whole area of a genlist item is an icon (elm.swallow.content). A custom item layout is inserted as each item's content. Apart from the item style, a content_get callback function is also defined. It is called when an item is appended to the genlist and contains the item layout creation.

    Evas_Object *genlist = elm_genlist_add(viewdata.win);
    
    // Error handling
    
    viewdata.item_class = elm_genlist_item_class_new();
    
    // Error handling
    
    viewdata.item_class->item_style = "full";
    viewdata.item_class->func.text_get = NULL;
    viewdata.item_class->func.content_get = __get_item_content;
    viewdata.item_class->func.state_get = NULL;
    viewdata.item_class->func.del = NULL;
    
  2. The genlist is filled using the view_display_application_list() function. To append items to the genlist, the elm_genlist_item_append() function is invoked for each Eina_List item.

    EINA_LIST_FOREACH(app_list, it, item)
       elm_genlist_item_append(viewdata.genlist, viewdata.item_class, (void *)item, NULL, ELM_GENLIST_ITEM_NONE, NULL, NULL);
    
  3. The application's app_item_t structure containing its ID and icon path is passed as the data argument to the appending function. It is later passed on to the previously defined callback function. The following example shows the content_get callback function. Application data is retrieved from the parameter and used to create the item layout.

    static Evas_Object *
    __get_item_content(void *data, Evas_Object *obj, const char *part)
    {
       // Error handling
    
       app_item_t *item = (app_item_t *)data;
    
       return __create_item_layout(obj, item->app_id, item->icon_path);
    }
    
  4. The item layout consists of a background, an icon, and a text part. The application ID is copied to the text part and its icon path is used to create an icon. To enable swiping an item left or right to terminate the application, the draggable block is used, and the item can be dragged around the interface. The following example shows how to define the draggable block. Note that it only has to be included in the background description, as the other parts' positions are relative to it and remain confined to it.

    part 
    {
       name: ITEM_PART_BASE;
       type: RECT;
       scale: 1;
       description 
       {
          state: "default" 0.0;
          color: 0 0 0 0;
       }
    
       draggable 
       {
          x: 1 1 2;
          y: 0 0 0;
       }
    }
    

    There are 2 lines in the draggable block: x and y, which define the movement in horizontal and vertical axes, respectively. The first argument in each line defines whether dragging along this axis is enabled (1 or -1) or disabled (0). In this example, dragging is possible only in the x axis. The second and third arguments define the step of the movement.

To detect user interaction, a callback for the mouse_up event is set for each item layout. There are 3 actions to perform, and to distinguish which action is performed, the drag value is obtained using the edje_object_part_drag_value_get() function that defines how much the object has been dragged. It takes the object's edje object as a parameter, and it needs to be acquired from the layout first using the elm_layout_edje_get() function. You also need to pass as a parameter the name of the part whose drag you want to measure. The actions are:

  • Tap the item

    A tap gesture is detected when the drag value equals 0. When it happens, the coordinates of the Evas_Event_Mouse_Up event are used to retrieve the item using the elm_genlist_at_xy_item_get() function. The item data is acquired from it using the elm_object_item_data_get() function, after which the application ID is passed to the application_mgr_resume_app() function to resume the given application.

  • Swipe it left or right to the edge of the screen

    In this application, a swipe gesture occurs when the absolute value of the drag value is greater than ITEM_DRAG_OUTSIDE_VAL. When this happens, a signal is emitted to the item layout to hide its content. The genlist item at the Evas_Event_Mouse_Up event coordinates is retrieved using the elm_genlist_at_xy_item_get() function. The acquired pointer is used to delete the item with the elm_object_item_del() function. After it is deleted, the genlist item count is checked: if it equals 0, there are no running applications left, and the view_display_no_applications() function has to be called to update the view.

  • Move the item left or right, but not far enough to indicate the swipe gesture
static void
__item_layout_mouse_up_cb(void *data, Evas *e, Evas_Object *obj, void *event_info)
{
   // Variable declaration and initialization

   edje = elm_layout_edje_get(obj);
    edje_object_part_drag_value_get(edje, ITEM_PART_BASE, &dx, NULL);

   if (dx == 0) 
   {
      // Item was not dragged left/right - item was clicked, resume application
      genlist_item = elm_genlist_at_xy_item_get(viewdata.genlist, mouse_up_ev->canvas.x, mouse_up_ev->canvas.y, NULL);
      // Error handling

      app_item_t *item = (app_item_t *)elm_object_item_data_get(genlist_item);
      // Error handling

      application_mgr_resume_app(item->app_id);

   } 
   else if (dx < ITEM_DRAG_OUTSIDE_VAL && dx > -ITEM_DRAG_OUTSIDE_VAL) 
   {
      // Item was dragged, but not far enough to terminate application
      elm_layout_signal_emit(obj, ITEM_PROGRAM_RESET_POSITION_SIGNAL, ITEM_PROGRAM_RESET_POSITION_SOURCE);
   } 
   else 
   {
      // Item was dragged to left/right edge of the screen - terminate application
      elm_layout_signal_emit(obj, ITEM_PROGRAM_HIDE_SIGNAL, ITEM_PROGRAM_HIDE_SOURCE);

      genlist_item = elm_genlist_at_xy_item_get(viewdata.genlist, mouse_up_ev->canvas.x, mouse_up_ev->canvas.y, NULL);
      // Error handling

      __delete_item(genlist_item);

      if (elm_genlist_items_count(viewdata.genlist) == 0) 
         view_display_no_applications();

   }
}