1# Distributed Data Service Development 2 3## When to Use 4 5The Distributed Data Service (DDS) implements synchronization of application data across user devices. When data is added, deleted, or modified for an application on a device, the same application on another device can obtain the updated data. The DDS applies to the distributed gallery, messages, contacts, and file manager. 6 7 8## Available APIs 9 10For details about the APIs, see [Distributed KV Store](../reference/apis/js-apis-distributedKVStore.md). 11 12**Table 1** APIs provided by the DDS 13 14| API | Description | 15| ------------------------------------------------------------ | ------------------------------------------------------------ | 16| createKVManager(config: KVManagerConfig): KVManager | Creates a **KvManager** object for database management. | 17| getKVStore<T extends KVStore>(storeId: string, options: Options, callback: AsyncCallback<T>): void<br>getKVStore<T extends KVStore>(storeId: string, options: Options): Promise<T> | Creates and obtains a KV store.| 18| put(key: string, value: Uint8Array\|string\|number\|boolean, callback: AsyncCallback<void>): void<br>put(key: string, value: Uint8Array\|string\|number\|boolean): Promise<void> | Inserts and updates data. | 19| delete(key: string, callback: AsyncCallback<void>): void<br>delete(key: string): Promise<void> | Deletes data. | 20| get(key: string, callback: AsyncCallback<Uint8Array\|string\|boolean\|number>): void<br>get(key: string): Promise<Uint8Array\|string\|boolean\|number> | Obtains data. | 21| on(event: 'dataChange', type: SubscribeType, observer: Callback<ChangeNotification>): void<br>on(event: 'syncComplete', syncCallback: Callback<Array<[string,number]>>): void | Subscribes to data changes in the KV store. | 22| sync(deviceIdList: string[], mode: SyncMode, delayMs?: number): void | Triggers database synchronization in manual mode. | 23 24## How to Develop 25 26The following uses a single KV store as an example to describe the development procedure. 27 281. Import the distributed data module. 29 30 ```js 31 import distributedKVStore from '@ohos.data.distributedKVStore'; 32 ``` 33 342. Apply for the required permission if data synchronization is required. 35 36 Add the permission required (FA model) in the **config.json** file. The sample code is as follows: 37 38 ```json 39 { 40 "module": { 41 "reqPermissions": [ 42 { 43 "name": "ohos.permission.DISTRIBUTED_DATASYNC" 44 } 45 ] 46 } 47 } 48 ``` 49 50 For the apps based on the stage model, see [Declaring Permissions](../security/accesstoken-guidelines.md#stage-model). 51 52 This permission must also be granted by the user when the application is started for the first time. The sample code is as follows: 53 54 ```js 55 // FA model 56 import featureAbility from '@ohos.ability.featureAbility'; 57 58 function grantPermission() { 59 console.info('grantPermission'); 60 let context = featureAbility.getContext(); 61 context.requestPermissionsFromUser(['ohos.permission.DISTRIBUTED_DATASYNC'], 666).then((data) => { 62 console.info('success: ${data}'); 63 }).catch((error) => { 64 console.error('failed: ${error}'); 65 }) 66 } 67 68 grantPermission(); 69 70 // Stage model 71 import UIAbility from '@ohos.app.ability.UIAbility'; 72 73 let context = null; 74 75 class EntryAbility extends UIAbility { 76 onWindowStageCreate(windowStage) { 77 let context = this.context; 78 } 79 } 80 81 function grantPermission() { 82 let permissions = ['ohos.permission.DISTRIBUTED_DATASYNC']; 83 context.requestPermissionsFromUser(permissions).then((data) => { 84 console.log('success: ${data}'); 85 }).catch((error) => { 86 console.error('failed: ${error}'); 87 }); 88 } 89 90 grantPermission(); 91 ``` 92 933. Create a **KvManager** instance based on the specified **KvManagerConfig** object. 94 95 1. Create a **kvManagerConfig** object based on the application context. 96 2. Create a **KvManager** instance. 97 98 The sample code is as follows: 99 100 ```js 101 // Obtain the context of the FA model. 102 import featureAbility from '@ohos.ability.featureAbility'; 103 let context = featureAbility.getContext(); 104 105 // Obtain the context of the stage model. 106 import UIAbility from '@ohos.app.ability.UIAbility'; 107 let context = null; 108 class EntryAbility extends UIAbility { 109 onWindowStageCreate(windowStage){ 110 context = this.context; 111 } 112 } 113 114 let kvManager; 115 try { 116 const kvManagerConfig = { 117 bundleName: 'com.example.datamanagertest', 118 context:context, 119 } 120 kvManager = distributedKVStore.createKVManager(kvManagerConfig); 121 console.log("Created KVManager successfully"); 122 } catch (e) { 123 console.error(`Failed to create KVManager. Code is ${e.code}, message is ${e.message}`); 124 } 125 ``` 126 1274. Create and obtain a single KV store. 128 129 1. Declare the ID of the single KV store to create. 130 2. Create a single KV store. You are advised to disable automatic synchronization (`autoSync:false`) and call `sync` when a synchronization is required. 131 132 The sample code is as follows: 133 134 ```js 135 let kvStore; 136 try { 137 const options = { 138 createIfMissing: true, 139 encrypt: false, 140 backup: false, 141 autoSync: false, 142 kvStoreType: distributedKVStore.KVStoreType.SINGLE_VERSION, 143 securityLevel: distributedKVStore.SecurityLevel.S1 144 }; 145 kvManager.getKVStore('storeId', options, function (err, store) { 146 if (err) { 147 console.error(`Failed to get KVStore: code is ${err.code}, message is ${err.message}`); 148 return; 149 } 150 console.log('Obtained KVStore successfully'); 151 kvStore = store; 152 }); 153 } catch (e) { 154 console.error(`An unexpected error occurred. Code is ${e.code}, message is ${e.message}`); 155 } 156 ``` 157 158 > **NOTE**<br> 159 > 160 > For data synchronization between networked devices, you are advised to open the distributed KV store during application startup to obtain the database handle. With this database handle (`kvStore` in this example), you can perform operations, such as inserting data into the KV store, without creating the KV store repeatedly during the lifecycle of the handle. 161 1625. Subscribe to changes in the distributed data. 163 164 The following is the sample code for subscribing to the data changes of a single KV store: 165 166 ```js 167 try{ 168 kvStore.on('dataChange', distributedKVStore.SubscribeType.SUBSCRIBE_TYPE_ALL, function (data) { 169 console.log(`dataChange callback call data: ${data}`); 170 }); 171 }catch(e){ 172 console.error(`An unexpected error occured. Code is ${e.code}, message is ${e.message}`); 173 } 174 ``` 175 1766. Write data to the single KV store. 177 178 1. Construct the `Key` and `Value` to be written into the single KV store. 179 2. Write key-value pairs into the single KV store. 180 181 The following is the sample code for writing key-value pairs of the string type into the single KV store: 182 183 ```js 184 const KEY_TEST_STRING_ELEMENT = 'key_test_string'; 185 const VALUE_TEST_STRING_ELEMENT = 'value-test-string'; 186 try { 187 kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, function (err,data) { 188 if (err != undefined) { 189 console.error(`Failed to put data. Code is ${err.code}, message is ${err.message}`); 190 return; 191 } 192 console.log("Put data successfully"); 193 }); 194 }catch (e) { 195 console.error(`An unexpected error occurred. Code is ${e.code}, message is ${e.message}`); 196 } 197 ``` 198 1997. Query data in the single KV store. 200 201 1. Construct the `Key` to be queried from the single KV store. 202 2. Query data from the single KV store. 203 204 The following is the sample code for querying data of the string type from the single KV store: 205 206 ```js 207 const KEY_TEST_STRING_ELEMENT = 'key_test_string'; 208 const VALUE_TEST_STRING_ELEMENT = 'value-test-string'; 209 try { 210 kvStore.put(KEY_TEST_STRING_ELEMENT, VALUE_TEST_STRING_ELEMENT, function (err,data) { 211 if (err != undefined) { 212 console.error(`Failed to put data. Code is ${err.code}, message is ${err.message}`); 213 return; 214 } 215 console.log("Put data successfully"); 216 kvStore.get(KEY_TEST_STRING_ELEMENT, function (err,data) { 217 if (err != undefined) { 218 console.error(`Failed to obtain data. Code is ${err.code}, message is ${err.message}`); 219 return; 220 } 221 console.log(`Obtained data successfully:${data}`); 222 }); 223 }); 224 }catch (e) { 225 console.error(`Failed to obtain data. Code is ${e.code}, message is ${e.message}`); 226 } 227 ``` 228 2298. Synchronize data to other devices. 230 231 Select the devices in the same network and the synchronization mode to synchronize data. 232 233 > **NOTE**<br> 234 > 235 > The APIs of the `deviceManager` module are system interfaces. 236 237 The following is the example code for synchronizing data in a single KV store: 238 239 ```js 240 import deviceManager from '@ohos.distributedHardware.deviceManager'; 241 242 let devManager; 243 // Create deviceManager. 244 deviceManager.createDeviceManager('bundleName', (err, value) => { 245 if (!err) { 246 devManager = value; 247 // deviceIds is obtained by deviceManager by calling getTrustedDeviceListSync(). 248 let deviceIds = []; 249 if (devManager != null) { 250 var devices = devManager.getTrustedDeviceListSync(); 251 for (var i = 0; i < devices.length; i++) { 252 deviceIds[i] = devices[i].deviceId; 253 } 254 } 255 try{ 256 // 1000 indicates that the maximum delay is 1000 ms. 257 kvStore.sync(deviceIds, distributedKVStore.SyncMode.PUSH_ONLY, 1000); 258 } catch (e) { 259 console.error(`An unexpected error occurred. Code is ${e.code}, message is ${e.message}`); 260 } 261 } 262 }); 263 ``` 264