1# Cross-Device Synchronization of RDB Stores 2 3 4## When to Use 5 6When creating a data table, you can set the table to support cross-device access. You can also use APIs to move the data to be accessed across devices to a distributed data. 7 8 9## Basic Concepts 10 11OpenHamony supports synchronization of the relational data of an application across multiple devices. 12 13- Distributed table list<br>After a table is created for an application in an RDB store, you can set it as a distributed table. When querying the RDB store of a remote device, you can obtain the distributed table name of the remote device based on the local table name. 14 15- Synchronization mode<br>Data can be synchronized between devices in either of the following ways: <br>- Pushing data from a local device to a remote device. <br>- Pulling data from a remote device to a local device. 16 17 18## Working Principles 19 20After completing device discovery and authentication, the underlying communication component notifies the application that the device goes online. The **DatamgrService** then establishes an encrypted transmission channel to synchronize data between the two devices. 21 22 23### Cross-Device Data Synchronization Mechanism 24 25![relationalStore_sync](figures/relationalStore_sync.jpg) 26 27After writing data to an RDB store, the service sends a synchronization request to the **DatamgrService**. 28 29The **DatamgrService** reads the data to be synchronized from the application sandbox and sends the data to the **DatamgrService** of the target device based on the **deviceId** of the peer device. Then, the **DatamgrService** writes the data to the RDB of the same application. 30 31 32### Data Change Notification Mechanism 33 34When data is added, deleted, or modified, a notification is sent to the subscriber. The notifications can be classified into the following types: 35 36- Local data change notification: subscription of the application data changes on the local device. When the data in the local KV store is added, deleted, or modified in the database, a notification is received. 37 38- Distributed data change notification: subscription of the application data changes of other devices in the network. When the data in the local RDB store changes after being synchronized with data from another device in the same network, a notification is received. 39 40 41## Constraints 42 43- A maximum of 16 distributed RDB stores can be opened simultaneously for an application. 44 45- Each RDB store supports a maximum of eight callbacks for subscription of data change notifications. 46 47- Third-party applications cannot call the distributed APIs that must be specified with the device. 48 49 50## Available APIs 51 52The following table lists the APIs for cross-device data synchronization of RDB stores. Most of the APIs are executed asynchronously, using a callback or promise to return the result. The following table uses the callback-based APIs as an example. For more information about the APIs, see [RDB Store](../reference/apis/js-apis-data-relationalStore.md). 53 54| API| Description| 55| -------- | -------- | 56| setDistributedTables(tables: Array<string>, callback: AsyncCallback<void>): void | Sets the distributed tables to be synchronized.| 57| sync(mode: SyncMode, predicates: RdbPredicates, callback: AsyncCallback<Array<[string, number]>>): void | Synchronizes data across devices.| 58| on(event: 'dataChange', type: SubscribeType, observer: Callback<Array<string>>): void | Subscribes to changes in the distributed data.| 59| off(event:'dataChange', type: SubscribeType, observer: Callback<Array<string>>): void | Unsubscribe from changes in the distributed data.| 60| obtainDistributedTableName(device: string, table: string, callback: AsyncCallback<string>): void; | Obtains the table name on the specified device based on the local table name.| 61| remoteQuery(device: string, table: string, predicates: RdbPredicates, columns: Array<string> , callback: AsyncCallback<ResultSet>): void | Queries data from the RDB store of a remote device based on specified conditions.| 62 63 64## How to Develop 65 66> **NOTE** 67> 68> The data on a device can be synchronized only to the devices whose data security labels are not higher than the security level of the device. For details, see [Access Control Mechanism in Cross-Device Synchronization](sync-app-data-across-devices-overview.md#access-control-mechanism-in-cross-device-synchronization). 69 701. Import the module. 71 72 ```js 73 import relationalStore from '@ohos.data.relationalStore'; 74 ``` 75 762. Request permissions. 77 78 1. Request the **ohos.permission.DISTRIBUTED_DATASYNC** permission. For details, see [Declaring Permissions in the Configuration File](../security/accesstoken-guidelines.md#declaring-permissions-in-the-configuration-file). 79 2. Display a dialog box to ask authorization from the user when the application is started for the first time. For details, see [Requesting User Authorization](../security/accesstoken-guidelines.md#requesting-user-authorization). 80 813. Create an RDB store and set a table for distributed synchronization. 82 83 ```js 84 const STORE_CONFIG = { 85 name: 'RdbTest.db', // Database file name. 86 securityLevel: relationalStore.SecurityLevel.S1 // Database security level. 87 }; 88 relationalStore.getRdbStore(this.context, STORE_CONFIG, (err, store) => { 89 store.executeSql('CREATE TABLE IF NOT EXISTS EMPLOYEE (ID INTEGER PRIMARY KEY AUTOINCREMENT, NAME TEXT NOT NULL, AGE INTEGER, SALARY REAL, CODES BLOB)', null, (err) => { 90 // Set the table for distributed synchronization. 91 store.setDistributedTables(['EMPLOYEE']); 92 // Perform related operations. 93 }) 94 }) 95 ``` 96 974. Synchronize data across devices. After **sync()** is called to trigger a synchronization, data is synchronized from the local device to all other devices on the network. 98 99 ```js 100 // Construct the predicate object for synchronizing the distributed table. 101 let predicates = new relationalStore.RdbPredicates('EMPLOYEE'); 102 // Call sync() to synchronize data. 103 store.sync(relationalStore.SyncMode.SYNC_MODE_PUSH, predicates, (err, result) => { 104 // Check whether data synchronization is successful. 105 if (err) { 106 console.error(`Failed to sync data. Code:${err.code},message:${err.message}`); 107 return; 108 } 109 console.info('Succeeded in syncing data.'); 110 for (let i = 0; i < result.length; i++) { 111 console.info(`device:${result[i][0]},status:${result[i][1]}`); 112 } 113 }) 114 ``` 115 1165. Subscribe to changes in the distributed data. The data synchronization triggers the **observer** callback registered in **on()**. The input parameter of the callback is the ID of the device whose data changes. 117 118 ```js 119 let observer = function storeObserver(devices) { 120 for (let i = 0; i < devices.length; i++) { 121 console.info(`The data of device:${devices[i]} has been changed.`); 122 } 123 } 124 125 try { 126 // Register an observer to listen for the changes of the distributed data. 127 // When data in the RDB store changes, the registered callback will be invoked to return the data changes. 128 store.on('dataChange', relationalStore.SubscribeType.SUBSCRIBE_TYPE_REMOTE, observer); 129 } catch (err) { 130 console.error('Failed to register observer. Code:${err.code},message:${err.message}'); 131 } 132 133 // You can unsubscribe from the data changes if required. 134 try { 135 store.off('dataChange', relationalStore.SubscribeType.SUBSCRIBE_TYPE_REMOTE, observer); 136 } catch (err) { 137 console.error('Failed to register observer. Code:${err.code},message:${err.message}'); 138 } 139 ``` 140 1416. Query data across devices. If data synchronization is not complete or triggered, an application can call **remoteQuery()** to query data from a remote device. 142 143 > **NOTE** 144 > 145 > **deviceIds** is obtained by using [devManager.getTrustedDeviceListSync](../reference/apis/js-apis-device-manager.md#gettrusteddevicelistsync). The APIs of the **deviceManager** module are all system interfaces and available only to system applications. 146 147 148 ```js 149 // Obtain device IDs. 150 import deviceManager from '@ohos.distributedHardware.deviceManager'; 151 152 deviceManager.createDeviceManager("com.example.appdatamgrverify", (err, manager) => { 153 if (err) { 154 console.info(`Failed to create device manager. Code:${err.code},message:${err.message}`); 155 return; 156 } 157 let devices = manager.getTrustedDeviceListSync(); 158 let deviceId = devices[0].deviceId; 159 160 // Construct a predicate object for querying the distributed table. 161 let predicates = new relationalStore.RdbPredicates('EMPLOYEE'); 162 // Query data from the specified remote device and return the query result. 163 store.remoteQuery(deviceId, 'EMPLOYEE', predicates, ['ID', 'NAME', 'AGE', 'SALARY', 'CODES'], 164 function (err, resultSet) { 165 if (err) { 166 console.error(`Failed to remoteQuery data. Code:${err.code},message:${err.message}`); 167 return; 168 } 169 console.info(`ResultSet column names: ${resultSet.columnNames}, column count: ${resultSet.columnCount}`); 170 } 171 ) 172 }) 173 ``` 174