Mobile native Wearable native

Data Control: Exchanging Specific Data Between Applications

This tutorial demonstrates how you can get, set, add, and remove map data, and insert, select, update, and delete SQL data.

Warm-up

Become familiar with the Data Control API basics by learning about:

Initializing Data Controls

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

#include <data_control.h>

#include <sqlite3.h>
#include <stdlib.h>
#include <glib.h>
#include <string.h>

To execute this application, the <sqlite3.h>, <stdlib.h>, <glib.h>, and <string.h> header files have to be included too.

This data control use cases run 2 applications. Each application plays a different role: one for the consumer, the other for the provider. For the consumer application, the http://tizen.org/privilege/datasharing and http://tizen.org/privilege/appmanager.launch privileges must be added. For the provider application, in the IDE, go to tizen-manifest.xml > Advanced > Data Control > Add (Read, Write SQL and Read, Write Map) access rights.

Working with Map-type Data Controls

To get, add, remove, and set map-type data using the Data Control API:

  1. Implement the provider application.

    The provider application stores and provides data to the consumer application.

    The provider application has 4 operations: get, add, remove, and set. To use the map-type Data Control API, these 4 operation callbacks must be implemented.

    typedef struct map_data
    {
       char **str_arr;
       int arr_size;
    } map_data_s;
    
    static GHashTable *map_repository_test;
    void get_value_request_cb(int request_id, data_control_h provider, const char *key, void *user_data)
    {
       map_data_s* map_data = (map_data_s*)g_hash_table_lookup(map_repository_test, key);
    
       int ret_value_count = 0;
       char **val_arr = NULL;
       if (map_data != NULL)
       {
          val_arr = map_data->str_arr;
          ret_value_count = map_data->arr_size;
       }
    
       int ret = data_control_provider_send_map_get_value_result(request_id, val_arr, ret_value_count);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "send_map_get_result failed with error: %d", ret);
       }
       else
       {
          dlog_print(DLOG_INFO, LOG_TAG, "Get value success request_id : %d", request_id);
       }
    }
    
    void set_value_request_cb(int request_id, data_control_h provider, const char *key, const char *old_value, const char *new_value, void *user_data)
    {
       map_data_s* map_data = (map_data_s*)g_hash_table_lookup(map_repository_test, key);
       if (map_data != NULL)
       {
          for (int i = 0; i<map_data->arr_size; i++)
          {
             if (strcmp(map_data->str_arr[i], old_value) == 0)
             {
                map_data->str_arr[i] = g_strdup(new_value);
             }
          }
       }
    
       int ret = data_control_provider_send_map_result(request_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "send_map_result failed with error: %d", ret);
       }
       else
       {
          dlog_print(DLOG_INFO, LOG_TAG, "Set value success request_id : %d", request_id);
       }
    }
    
    void add_value_request_cb(int request_id, data_control_h provider, const char *key, const char *value, void *user_data)
    {
       map_data_s* map_data = (map_data_s*)g_hash_table_lookup(map_repository_test, key);
    
       if (map_data == NULL)
       {
          map_data = (map_data_s*)(g_malloc(sizeof(*map_data)));
          map_data->arr_size = 0;
          map_data->str_arr = (char**) calloc(1, sizeof(char*));
          map_data->str_arr[0] = g_strdup(value);
          g_hash_table_insert(map_repository_test, g_strdup(key), map_data);
    
       }
       else
       {
          char **new_arr = (char**) calloc(map_data->arr_size+2, sizeof(char*));
          for (int i=0; i<map_data->arr_size; i++)
          {
             new_arr[i] = g_strdup(map_data->str_arr[i]);
          }
          free(map_data->str_arr);
          new_arr[map_data->arr_size] = g_strdup(value);
          map_data->str_arr = g_strdupv(new_arr);
          free(new_arr);
       }
       map_data->arr_size+=1;
    
       int ret = data_control_provider_send_map_result(request_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "send_map_result failed with error: %d", ret);
       }
       else
       {
          dlog_print(DLOG_INFO, LOG_TAG, "Add value success request_id : %d %d %s", request_id, map_data->arr_size, map_data->str_arr[0]);
       }
    }
    
    void remove_value_request_cb(int request_id, data_control_h provider, const char *key, const char *value, void *user_data)
    {
       map_data_s* map_data = (map_data_s*)g_hash_table_lookup(map_repository_test, key);
    
       if (map_data != NULL)
       {
          int size = map_data->arr_size;
          for (int i = 0; i<size ;i++)
          {
             if (strcmp(map_data->str_arr[i], value) == 0)
             {
                free(map_data->str_arr[i]);
                map_data->arr_size--;
             }
          }
          if (map_data->arr_size == 0)
          {
             if (!g_hash_table_remove(map_repository_test, key))
             {
                dlog_print(DLOG_ERROR, LOG_TAG, "remove value fail -%s", key);
    
                return;
             }
          }
       }
    
       int ret = data_control_provider_send_map_result(request_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "send_map_result failed with error: %d", ret);
       }
       else
       {
          dlog_print(DLOG_INFO, LOG_TAG, "Remove value Success");
       }
    }
    

    Register the callback within the app_create(void *data) function using the data_control_provider_map_register_cb() function:

    void __free_key(gpointer data)
    {
       if (data)
       {
          g_free(data);
          data = NULL;
          dlog_print(DLOG_INFO, LOG_TAG, "Remove key");
       }
    }
    
    void __free_data(gpointer data)
    {
       if (data)
       {
          g_free(data);
          data = NULL;
          dlog_print(DLOG_INFO, LOG_TAG, "Remove value");
       }
    }
    
    data_control_provider_map_cb map_callback;
    void initialize_datacontrol_provider()
    {
       map_repository_test = g_hash_table_new_full(g_str_hash, g_str_equal, __free_key, __free_data);
    
       map_callback.get_cb = get_value_request_cb;
       map_callback.add_cb = add_value_request_cb;
       map_callback.remove_cb = remove_value_request_cb;
       map_callback.set_cb = set_value_request_cb;
    
       int result = data_control_provider_map_register_cb(&map_callback);
       if (result != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "data_control_provider_map_register_cb failed with error: %d", result);
       }
       else 
       {
          dlog_print(DLOG_INFO, LOG_TAG, "Provider map register success");
       }
    }	
    
  2. Implement the consumer application.

    The consumer application requests get, set, add, and remove functions to the provider application and receives the results from the provider application.

    Implement the response callback. The response callback receives the request result and data from the provider.

    // Callback functions 
    void map_get_response_cb(int request_id, data_control_h provider,
                             char **ret_value_list, int ret_value_count, bool provider_ret, 
                             const char *error, void *user_data)
    {
       if (provider_ret)
       {
    
          dlog_print(DLOG_INFO, LOG_TAG, "The get operation is successful. value count : %d ", ret_value_count);
          for (int i = 0; i<ret_value_count; i++)
             dlog_print(DLOG_INFO, LOG_TAG, "(%d) Return value : %s ", i , ret_value_list[i]);
    
       }
       else
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "The get operation for the request %d is failed. error message: %s", request_id, error);
       }
    }
    
    void map_set_response_cb(int request_id, data_control_h provider, bool provider_ret, const char *error, void *user_data)
    {
       if (provider_ret)
       {
          dlog_print(DLOG_INFO, LOG_TAG, "The set operation is successful");
       }
       else
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "The set operation for the request %d is failed. error message: %s", request_id, error);
       }
    }
    
    void map_add_response_cb(int request_id, data_control_h provider, bool provider_ret, const char *error, void *user_data)
    {
       if (provider_ret)
       {
          dlog_print(DLOG_INFO, LOG_TAG, "The add operation is successful");
       }
       else
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "The add operation for the request %d is failed. error message: %s", request_id, error);
       }
    }
    
    void map_remove_response_cb(int request_id, data_control_h provider, bool provider_ret, const char *error, void *user_data)
    {
       if (provider_ret)
       {
          dlog_print(DLOG_INFO, LOG_TAG, "The remove operation is successful");
       }
       else
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "The remove operation for the request %d is failed. error message: %s", request_id, error);
       }
    }
    

    To identify the provider and data, initialize a data control handler. The initializing process has to be performed within the app_create(void *data) function generated by the IDE.

    To grant access to the provider ID, go to the provider application tizen-manifest.xml > Advanced > Data Control.

    data_control_map_response_cb map_callback;
    void initialize_datacontrol_consumer(appdata_s *ad)
    {
       const char *provider_id = Your Provider ID;
       const char *data_id = "table";
       int ret;
    
       // Create data control handler
       ret = data_control_map_create(&(ad->provider_h));
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "creating data control provider is failed with error: %d", ret);
       }
       ret = data_control_map_set_provider_id(ad->provider_h, provider_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "setting provider id is failed with error: %d", ret);
       }
       ret = data_control_map_set_data_id(ad->provider_h, data_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "setting data id is failed with error: %d", ret);
       }
    
       // Set response callback
       map_callback.get_cb = map_get_response_cb;
       map_callback.set_cb = map_set_response_cb;
       map_callback.add_cb = map_add_response_cb;
       map_callback.remove_cb = map_remove_response_cb;
    
       // Register response callback
       ret = data_control_map_register_response_cb(ad->provider_h, &map_callback, NULL);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "Registering the callback function is failed with error: %d", ret);
    
          if (ret == DATA_CONTROL_ERROR_IO_ERROR) 
          {
             dlog_print(DLOG_ERROR, LOG_TAG, "I/O error");
          }
          else 
          {
             dlog_print(DLOG_ERROR, LOG_TAG, "Out of memory");
          }
       }
    
       int req_id = 0;
    
       // Add value
       const char *key = "key";
       const char *value = "value";
       data_control_map_add(provider_map, key, value, &req_id);
     
       // Get value
       data_control_map_get(provider_map, key, &req_id);
    
       // Set value
       const char *old_value = "old value";
       const char *new_value = "new value";
       data_control_map_set(provider_map, key, old_value, new_value, &req_id);
       
       // Remove value
       data_control_map_remove(provider_map, key, value, &req_id);
    }
    

Working with SQL-type Data Controls

To insert, select, update, and delete SQL-type data using the Data Control API:

  1. Implement the provider application.

    The provider application stores and provides data to the consumer application.

    The provider application has 4 operations: insert, select, update, and delete. To use the SQL-type Data Control API, these operation callbacks have to be implemented.

    data_control_provider_sql_cb *sql_callback;
    static sqlite3* db;
    void insert_request_cb(int request_id, data_control_h provider, bundle *insert_data, void *user_data)
    {
       char* command = data_control_provider_create_insert_statement(provider, insert_data);
       int ret = sqlite3_exec(db, command, NULL, NULL, NULL);
    
       if (ret != SQLITE_OK)
       {
          data_control_provider_send_error(request_id, sqlite3_errmsg(db));
          free(command);
    
          return;
       }
       dlog_print(DLOG_INFO, LOG_TAG, "[insert_request_cb] insert success");
    
       long long inserted_row_id = sqlite3_last_insert_rowid(db);
       ret = data_control_provider_send_insert_result(request_id, inserted_row_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "insert_send_result failed with error: %d", ret);
       }
       dlog_print(DLOG_INFO, LOG_TAG, "[insert_request_cb] send result success");
    
       free(command);
    }
    
    void delete_request_cb(int request_id, data_control_h provider, const char *where, void *user_data)
    {
       dlog_print(DLOG_INFO, LOG_TAG, "[delete_request_cb] request_id(%d)", request_id);
       char* command = data_control_provider_create_delete_statement(provider, where);
       int ret = sqlite3_exec(db, command, NULL, NULL, NULL);
       if (ret != SQLITE_OK)
       {
          data_control_provider_send_error(request_id, sqlite3_errmsg(db));
          free(command);
    
          return;
       }	
    
       ret = data_control_provider_send_delete_result(request_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "delete_send_result failed with error: %d", ret);
       }
       dlog_print(DLOG_INFO, LOG_TAG, "[delete_request_cb] delete success");
    
       free(command);
    }
    
    void select_request_cb(int request_id, data_control_h provider, const char **column_list, 
                           int column_count, const char *where, const char *order, void *user_data)
    {
       sqlite3_stmt* sql_stmt = NULL;
    
       char* command = data_control_provider_create_select_statement(provider, column_list, 
                                                                     column_count, where, order);
       int ret = sqlite3_prepare_v2(db, command, strlen(command), &sql_stmt, NULL);
       if (ret != SQLITE_OK)
       {
          data_control_provider_send_error(request_id, sqlite3_errmsg(db));
          free(command);
    
          return;
       }	
    
       ret = data_control_provider_send_select_result(request_id, (void *)sql_stmt);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "select_send_result failed with error: %d", ret);
       }
       dlog_print(DLOG_INFO, LOG_TAG, "[select_request_cb] send result success");
    
       sqlite3_finalize(sql_stmt);
       free(command);
    }
    
    void update_request_cb(int request_id, data_control_h provider, bundle *update_data, const char *where, void *user_data)
    {
       char* command = data_control_provider_create_update_statement(provider, update_data, where);
       int ret = sqlite3_exec(db, command, NULL, NULL, NULL);
       if (ret != SQLITE_OK)
       {
          data_control_provider_send_error(request_id, sqlite3_errmsg(db));
          free(command);
    
          return;
       }
    
       ret = data_control_provider_send_update_result(request_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "update_send_result failed with error: %d", ret);
       }
       dlog_print(DLOG_INFO, LOG_TAG, "[update_request_cb] send result success");
    
       free(command);
    }
    

    Register the callback and create the database:

    int create_database()
    {
       dlog_print(DLOG_INFO, LOG_TAG,  "%s%s", app_get_data_path(), "test.db");
    
       int open_flags = (SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE);
    
       int ret = sqlite3_open_v2(Your DB Path , &db, open_flags, NULL);
       if (ret != SQLITE_OK)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "database creation failed with error: %d", ret);
    
          return ret;
       }
    
       char* sql_command = "CREATE TABLE IF NOT EXISTS Dictionary (WORD VARCHAR(30) , WORD_DESC TEXT, WORD_NUM INT, Point INT)";
       ret = sqlite3_exec(db, sql_command, NULL, NULL, NULL);
       if (ret != SQLITE_OK)
       {
          dlog_print(DLOG_ERROR, LOG_TAG,"database table creation failed with error: %d", ret);
       }
       dlog_print(DLOG_INFO, LOG_TAG,"DB init Success.");
    
       return ret;
    }
    
    void initialize_datacontrol_provider()
    {
       dlog_print(DLOG_INFO, LOG_TAG, "initialize_datacontrol_provider ");
    
       int result = create_database();
       if (result != SQLITE_OK)
          return;
    
       sql_callback = 
    (data_control_provider_sql_cb *) malloc(sizeof(data_control_provider_sql_cb));
       sql_callback->select_cb = select_request_cb;
       sql_callback->insert_cb = insert_request_cb;
       sql_callback->delete_cb = delete_request_cb;
       sql_callback->update_cb = update_request_cb;
       result = data_control_provider_sql_register_cb(sql_callback, NULL);
       if (result != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, "data_control_sql_response_c failed with error: %d", result);
       }
       else 
       {
          dlog_print(DLOG_INFO, LOG_TAG, "Provider SQL register success");
       }
    }		
    
  2. Implement the consumer application.

    The consumer application requests the insert, select, update, and delete functions to the provider application and receives the result from the provider application.

    Implement the response callback. The response callback receives the request result and data from the provider.

    void sql_delete_response_cb(int request_id, data_control_h provider, bool provider_result, const char *error, void *user_data)
    {
       if (provider_result)
       {
          dlog_print(DLOG_INFO, LOG_TAG, "The delete operation is successful");
       }
       else
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "The delete operation for the request %d is failed. error message: %s", request_id, error);
       }
    }
    
    void sql_insert_response_cb(int request_id, data_control_h provider, long long inserted_row_id, 
                                bool provider_result, const char *error, void *user_data)
    {
       if (provider_result)
       {
          dlog_print(DLOG_INFO, LOG_TAG, "The insert operation is successful");
       }
       else
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "The insert operation for the request %d is failed. error message: %s", request_id, error);
       }
    }
    
    void sql_select_response_cb(int request_id, data_control_h provider, result_set_cursor cursor, 
                                bool provider_result, const char *error, void *user_data)
    {
       if (provider_result)
       {
          dlog_print(DLOG_INFO, LOG_TAG, "The select operation is successful");
       }
       else
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "The select operation for the request %d is failed. error message: %s", request_id, error);
       }
    
       while (data_control_sql_step_next(cursor) == DATA_CONTROL_ERROR_NONE) 
       {
    
          char word[32] = {0,};
          char word_desc[32] = {0,};
          long long word_number = -1;
    
          data_control_sql_get_text_data(cursor, 0, word);
          data_control_sql_get_text_data(cursor, 1, word_desc);
          data_control_sql_get_int64_data(cursor, 2, &word_number);
    
          dlog_print(DLOG_INFO, LOG_TAG, "Word : %s, Word DESC : %s, Word NUM : %ld ", word, word_desc, word_number);
       }
    }
    
    void sql_update_response_cb(int request_id, data_control_h provider, bool provider_result, const char *error, void *user_data)
    {
       if (provider_result)
       {
          dlog_print(DLOG_INFO, LOG_TAG, "The update operation is successful");
       }
       else
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "The update operation for the request %d is failed. error message: %s", request_id, error);
       }
    }
    

    To identify the provider and data, initialize a data control handler. The initializing process has to be performed within the app_create(void *data) function generated by the IDE.

    To grant access to the provider ID, go to the provider application tizen-manifest.xml > Advanced > Data Control.

    data_control_sql_response_cb sql_callback;
    void initialize_datacontrol_consumer(appdata_s *ad)
    {
       int ret;
    
       const char *provider_id = Your Provider ID;
       const char *data_id = "Dictionary";
    
       ret = data_control_sql_create(&(ad->provider_h));
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "creating data control provider is failed with error: %d", ret);
       }
    
       ret = data_control_sql_set_provider_id(ad->provider_h, provider_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "setting provider id is failed with error: %d", ret);
       }
    
       ret = data_control_sql_set_data_id(ad->provider_h, data_id);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "setting data id is failed with error: %d", ret);
       }
    
       sql_callback.delete_cb = sql_delete_response_cb;
       sql_callback.insert_cb = sql_insert_response_cb;
       sql_callback.select_cb = sql_select_response_cb;
       sql_callback.update_cb = sql_update_response_cb;
    
       ret = data_control_sql_register_response_cb(ad->provider_h, &sql_callback, NULL);
       if (ret != DATA_CONTROL_ERROR_NONE)
       {
          dlog_print(DLOG_ERROR, LOG_TAG, "Registering the callback function is failed with error: %d", ret);
       }
    
       dlog_print(DLOG_INFO, LOG_TAG, "Init data control success");
    
       int req_id = 0; 
       
       // Insert row
       bundle *b = bundle_create();
       bundle_add_str(b, "WORD", "'test'");
       bundle_add_str(b, "WORD_DESC", "'test desc'");
    
       data_control_sql_insert(provider_sql, b, &req_id);
    
       // Select row
       char *column_list[2];
       column_list[0] = "WORD";
       column_list[1] = "WORD_DESC";
       
       const char *where = "WORD = 'test'";
       const char *order = "WORD ASC";
    
       data_control_sql_select(provider_sql, column_list, 2, where, order, &req_id);
    
       // Select row
       bundle_add_str(b, "WORD", "'test_new'");
       data_control_sql_update(provider_sql, b, where, &req_id);
    
       // Delete row
       const char *where_delete = "WORD = 'test'";
       result = data_control_sql_delete(provider_sql, where_delete, &req_id);
    
       // Free memory
       bundle_free(b);
    }
    
    static bool
    app_create(void *data)
    {
       // Take necessary actions before main event loop starts
       // Initialize UI resources and application data
       // If this function returns true, the main loop of application starts
       // If this function returns false, the application is terminated 
       appdata_s *ad = data;
    
       create_base_gui(ad);
       initialize_datacontrol_consumer(ad);
    
       return true;
    }
    
Go to top