Published on 25th of October 2017
Settings Saving. App Preference Module

In this lesson, we will consider the necessity to save small sets of simple data between application restarts, by using the App Preference module.

Using App Preference you may save information about the currently selected watch application style, so when changing the watch app and return it back, the application will be loaded with the style, which was set during the last session.

Module Description

So, as it was already mentioned, this module is mainly used to save application settings (a small set of simple data). In general, if necessary, you can store any simple data.

Thus, if you have several variables, values of which you want to save till the next application launch, there is no need at first open the file for storing these values there, and then open and read them. Using databases is not rational as well. All these options, requires implementing some functionality, and as a result spending additional time on it. Using the App Preference, you simply call the function to save the value, or the function to load a value. What can be easier? The value is stored in the operating system with reference to the package name of your application, registered in the manifest file, and the key that you specify for storing the variable. For example, if in your package, there are a service application and a ui application, then you can access same data from both of them. Another advantage is a possibility to create handlers for events of changing the variable, which are stored with the specified key.

Saving the Selected Style

Now knowing what App Preferences is, let's use this module and save the current watch app style between the application restarts.

To use the interface of this module, include the following header file:

#include <app_preference.h>

In the watch application, the index of the current style stores in the form of an ordinary int value. Let's create a function to save this value in the system:

#define KEY_STYLE_INDEX "key.style.index"
static void
style_index_save(int style_index)
{
   preference_set_int(KEY_STYLE_INDEX, style_index);
}

As you can see, there was defined the key "key.style.index" to store the value of the style index.

There are four functions for storing values of different types:

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

In this example was used a function to store an integer value.

As you can see, there is no need to open the file or initialize the database, and then write the value in it; instead you should just call one function that does all the dirty work for you.

Now implement the function to load the style index from the system:

static int
style_index_load()
{
   int style_index = 0;
   bool is_existing = false;

   preference_is_existing(KEY_STYLE_INDEX, &is_existing);
   if (is_existing)
     preference_get_int(KEY_STYLE_INDEX, &style_index);

   return style_index;
}

As well there are 4 functions for loading different types of values:

preference_get_boolean(const char *key, bool *value);
preference_get_int(const char *key, int *value);
preference_get_double(const char *key, double *value);
preference_get_string(const char *key, char **value);

There may be a situation that you call function for loading the value, but it has not been stored yet, in this case nothing will be written to the variable, you passed for writing the result, and its value will remain the same. But if you still need to know if there is some value for the specified key, use following function:

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

To make this issue more clear, we’ve showed how to use it in the style loading function. So, if the value with the given key does not exist, a load is not performed, and the function will return the index of the first style. It's time to use these functions.

Save style index each time it was changed. For this, to the text click handler add the call for saving the index:

static void
down_cb(void *data, Evas *evas, Evas_Object *obj, void *event)
{
   ...

   int styles_count = EINA_C_ARRAY_LENGTH(styles);
   ui->style_index = (ui->style_index + 1) % styles_count;
   style_index_save(ui->style_index);

   ...
}

Now during application creation, add the load of the saved style. Before creating the window and all graphic components add the following line:

static bool
_app_create(int width, int height, void *data)
{
   UIData *ui = data;
   ui->style_index = style_index_load();

   ...
}

Let's see how it works in the application.

As you can see, when you reload the watch application, the chosen style is saved due to the fact that you used the App Preference.

Additional Module Functions

Sometimes there is a need to get a notification that the value, stored in the App Preference has changed, you just need to use the following function and implement your own handler.

preference_set_changed_cb(const char *key, preference_changed_cb callback,void *user_data);

In this function, there were passed: the key that stores the value of the change you want to monitor, the handler function, and the user data that will come to the handler.

Important:

If at the time of registration, the data with the specified key does not exist yet, the function will be ineffectual and the handler will not be called even if the data with given key appears further. Therefore, it is recommended before registering the handler, check whether the data with the specified key exists or not and if not, save a certain zero value with the function preference_set_int() or with any other similar function.

To remove a handler, call the following function:

preference_unset_changed_cb(const char *key);

Important:

You can set the handler to change the value only for one handler for each key. So, 2 handlers for one key can not be registered, since, when the function is called for a second time, the last registered handlers will be used.

Sometimes there may be a need to erase data using the key. For this use the following function:

preference_remove(const char *key);

Also it is possible to erase all key-value pairs by calling next function:

preference_remove_all();

So application # 5 is completed. Project with the source code is available here WearLesson030.

Leave a Reply

Your email address will not be published. Required fields are marked *