1# Persisting User Preference Data (C/C++) 2 3## When to Use 4Use the **Preferences** module to store small amounts of data in key-value (KV) format. The data is stored in files and memory for fast access. If a large amount of data needs to be stored, consider using a KV store or RDB store. 5 6## Constraints 7- Prior to API version 18: ArkTS APIs support only the XML storage format, and C APIs support only the GSKV storage format. Due to incompatible formats, ArkTS and C APIs cannot operate the same **Preferences** instance. 8- API version 18 and later: Both ArkTS and C APIs support the XML and GSKV storage formats. ArkTS and C APIs can operate the same **Preferences** instance if they use the same format. 9- The maximum key length is 1024 bytes, and the maximum value length is 16 MB. 10 11 12## Available APIs 13 14For details about the APIs, see [Preferences](../reference/apis-arkdata/capi-preferences.md). 15 16| API| Description| 17| -------- | -------- | 18| OH_Preferences \* OH_Preferences_Open (OH_PreferencesOption \*option, int \*errCode) | Opens a **Preferences** instance and creates a pointer to it. If the pointer is no longer required, use **OH_Preferences_Close** to close the instance.| 19| int OH_Preferences_Close (OH_Preferences \*preference) | Closes a **Preferences** instance.| 20| int OH_Preferences_GetInt (OH_Preferences \*preference, const char \*key, int \*value) | Obtains an integer corresponding to the specified key in a **Preferences** instance.| 21| int OH_Preferences_GetBool (OH_Preferences \*preference, const char \*key, bool \*value) | Obtains a Boolean value corresponding to the specified key in a **Preferences** instance.| 22| int OH_Preferences_GetString (OH_Preferences \*preference, const char \*key, char \*\*value, uint32_t \*valueLen) | Obtains a string corresponding to the specified key in a **Preferences** instance.| 23| void OH_Preferences_FreeString (char \*string) | Releases a string.| 24| int OH_Preferences_SetInt (OH_Preferences \*preference, const char \*key, int value) | Sets an integer based on the specified key in a **Preferences** instance.| 25| int OH_Preferences_SetBool (OH_Preferences \*preference, const char \*key, bool value) | Sets a Boolean value based on the specified key in a **Preferences** instance.| 26| int OH_Preferences_SetString (OH_Preferences \*preference, const char \*key, const char \*value) | Sets a string based on the specified key in a **Preferences** instance.| 27| int OH_Preferences_Delete (OH_Preferences \*preference, const char \*key) | Deletes the KV data corresponding to the specified key from a **Preferences** instance.| 28| int OH_Preferences_RegisterDataObserver (OH_Preferences \*preference, void \*context, OH_PreferencesDataObserver observer, const char \*keys[], uint32_t keyCount) | Subscribes to data changes of the specified keys. If the value of the specified key changes, a callback will be invoked after **OH_Preferences_Close()** is called.| 29| int OH_Preferences_UnregisterDataObserver (OH_Preferences \*preference, void \*context, OH_PreferencesDataObserver observer, const char \*keys[], uint32_t keyCount) | Unsubscribes from data changes of the specified keys.| 30| int OH_Preferences_IsStorageTypeSupported (Preferences_StorageType type, bool \*isSupported) | Checks whether the specified storage type is supported.| 31| OH_PreferencesOption \* OH_PreferencesOption_Create (void) | Creates an **OH_PreferencesOption** instance and a pointer to it. If this pointer is no longer required, use **OH_PreferencesOption_Destroy** to destroy it. Otherwise, memory leaks may occur.| 32| int OH_PreferencesOption_SetFileName (OH_PreferencesOption \*option, const char \*fileName) | Sets the file name for an **OH_PreferencesOption** instance. The file name cannot contain a slash (/) or exceed 255 bytes.| 33| int OH_PreferencesOption_SetBundleName (OH_PreferencesOption \*option, const char \*bundleName) | Sets the bundle name for an OH_PreferencesOption instance.| 34| int OH_PreferencesOption_SetDataGroupId (OH_PreferencesOption \*option, const char \*dataGroupId) | Sets the application group ID for an **OH_PreferencesOption** instance.| 35| int OH_PreferencesOption_SetStorageType (OH_PreferencesOption \*option, Preferences_StorageType type) | Sets the storage type for an **OH_PreferencesOption** instance.| 36| int OH_PreferencesOption_Destroy (OH_PreferencesOption \*option) | Destroys an **OH_PreferencesOption** instance.| 37| const char \* OH_PreferencesPair_GetKey (const OH_PreferencesPair \*pairs, uint32_t index) | Obtains the key based on the specified index from the KV data.| 38| const OH_PreferencesValue \* OH_PreferencesPair_GetPreferencesValue (const OH_PreferencesPair \*pairs, uint32_t index) | Obtains the value based on the specified index from the KV pairs.| 39| Preference_ValueType OH_PreferencesValue_GetValueType (const OH_PreferencesValue \*object) | Obtains the data type of a **PreferencesValue** instance.| 40| int OH_PreferencesValue_GetInt (const OH_PreferencesValue \*object, int \*value) | Obtains an integer value from an **OH_PreferencesValue** instance.| 41| int OH_PreferencesValue_GetBool (const OH_PreferencesValue \*object, bool \*value) | Obtains a Boolean value from an **OH_PreferencesValue** instance.| 42| int OH_PreferencesValue_GetString (const OH_PreferencesValue \*object, char \*\*value, uint32_t \*valueLen) | Obtains a string from an **OH_PreferencesValue** instance.| 43 44 45## Adding Dynamic Link Libraries 46 47Add the following library to **CMakeLists.txt**. 48 49```txt 50libohpreferences.so 51``` 52 53## Including Header Files 54 55```c 56#include <cstring> 57#include <database/preferences/oh_preferences.h> 58#include <database/preferences/oh_preferences_err_code.h> 59#include <database/preferences/oh_preferences_option.h> 60#include <database/preferences/oh_preferences_value.h> 61``` 62 63## How to Develop 64The following example shows how to use **Preferences** APIs to modify and persist KV data. 651. Create a **PreferencesOption** instance and set the name, application group ID, bundle name, and storage type. If the **PreferencesOption** object is no longer required, call **OH_PreferencesOption_Destroy** to destroy it. 662. Call **OH_Preferences_Open** to open a **Preferences** instance. When the **Preferences** instance is not required, call **OH_Preferences_Close** to close it. 673. Call **OH_Preferences_RegisterDataObserver** to register a **DataChangeObserverCallback** callback to observe data changes of three keys. 684. Set KV data in the **Preferences** instance. 695. Obtain data in the **Preferences** instance. 706. Call **OH_Preferences_Close** to close the **Preferences** instance and set the instance pointer to null. 71 72```c 73// Callback used to return data changes. 74void DataChangeObserverCallback(void *context, const OH_PreferencesPair *pairs, uint32_t count) { 75 for (uint32_t i = 0; i < count; i++) { 76 // Obtain the value corresponding to index i. 77 const OH_PreferencesValue *pValue = OH_PreferencesPair_GetPreferencesValue(pairs, i); 78 // Obtain the data type of a value. 79 Preference_ValueType type = OH_PreferencesValue_GetValueType(pValue); 80 int ret = PREFERENCES_OK; 81 if (type == PREFERENCE_TYPE_INT) { 82 int intValue = 0; 83 ret = OH_PreferencesValue_GetInt(pValue, &intValue); 84 if (ret == PREFERENCES_OK) { 85 // Service logic. 86 } 87 } else if (type == PREFERENCE_TYPE_BOOL) { 88 bool boolValue = true; 89 ret = OH_PreferencesValue_GetBool(pValue, &boolValue); 90 if (ret == PREFERENCES_OK) { 91 // Service logic. 92 } 93 } else if (type == PREFERENCE_TYPE_STRING) { 94 char *stringValue = nullptr; 95 uint32_t valueLen = 0; 96 ret = OH_PreferencesValue_GetString(pValue, &stringValue, &valueLen); 97 if (ret == PREFERENCES_OK) { 98 // Service logic. 99 OH_Preferences_FreeString(stringValue); 100 } 101 } else { 102 // Invalid type. 103 } 104 } 105} 106 107// 1. Create a PreferencesOption instance. 108OH_PreferencesOption *option = OH_PreferencesOption_Create(); 109if (option == nullptr) { 110 // Error handling. 111} 112// Set the file name. 113int ret = OH_PreferencesOption_SetFileName(option, "testdb"); 114if (ret != PREFERENCES_OK) { 115 (void)OH_PreferencesOption_Destroy(option); 116 // Error handling. 117} 118// Set the application group ID. 119ret = OH_PreferencesOption_SetDataGroupId(option, ""); 120if (ret != PREFERENCES_OK) { 121 (void)OH_PreferencesOption_Destroy(option); 122 // Error handling. 123} 124// Set the bundle name. 125ret = OH_PreferencesOption_SetBundleName(option, "com.example"); 126if (ret != PREFERENCES_OK) { 127 (void)OH_PreferencesOption_Destroy(option); 128 // Error handling. 129} 130 131// Set the storage type for the PreferencesOption instance. Before the setting, call OH_Preferences_IsStorageTypeSupported to check whether the storage type is supported. 132bool isGskvSupported = false; 133ret = OH_Preferences_IsStorageTypeSupported(Preferences_StorageType::PREFERENCES_STORAGE_GSKV, &isGskvSupported); 134if (ret != PREFERENCES_OK) { 135 (void)OH_PreferencesOption_Destroy(option); 136 // Error handling. 137} 138if (isGskvSupported) { 139 ret = OH_PreferencesOption_SetStorageType(option, Preferences_StorageType::PREFERENCES_STORAGE_GSKV); 140 if (ret != PREFERENCES_OK) { 141 (void)OH_PreferencesOption_Destroy(option); 142 // Error handling. 143 } 144} else { 145 ret = OH_PreferencesOption_SetStorageType(option, Preferences_StorageType::PREFERENCES_STORAGE_XML); 146 if (ret != PREFERENCES_OK) { 147 (void)OH_PreferencesOption_Destroy(option); 148 // Error handling. 149 } 150} 151 152// 2. Open a Preferences instance. 153int errCode = PREFERENCES_OK; 154OH_Preferences *preference = OH_Preferences_Open(option, &errCode); 155// Destroy the PreferencesOption instance that is no longer used, and set the instance pointer to null. 156(void)OH_PreferencesOption_Destroy(option); 157option = nullptr; 158if (preference == nullptr || errCode != PREFERENCES_OK) { 159 // Error handling. 160} 161 162// 3. Subscribe to data changes of key_int, key_bool, and key_string. 163const char *keys[] = {"key_int", "key_bool", "key_string"}; 164ret = OH_Preferences_RegisterDataObserver(preference, nullptr, DataChangeObserverCallback, keys, 3); 165if (ret != PREFERENCES_OK) { 166 (void)OH_Preferences_Close(preference); 167 // Error handling. 168} 169 170// 4. Set KV data in the Preferences instance. 171ret = OH_Preferences_SetInt(preference, keys[0], 0); 172if (ret != PREFERENCES_OK) { 173 (void)OH_Preferences_Close(preference); 174 // Error handling. 175} 176ret = OH_Preferences_SetBool(preference, keys[1], true); 177if (ret != PREFERENCES_OK) { 178 (void)OH_Preferences_Close(preference); 179 // Error handling. 180} 181ret = OH_Preferences_SetString(preference, keys[2], "string value"); 182if (ret != PREFERENCES_OK) { 183 (void)OH_Preferences_Close(preference); 184 // Error handling. 185} 186 187// 5. Obtain KV data from the Preferences instance. 188int intValue = 0; 189ret = OH_Preferences_GetInt(preference, keys[0], &intValue); 190if (ret == PREFERENCES_OK) { 191 // Service logic. 192} 193 194bool boolValue = false; 195ret = OH_Preferences_GetBool(preference, keys[1], &boolValue); 196if (ret == PREFERENCES_OK) { 197 // Service logic. 198} 199 200char *stringValue = nullptr; 201uint32_t valueLen = 0; 202ret = OH_Preferences_GetString(preference, keys[2], &stringValue, &valueLen); 203if (ret == PREFERENCES_OK) { 204 // Service logic. 205 // Release the string obtained by OH_Preferences_GetString. 206 OH_Preferences_FreeString(stringValue); 207 stringValue = nullptr; 208} 209 210// 6. Close the Preferences instance and set the pointer to null. 211(void)OH_Preferences_Close(preference); 212preference = nullptr; 213 214``` 215