Page Example

Context Trigger Sample Overview

Mobile native

The Context Trigger sample application demonstrates how you can manage contextual rules using the Contextual Trigger API. The application displays several rules in a genlist. You can tap each list item to start or stop the rule. When a rule is triggered, a notification is posted with an appropriate message.

The following figure illustrates the main view of the Context Trigger.

Figure: Context Trigger screen

Context Trigger screen

Prerequisites

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

  • To post a notification:
    • http://tizen.org/privilege/notification
  • To use the Important Call rule:
    • http://tizen.org/privilege/telephony
    • http://tizen.org/privilege/callhistory.read
  • To use The 5th-day-no-driving System rule:
    • http://tizen.org/privilege/alarm.set
  • To use the Home Wi-Fi rule:
    • http://tizen.org/privilege/location
    • http://tizen.org/privilege/network.get

Implementation

Rule Module

To initialize the rule module:

  1. Use the app_create() callback function to initialize the Context Trigger sample application. Register the contextual rules with the add_rules() function. The following example shows how to create a rule handle for a battery rule and to register the rule.

    void 
    add_rules(void)
    {
       // Add rules
       rule_info[RULE_BATTERY].id = add_battery_rule();
       rule_info[RULE_CALL].id = add_call_rule();
       rule_info[RULE_DRIVING].id = add_driving_rule();
       rule_info[RULE_HOME].id = add_home_rule();
    }
    
    static int 
    add_battery_rule(void)
    {
       int rule_id = 0;
       context_trigger_rule_h rule = NULL;
       context_trigger_rule_entry_h battery_e = NULL;
    
       bool battery_e_supported;
       context_trigger_rule_event_is_supported(CONTEXT_TRIGGER_EVENT_BATTERY, &battery_e_supported);
       if (!battery_e_supported) {
          rule_info[RULE_BATTERY].result = CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED;
          return rule_id;
       }
    
       context_trigger_rule_create(CONTEXT_TRIGGER_LOGICAL_CONJUNCTION, &rule);
       context_trigger_rule_set_description(rule, rule_info[RULE_BATTERY].description);
    
       context_trigger_rule_event_create(CONTEXT_TRIGGER_EVENT_BATTERY, CONTEXT_TRIGGER_LOGICAL_CONJUNCTION, &battery_e);
       context_trigger_rule_entry_add_key(battery_e, CONTEXT_TRIGGER_LOGICAL_DISJUNCTION, CONTEXT_TRIGGER_LEVEL);
       context_trigger_rule_entry_add_comparison_string(battery_e, CONTEXT_TRIGGER_LEVEL, CONTEXT_TRIGGER_EQUAL_TO, CONTEXT_TRIGGER_EMPTY);
       context_trigger_rule_entry_add_comparison_string(battery_e, CONTEXT_TRIGGER_LEVEL, CONTEXT_TRIGGER_EQUAL_TO, CONTEXT_TRIGGER_CRITICAL);
       context_trigger_rule_entry_add_comparison_string(battery_e, CONTEXT_TRIGGER_LEVEL, CONTEXT_TRIGGER_EQUAL_TO, CONTEXT_TRIGGER_LOW);
       context_trigger_rule_entry_add_key(battery_e, CONTEXT_TRIGGER_LOGICAL_CONJUNCTION, CONTEXT_TRIGGER_IS_CHARGING);
       context_trigger_rule_entry_add_comparison_int(battery_e, CONTEXT_TRIGGER_IS_CHARGING, CONTEXT_TRIGGER_EQUAL_TO, CONTEXT_TRIGGER_FALSE);
       context_trigger_rule_add_entry(rule, battery_e);
    
       context_trigger_rule_set_action_notification(rule, rule_info[RULE_BATTERY].name, rule_info[RULE_BATTERY].msg, NULL, NULL);
    
       rule_info[RULE_BATTERY].result = context_trigger_add_rule(rule, &rule_id);
       if (rule_info[RULE_BATTERY].result != CONTEXT_TRIGGER_ERROR_NONE)
          dlog_print(DLOG_ERROR, LOG_TAG, "Failed to add '%s' rule: %d", rule_info[RULE_BATTERY].name, rule_info[RULE_BATTERY].result);
    
       context_trigger_rule_entry_destroy(battery_e);
       context_trigger_rule_destroy(rule);
    
       return rule_id;
    }
    
  2. When the Context Trigger application is terminated, the app_terminate() callback function is called, and all registered rules are disabled and removed in the remove_rules() function. An enabled rule can be removed after being disabled.

    void 
    remove_rules(void)
    {
       // Get rules
       int enabled_rule_cnt = 0;
       int disabled_rule_cnt = 0;
       int *enabled_rule_ids = NULL;
       int *disabled_rule_ids = NULL;
       int error = context_trigger_get_own_rule_ids(&enabled_rule_ids, &enabled_rule_cnt, &disabled_rule_ids, &disabled_rule_cnt);
       if (error != CONTEXT_TRIGGER_ERROR_NONE) 
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "Failed to get rule ids");
    
          return;
       }
    
       // Disable and remove enabled rules
       int i;
       for (i = 0; i < enabled_rule_cnt; i++)
       {
          context_trigger_disable_rule(enabled_rule_ids[i]);
          context_trigger_remove_rule(enabled_rule_ids[i]);
       }
    
       // Remove disabled rules
       for (i = 0; i < disabled_rule_cnt; i++)
       {
          context_trigger_remove_rule(disabled_rule_ids[i]);
       }
    
       if (enabled_rule_ids) 
       {
          free(enabled_rule_ids);
          enabled_rule_ids = NULL;
       }
    
       if (disabled_rule_ids) 
       {
          free(disabled_rule_ids);
          disabled_rule_ids = NULL;
       }
    }
    

View Manager Module

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 text_get() and a content_get() callback functions are defined for creating the item text and layout.

    int index;
    Evas_Object *genlist;
    Elm_Genlist_Item_Class *itc_name, *itc;
    
    // Create item class
    itc = elm_genlist_item_class_new();
    itc->item_style = "multiline";
    itc->func.text_get = _gl_text_get_cb;
    itc->func.content_get = _gl_content_get_cb;
    
    // Genlist
    genlist = elm_genlist_add(parent);
    elm_genlist_mode_set(genlist, ELM_LIST_COMPRESS);
    evas_object_size_hint_weight_set(genlist, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
    evas_object_size_hint_align_set(genlist, EVAS_HINT_FILL, EVAS_HINT_FILL);
    
  2. The genlist is filled with rule items. To append items to the genlist, the elm_genlist_item_append() function is invoked for each Eina_List item.

    // For each rule
    for (index = RULE_FIRST; index < RULE_LAST; index++) 
    {
       // Rule item
       elm_genlist_item_append(genlist, itc, (void *)&rule_info[index], NULL, ELM_GENLIST_ITEM_NONE, _gl_selected_cb, NULL);
    }
    
  3. The application's rule_data structure contains its rule information, such as name and description. It is later passed on to the previously defined callback function. The following example shows the _gl_text_get_cb() and the _gl_content_get_cb() callback functions. The rule information is retrieved from the parameter and used to create the item layout.

    static char* 
    _gl_text_get_cb(void *data, Evas_Object * obj, const char *part)
    {
       rule_data_s *info = (rule_data_s *) data;
    
       if (!strcmp(part, "elm.text"))
          return strdup(info->name);
    
       else if (!strcmp(part, "elm.text.multiline"))
          return strdup(info->description);
    
       return NULL;
    }
    
    static Evas_Object*
    _gl_content_get_cb(void *data, Evas_Object * obj, const char *part)
    {
       rule_data_s *info = (rule_data_s *) data;
    
       if (!strcmp(part, "elm.swallow.end"))
       {
          Evas_Object *check = elm_check_add(obj);
    
          evas_object_smart_callback_add(check, "changed", _check_changed_cb, info);
          evas_object_propagate_events_set(check, EINA_FALSE);
    
          evas_object_size_hint_weight_set(check, EVAS_HINT_EXPAND, EVAS_HINT_EXPAND);
          evas_object_size_hint_align_set(check, EVAS_HINT_FILL, EVAS_HINT_FILL);
          elm_object_style_set(check, "on&off");
          elm_check_state_set(check, false);
          elm_check_state_pointer_set(check, &info->enabled);
    
          if (info->result != CONTEXT_TRIGGER_ERROR_NONE)
             elm_object_disabled_set(check, EINA_TRUE);
    
          return check;
       }
    
       return NULL;
    }
    
  4. When a genlist item or a check button is clicked, a corresponding rule is enabled or disabled. If the user taps a rule item which fails to be added, an error popup is shown to indicate the error reason.

    static void 
    _gl_selected_cb(void *data, Evas_Object * obj, void *event_info)
    {
       Elm_Object_Item *it = (Elm_Object_Item *) event_info;
       elm_genlist_item_selected_set(it, false);
    
       rule_data_s *info = elm_object_item_data_get(it);
    
       if (info->result == CONTEXT_TRIGGER_ERROR_NONE) 
       {
          int error = CONTEXT_TRIGGER_ERROR_NONE;
          Evas_Object *check = elm_object_item_part_content_get(it, "elm.swallow.end");
    
          if (elm_check_state_get(check)) 
          {
             error = disable_rule(info->id);
             if (error == CONTEXT_TRIGGER_ERROR_NONE)
                elm_check_state_set(check, !info->enabled);
          } 
          else 
          {
             error = enable_rule(info->id);
             if (error == CONTEXT_TRIGGER_ERROR_NONE)
                elm_check_state_set(check, !info->enabled);
          }
       } 
       else 
       {
          view_create_error_popup(data, info);
       }
    }
    
    static void 
    _check_changed_cb(void *data, Evas_Object * obj, void *event_info)
    {
       rule_data_s *info = (rule_data_s *) data;
       int error = CONTEXT_TRIGGER_ERROR_NONE;
    
       if (elm_check_state_get(obj)) 
       {
          error = enable_rule(info->id);
          if (error != CONTEXT_TRIGGER_ERROR_NONE)
             elm_check_state_set(obj, !info->enabled);
       } 
       else 
       {
          error = disable_rule(info->id);
          if (error != CONTEXT_TRIGGER_ERROR_NONE)
             elm_check_state_set(obj, !info->enabled);
       }
    }
    
    static void 
    view_create_error_popup(void *data)
    {
       rule_data_s *info = (rule_data_s *) data;
    
       char *err_msg = NULL;
    
       switch (info->result) 
       {
          case CONTEXT_TRIGGER_ERROR_PERMISSION_DENIED:
             err_msg = ERR_MSG_PERMISSION_DENIED;
             break;
          case CONTEXT_TRIGGER_ERROR_NOT_SUPPORTED:
             err_msg = ERR_MSG_NOT_SUPPORTED;
             break;
          case CONTEXT_TRIGGER_ERROR_INVALID_RULE:
             err_msg = ERR_MSG_INVALID_RULE;
             break;
          default:
             err_msg = ERR_MSG_DEFAULT;
             break;
       }
    
       Evas_Object *popup = elm_popup_add(s_info.win);
       elm_popup_align_set(popup, ELM_NOTIFY_ALIGN_FILL, 1.0);
       eext_object_event_callback_add(popup, EEXT_CALLBACK_BACK, eext_popup_back_cb, NULL);
       elm_object_part_text_set(popup, "title,text", info->name);
    
       elm_object_text_set(popup, err_msg);
    
       Evas_Object *btn = elm_button_add(popup);
       elm_object_style_set(btn, "popup");
       elm_object_text_set(btn, "OK");
       elm_object_part_content_set(popup, "button1", btn);
       evas_object_smart_callback_add(btn, "clicked", popup_btn_clicked_cb, popup);
       evas_object_show(popup);
    }