Mobile native Wearable native

Application: Using Alarms, Preferences, AppControl, and Other Fundamentals

This tutorial demonstrates how you can manage application fundamentals, such as application settings and service applications.

Warm-up

Become familiar with the Application API basics by learning about:

Handling the Application Fundamentals

The Application API is the framework all Tizen applications are based on. It is simple and only handles interactions between applications and the operating system.

An application starts with the main() function. It initializes the Application API and starts it.

The code below is the minimal application using the Application API. It only builds and runs.

// Add this include to be able to use the functions from the Application API
#include <app.h>

int
main(int argc, char *argv[])
{
   // Create a ui_app_lifecycle_callback_s object and initialize its contents to 0
   ui_app_lifecycle_callback_s event_callback = {0,};

   // Run the application
   return ui_app_main(&argc, &argv, &event_callback, NULL);
}

The Application API has 2 classes of application state callbacks: those about the application's life-cycle and those about the system.

The application's life-cycle callbacks are:

  • create: first initialization, comes after ui_app_main() has been called and initializes UI.
  • control: triggered when the application is started to do something. It can be called several times during the lifespan of an application, it shows the screen for the action requested. It requires specific information given to the callback.
  • terminate: saves work, releases resources, and exits.
  • pause: sets the application's window not visible and switches to a mode which uses less resources.
  • resume: sets the application's window to be visible again.

The system-related callbacks can be handled with the app_event_cb() callback:

  • APP_EVENT_LOW_MEMORY: Event type responsible for saving data in the main memory to a persistent memory or storage to avoid data loss in case the Tizen platform Low Memory Killer kills your application to get more free memory. The event is also used to release any cached data in the main memory to secure more free memory.
  • APP_EVENT_LOW_BATTERY: Event type responsible for saving data in the main memory to a persistent memory or storage to avoid data loss in case the power goes off completely. The event is also used to stop heavy CPU consumption or power consumption activities to save the remaining power.
  • APP_EVENT_DEVICE_ORIENTATION_CHANGED: Event type responsible for changing the display orientation to match the device orientation.
  • APP_EVENT_LANGUAGE_CHANGED: Event type responsible for refreshing the display into the new language.
  • APP_EVENT_REGION_FORMAT_CHANGED: Event type responsible for refreshing the display into the new time zone.

A basic implementation is shown below:

#include <app.h>

// Structure to store the data for application's logic; it is given
// to each callback invoked through the Application API
typedef struct appdata 
{
   char *several;
   char *fields;
} appdata_s;

static bool
app_create(void *data)
{
   // Hook to take necessary actions before main event loop starts; this
   // usually means initializing UI and application's data (the "data"
   // parameter to this function)

   appdata_s *ad = data;
   create_gui(ad);

   // If this function returns true, the main loop of application starts
   // If this function returns false, the application is terminated
   return true;
}

static void
app_control(app_control_h app_control, void *data)
{
   // Handles the launch request, show the user the task requested through the
   // "app_control" parameter (detailed in the next section)
}

static void
app_pause(void *data)
{
   // Takes necessary actions when application becomes invisible
}

static void
app_resume(void *data)
{
   // Takes necessary actions when application becomes visible
}

static void
app_terminate(void *data)
{
   // Releases all resources
   appdata_s *ad = data;

   if (!ad) 
   {
      return;
   }

   // If specific steps are needed:
   // destroy_gui(ad);
}

int
main(int argc, char *argv[])
{
   appdata_s ad = {0,};
   ui_app_lifecycle_callback_s event_callback = {0,};

   // Sets the callbacks for the application's logic; explanation on the
   // implementation below
   event_callback.create = app_create;
   event_callback.terminate = app_terminate;
   event_callback.pause = app_pause;
   event_callback.resume = app_resume;
   event_callback.app_control = app_control;

   // Note the &ad below; this is how the struct is given to callbacks
   return ui_app_main(argc, argv, &event_callback, &ad);
}

The last section of this tutorial describes app control. It is a mechanism through which an application receives additional information about why it was started and with which parameters.

An application receives a handle to an app control object in the app_control callback. A definition for that callback is:

app_control_cb(app_control_h app_control, void *user_data);

The app_control_h type is opaque and information can only be extracted from it through functions from the SDK.

The most interesting ones are:

  • app_control_get_operation(): retrieves a string describing which operation the application was started for.
  • app_control_get_mime(): retrieves the MIME type of the data (e.g. image/jpg).
  • app_control_get_app_extra_data(): gets the string value associated with the given key.
  • app_control_get_app_extra_data_array(): gets the string array associated with the given key (first check with app_control_is_extra_data_array() whether the data associated with a key is an array).

If other functions are needed, check the app.h header.

Running Applications Using Extra Data

To run a specified app_control with some preconfigured parameters:

  1. To use the functions and data types of the App Control API (in mobile and wearable applications), include the <app.h> header file in your application:

    #include <app.h>
    
  2. Prepare app_control.

    In this example, the app_control launches an application which has the APP_CONTROL_OPERATION_VIEW operation and image/jpeg mime type with a message.

    When the app_control is created, set the operation. The operation is mandatory information for the launch request. If the operation is not specified, APP_CONTROL_OPERATION_DEFAULT is used for the launch request. Add extra data to the app_control using the app_control_add_extra_data() or app_control_add_extra_data_array() function.

    error_code = app_control_create(&app_control);
    
    ret = app_control_create(&app);
    if (ret != APP_CONTROL_ERROR_NONE)
       dlog_print(DLOG_ERROR, LOG_TAG, "app_control_create() is failed. err = %d", ret);
    
    ret = app_control_set_operation(app, APP_CONTROL_OPERATION_VIEW);
    if (ret != APP_CONTROL_ERROR_NONE)
       dlog_print(DLOG_ERROR, LOG_TAG, "app_control_set_operation() is failed. err = %d", ret);
    
    ret = app_control_set_mime(app, "image/jpeg");
    if (ret != APP_CONTROL_ERROR_NONE)
       dlog_print(DLOG_ERROR, LOG_TAG, "app_control_set_mime() is failed. err = %d", ret);
    
    ret = app_control_add_extra_data(app, Your Message Key, message);
    if (ret != APP_CONTROL_ERROR_NONE)
       dlog_print(DLOG_ERROR, LOG_TAG, "app_control_add_extra_data() is failed. err = %d", ret);
    

    The following table lists the available base application services.

    Table: Tizen base application services
    Service Operation Scheme MIME
    Browsing a Web page http://tizen.org/appcontrol/operation/view
    • http
    • https
    -
    Displaying an image
    • file
    • http
    • https
    • image/bmp
    • image/gif
    • image/jpeg
    • image/png
    Playing a sound file file
    • audio/aac
    • audio/amr
    • audio/mp3
    • audio/wav
    Playing a video file
    • video/mp4
    • video/3gpp
    Selecting a file http://tizen.org/appcontrol/operation/pick
    • */*
    • image/*
    • video/*
    • audio/*
  3. Launch app_control.

    After preparing app_control, launch it using the app_control_send_launch_request() function:

    ret = app_control_send_launch_request(app, NULL, NULL);
    if (ret != APP_CONTROL_ERROR_NONE)
       dlog_print(DLOG_ERROR, LOG_TAG, "app_control_send_launch_request() is failed. err = %d", ret);
    
  4. Get extra data.

    Read the extra data set to app_control using the app_control_foreach_extra_data() function. The same function used on app_control_h returned by the app_control reply allows you to read the reply message.

    bool _app_control_extra_data_cb(app_control_h app_control, const char *key, void *user_data)
    {
       int ret;
       char *value;
       
       ret = app_control_get_extra_data(app, key, &value);
       if (ret != APP_CONTROL_ERROR_NONE) 
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "app_control_get_extra_data() is failed. err = %d", ret);
       }
       dlog_print(DLOG_DEBUG, LOG_TAG, "[value] %s", value);
    
       return true;
    }
    
    ret = app_control_foreach_extra_data(app, _app_control_extra_data_cb, 0);
    if (ret != APP_CONTROL_ERROR_NONE)
       dlog_print(DLOG_ERROR, LOG_TAG, "app_control_foreach_extra_data() is failed. err = %d", ret);
    
  5. Clean up.

    When your work with app_control is finished, clean up. To do this, pass the app_control handle to the app_control_destroy() function.

    ret = app_control_destroy(app);
    if (ret != APP_CONTROL_ERROR_NONE)
       dlog_print(DLOG_ERROR, LOG_TAG, "app_control_destroy() is failed. err = %d", ret);
    

Initializing Alarms

To initialize the alarm:

  1. To use the functions and data types of the Alarm API (in mobile and wearable applications), include the <app.h> header file in your application:
    #include <app.h>
    #include <app_alarm.h>
    
  2. The http://tizen.org/privilege/alarm.get and http://tizen.org/privilege/alarm.set privileges are required for the Alarm API.

Setting an Alarm after Specific Time

To set an alarm after a specific time:

  1. Implement the AlarmRegister application

    AlarmRegister requires the http://tizen.org/privilege/alarm.set privilege.

    1. To identify which application to alarm, the Alarm API needs app_control_h.

      Obtain app_control_h of a specific app by calling app_control_set_app_id(app_control_h app_control, const char *app_id);. You can get AlarmTarget app_id from the tizen-manifest.xml file.

      bool init_alarm()
      {
         int ret;
         int DELAY = 2;
         int REMIND = 1;
         int alarm_id;
      
         app_control_h app_control = NULL;
         ret = app_control_create(&app_control);
         ret = app_control_set_operation(app_control, APP_CONTROL_OPERATION_DEFAULT);
         ret = app_control_set_app_id (app_control, "org.tizen.alarmslave");
      
    2. To schedule an alarm after a delay, the function requires 4 parameters:

      • [in] app_control: The destination app_control to perform the specific work when the alarm is triggered
      • [in] delay: The amount of time before the first execution (in seconds)
      • [in] period: The amount of time before a subsequent alarm (in seconds). If set to 0, there is only 1 execution.
      • [out] alarm_id The alarm ID that uniquely identifies an alarm
         ret = alarm_schedule_after_delay(app_control, DELAY, REMIND, &alarm_id);
      
         return true;
      }
      
  2. Implement the AlarmTarget application

    A scheduled alarm calls AlarmTarget' app_control_cb callback when the alarm expires.

    void service_app_control(app_control_h app_control, void *data)
    {
       dlog_print(DLOG_INFO, LOG_TAG, "app_control called by Alarm API.");
    }
    

Setting an Alarm on a Specific Date

To schedule an alarm on a specific date, the function requires 4 parameters:

  • [in] app_control: The destination app_control to perform the specific work when the alarm is triggered
  • [in] date: The first active alarm time
  • [in] period: The amount of time before a subsequent alarm (in seconds). If set to 0, there is only 1 execution.
  • [out] alarm_id: The alarm ID that uniquely identifies an alarm

The tm struct is included in the <time.h> header file. The following table lists the selected tm fields.

Table: tm fields
Member Type Meaning Range
tm_sec int Seconds after the minute 0-61*
tm_min int Minutes after the hour 0-59
tm_hour int Hours since midnight 0-23
tm_mday int Day of the month 1-31
tm_mon int Months since January 0-11
tm_year int Years since 1900
int alarm_schedule_at_date(app_control_h app_control, struct tm* date, int period, int* alarm_id)

The following code schedules app_control to invoke after 4 seconds. Modifying, for example, date.tm_mday, sets the alarm to another day of the month.

struct tm date;
ret = alarm_get_current_time(&date);

date.tm_sec+=4;
ret = alarm_schedule_at_date(app, &date, 0, &alarm_id);	

Setting a Recurring Alarm at a Specific Time of the Day

To schedule an alarm on a specific time of the day with a recurrence, use the alarm_schedule_with_recurrence_week_flag() function, which requires 4 parameters:

  • [in] app_control: The destination app_control that performs the specific work when the alarm is triggered.
  • [in] date: The date on which the alarm is triggered for the first time.
  • [in] week_flag: The day of the week on which the alarm recurs. The value is defined with the enum alarm_week_flag_e enumerator (in mobile and wearable applications), and can be a combination of days, for example ALARM_WEEK_FLAG_TUESDAY | ALARM_WEEK_FLAG_FRIDAY. The value can also be a binary, such as 1<<3 | 1<<6.
  • [out] alarm_id: The unique ID that identifies the alarm.

The following code schedules app_control to invoke on TUESDAY and FRIDAY.

struct tm date;
ret = alarm_get_current_time(&date);

time_t time_current = mktime(&date);
dlog_print(DLOG_INFO, TAG, "Schedule on date: %s ", ctime(&time_current));
ret = alarm_schedule_with_recurrence_week_flag(app_control, &date, ALARM_WEEK_FLAG_TUESDAY | ALARM_WEEK_FLAG_FRIDAY, &alarm_id);

Listing All Scheduled Alarms and Canceling an Alarm

To list all scheduled alarms, use the following function:

int alarm_foreach_registered_alarm(alarm_registered_alarm_cb callback, void* user_data)

To list a scheduled alarm, the function requires 2 parameters:

  • [in] callback: The callback function to invoke.
  • [in] user_data: The user data to be passed to the callback.

To cancel specific scheduled alarms, use the following function:

int alarm_cancel(int alarm_id)

To cancel a scheduled alarm, the function requires 1 parameter:

  • [in] alarm_id: The alarm ID that is cancelled.

The following code implements the alarm_registered_alarm_cb() function. This callback lists all registered alarms and alarm recurrence days. At the end of the function, the alarm_cancel() function is called to cancel every scheduled alarm.

static bool on_foreach_registered_alarm(int alarm_id, void *user_data)
{
   int flag;
   int ret = 0;
   struct tm date;
   time_t time_current;

   ret = alarm_get_scheduled_date(alarm_id, &date);
   if (ret != ALARM_ERROR_NONE)
   {
      dlog_print(DLOG_ERROR, TAG, "Get time Error : %d ", ret);
   }
   
   // Logging scheduled alarm's info
   time_current = mktime(&date);
   dlog_print(DLOG_INFO, TAG, "Registered alarm:%d on date:%s ", alarm_id, ctime(&time_current));

   ret = alarm_get_scheduled_recurrence_week_flag(alarm_id, &flag);
   if (ret==0)
   {
      if (flag & ALARM_WEEK_FLAG_SUNDAY)
         dlog_print(DLOG_INFO, TAG, "Alarm Recurrence on SUNDAY \n");
      if (flag & ALARM_WEEK_FLAG_MONDAY)
         dlog_print(DLOG_INFO, TAG, "Alarm Recurrence on MONDAY \n");
      if (flag & ALARM_WEEK_FLAG_TUESDAY)
         dlog_print(DLOG_INFO, TAG, "Alarm Recurrence on TUESDAY \n");
      if (flag & ALARM_WEEK_FLAG_WEDNESDAY)
         dlog_print(DLOG_INFO, TAG, "Alarm Recurrence on WEDNESDAY \n");
      if (flag & ALARM_WEEK_FLAG_THURSDAY)
         dlog_print(DLOG_INFO, TAG, "Alarm Recurrence on THURSDAY \n");
      if (flag & ALARM_WEEK_FLAG_FRIDAY)
         dlog_print(DLOG_INFO, TAG, "Alarm Recurrence on FRIDAY \n");
      if (flag & ALARM_WEEK_FLAG_SATURDAY)
         dlog_print(DLOG_INFO, TAG, "Alarm Recurrence on SATURDAY \n");
   }

   // Cancel scheduled alarms
   ret = alarm_cancel (alarm_id);
   if (ret != ALARM_ERROR_NONE) 
   {
      dlog_print(DLOG_ERROR, TAG, "Cancel Error : %d ", ret);
   }

   return true;
}
ret = alarm_foreach_registered_alarm(on_foreach_registered_alarm, NULL);
if (ret != ALARM_ERROR_NONE) 
{
      dlog_print(DLOG_ERROR, TAG, "Listing Error : %d ", ret);
}

Managing Application Preferences

You can set and get application preference data. Any stored preference data can also be shared with among the applications in the same package.

To manage preferences:

  1. To use the functions and data types of the Preference API (in mobile and wearable applications), include the <app.h> header file in your application:

    #include <app.h>
    #include <app_preference.h>
    
  2. Store and retrieve simple type variables.

    To store a variable, you must create a key-value pair. Use the following functions to create a key-value pair for a specific simple type:

    • preference_set_int (const char *key, int value)
    • preference_set_double (const char *key, double value)
    • preference_set_boolean (const char *key, bool value)

    Before storing or retrieving a variable, check whether it exists using:

    • preference_is_existing (const char *key, bool *existing)

    Use the following functions to retrieve a stored variable of a given simple type:

    • preference_get_int (const char *key, int *value)
    • preference_get_double (const char *key, double *value)
    • preference_get_boolean (const char *key, bool *value)
    const char *integer_key = "integer_key";
    int integer_value = 1;
    int integer_output;
    
    preference_set_int(integer_key, integer_value);
    
    preference_is_existing(integer_key, &existing);
    
    preference_get_int(integer_key, &integer_output);
  3. Store and retrieve string variables.

    Use the following functions to store and retrieve string variables:

    • preference_set_string (const char *key, const char *value)
    • preference_get_string (const char *key, char **value)

    Release the value returned by the get function using the free() function.

    const char *string_key = "string_key";
    const char *string_value = "Sample content";
    char *string_output;
    bool existing;
    
    preference_set_string(string_key, string_value);
    
    preference_is_existing(string_key, &existing);
    
    preference_get_string(string_key, &string_output);
    
    free(string_output);
  4. Track variables.

    You can set a different callback function to each variable. The callback function is invoked each time the variable is changed.

    int previous_value;
    
    preference_set_changed_cb(integer_key, preference_changed_cb_impl, &previous_value);

    Pass custom parameters to the callback function in the user_data field.

    void preference_changed_cb_impl(const char *key, void *user_data)
    {
       int ret = 0;
       int integer_output = 0;
    
       dlog_print(DLOG_DEBUG, LOG_TAG, "[preference_changed_cb_impl]\n");
       preference_get_int(key, &integer_output);
         
       dlog_print(DLOG_DEBUG, LOG_TAG, "Key: %s has changed its value to %d \n", 
                  key, integer_output);
    }

    Unset a callback function based on a variable key.

    preference_unset_changed_cb(const char *key);
  5. List all records.

    Access all the records with the foreach function. The function calls a specific callback function for each key-value pair in the database. You can pass additional data to the function in the user_data field.

    preference_foreach_item(preference_foreach_item_cb, NULL);

    If the callback function returns false, or if all the records have been opened, the foreach function ends.

    bool preference_foreach_item_cb(const char *key, void *user_data)
    {
       dlog_print(DLOG_DEBUG, LOG_TAG, "[preference_foreach_item_cb]\n");
       dlog_print(DLOG_DEBUG, LOG_TAG, "Key found: %s\n", key);
       return true;
    }
  6. Delete records.

    Delete records one by one using a unique key. You can also delete all records for an application using the remove_all() function.

    preference_remove(const char *key)
    
    preference_remove_all(void)
Go to top