1# Silent Access via the DatamgrService 2 3 4## When to Use 5 6In a typical cross-application data access scenario, the data provider may be started multiple times. 7 8To minimize the startup times of the data provider and speed up data access, OpenHarmony provides the silent access feature, which allows access to the database without starting the data provider. 9 10In silent access, the DatamgrService accesses and modifies data without starting the data provider. 11 12The DatamgrService supports basic database access and data hosting only. If service processing is required, the service processing logic must be encapsulated into APIs for the data consumer to call. 13 14If the service is too complex, use [DataShareExtensionAbility](../reference/apis-arkdata/js-apis-application-dataShareExtensionAbility-sys.md) to start the data provider. 15 16 17## Working Principles 18 19The DatamgrService can serve as a proxy to access the following data: 20 21- Persistent data: data in the database of the data provider. It is stored in the sandbox directory of the data provider and can be shared in declaration mode by the data provider. Persistent data is configured as data tables for access. 22 23 24- Process data: process data, in the JSON or byte format, managed by the DatamgrService. It is stored in the DatamgrService sandbox directory, and is automatically deleted 10 days after no subscription. 25 26 27- Dynamic data: data stored in the memory of a device. It is automatically deleted after the device is restarted. Currently, the dynamic data refers to only the data set by **enableSilentProxy** and **disableSilentProxy**. 28 29 30| Data Type | Location | Data Format | Validity Period | Usage | 31| ----- | --------- | ----------- | ------------ | --------------------------------- | 32| Persistent data| Sandbox directory of the data provider | Database tables | Permanent | RDB data used for schedules and meetings. | 33| Process data | DatamgrService sandbox directory| JSON or byte| Automatically deleted 10 days after no subscription| Time-sensitive data in simple format used for step count, weather, and heart rate monitoring.| 34| Dynamic data | DatamgrService memory| KV pair| Automatically deleted after the device is restarted| Data generated when silent access is dynamically disabled or enabled. For example, to ensure data accuracy, silent access needs to be disabled in upgrade and enabled after the upgrade by using APIs. The "enabled" or "disabled" status generated by using the API is cleared after the device is restarted. The dynamic data refers to only the data set by **enableSilentProxy** and **disableSilentProxy**.| 35 36 37 38**Figure 1** Silent access 39 40 41 42- In silent access, **DatamgrService** obtains the access rules configured by the data provider through directory mapping, performs preprocessing based on rules, and accesses the database. 43 44- To use silent access, the URIs must be in the following format: 45 datashareproxy://{bundleName}/{dataPath} 46 47 The **DatamgrService** obtains the data provider application based on **bundleName**, reads the configuration, verifies the permission, and accesses data. 48 49 **dataPath** identifies the data. It can be customized and must be unique in the same data provider application. 50 51 52## Constraints 53 54- Currently, only the RDB stores support silent access. 55- The system supports a maximum of 16 concurrent query operations. Excess query requests need to be queued for processing. 56- The proxy is not allowed to create a database for persistent data. To create a database, you must start the data provider. 57- If the data provider is an application with a normal signature, the data read/write permission must be system_basic or higher. 58 59 60## Available APIs 61 62Most of the APIs for silent access are executed asynchronously in callback or promise mode. In the following table, callback-based APIs are used as an example. For more information about the APIs, see [Data Sharing](../reference/apis-arkdata/js-apis-data-dataShare-sys.md). 63 64### Universal APIs 65 66| API | Description | 67| ---------------------------------------- | -------------------- | 68| createDataShareHelper(context: Context, uri: string, options: DataShareHelperOptions, callback: AsyncCallback<DataShareHelper>): void | Creates a **DataShareHelper** instance.| 69 70### APIs for Accessing Persistent Data 71 72| API | Description | 73| ---------------------------------------- | -------------------- | 74| insert(uri: string, value: ValuesBucket, callback: AsyncCallback<number>): void | Inserts a row of data into a table. | 75| delete(uri: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback<number>): void | Deletes one or more data records from the database. | 76| query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array<string>, callback: AsyncCallback<DataShareResultSet>): void | Queries data in the database. | 77| update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback<number>): void | Updates data in the database. | 78| addTemplate(uri: string, subscriberId: string, template: Template): void | Adds a data template with the specified subscriber. | 79| on(type: 'rdbDataChange', uris: Array<string>, templateId: TemplateId, callback: AsyncCallback<RdbDataChangeNode>): Array<OperationResult | Subscribes to the changes of the data corresponding to the specified URI and template.| 80 81### APIs for Accessing Process Data 82 83| API | Description | 84| ---------------------------------------- | ------------------ | 85| publish(data: Array<PublishedItem>, bundleName: string, version: number, callback: AsyncCallback<Array<OperationResult>>): void | Publish data to the DatamgrService.| 86| on(type: 'publishedDataChange', uris: Array<string>, subscriberId: string, callback: AsyncCallback<PublishedDataChangeNode>): Array<OperationResult> | Subscribes to changes of the published data. | 87 88### APIs for Accessing Dynamic Data 89 90| API | Description | 91| ---------------------------------------- | ------------------ | 92| enableSilentProxy(context: Context, uri?: string): Promise<void> | Enables silent access by the data provider dynamically.<br>When the data consumer calls the **DataShare** API through silent access, the system verifies the silent access status.<br>If silent access is enabled, the **DataShare** API will be executed.| 93| disableSilentProxy(context: Context, uri?: string): Promise<void> | Disables silent access by the data provider dynamically.<br>When the data consumer calls the **DataShare** API through silent access, the system verifies the silent access status.<br>If silent access is disabled, the **DataShare** API will be denied. | 94 95 96 97## Accessing Persistent Data 98 99The following walks you through on how to share an RDB store. 100 101### Data Provider Application 102 1031. In the **module.json5** file, set the data to be shared in **proxyData**. For details about the configuration, see [module.json5 Configuration File](../quick-start/module-configuration-file.md). 104 105 **Table 1** proxyData in module.json5 106 107 | Name | Description | Mandatory | 108 | ----------------------- | ---------------------------------------- | ---- | 109 | uri | URI of the data proxy, which is the unique identifier for cross-application data access. | Yes | 110 | requiredReadPermission | Permission required for reading data from the data proxy. If this parameter is not set, other applications are not allowed to access data. For details about the permissions, see [Permissions for All Applications](../security/AccessToken/permissions-for-all.md). | No | 111 | requiredWritePermission | Permission required for writing data to the data proxy. If this parameter is not set, other applications are not allowed to write data to the data proxy. For details about the permissions, see [Permissions for All Applications](../security/AccessToken/permissions-for-all.md). | No | 112 | metadata | Metadata of the data source, including the **name** and **resource** fields.<br>The **name** field identifies the configuration, which has a fixed value of **dataProperties**.<br>The value of **resource** is **$profile:{fileName}**, indicating that the name of the configuration file is **{fileName}.json**.| Yes | 113 114 **module.json5 example** 115 116 ```json 117 "proxyData":[ 118 { 119 "uri": "datashareproxy://com.acts.ohos.data.datasharetest/test", 120 "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO", 121 "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING", 122 "metadata": { 123 "name": "dataProperties", 124 "resource": "$profile:my_config" 125 } 126 } 127 ] 128 ``` 129 **Table 2** Fields in my_config.json 130 131 | Name | Description | Mandatory | 132 | ----- | ---------------------------------------- | ---- | 133 | path | Data source path, in the **Database_name/Table_name** format. Currently, only RDB stores are supported. | Yes | 134 | type | Database type. Currently, only **rdb** is supported. | Yes | 135 | scope | Scope of the database.<br>- **module** indicates that the database is located in this module.<br>- **application** indicates that the database is located in this application.| No | 136 137 **my_config.json example** 138 139 ```json 140 { 141 "path": "DB00/TBL00", 142 "type": "rdb", 143 "scope": "application" 144 } 145 ``` 146 147### Data Consumer Application 148 149 1501. Import dependencies. 151 152 ```ts 153 import { dataShare, dataSharePredicates, ValuesBucket } from '@kit.ArkData'; 154 import { UIAbility } from '@kit.AbilityKit'; 155 import { window } from '@kit.ArkUI'; 156 import { BusinessError } from '@kit.BasicServicesKit' 157 ``` 158 1592. Define the URI string for communicating with the data provider. 160 161 ```ts 162 let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/test'); 163 ``` 164 1653. Create a **DataShareHelper** instance. 166 167 ```ts 168 let dsHelper: dataShare.DataShareHelper | undefined = undefined; 169 let abilityContext: Context; 170 171 export default class EntryAbility extends UIAbility { 172 onWindowStageCreate(windowStage: window.WindowStage) { 173 abilityContext = this.context; 174 dataShare.createDataShareHelper(abilityContext, dseUri, { 175 isProxy: true 176 }, (err, data) => { 177 dsHelper = data; 178 }); 179 } 180 } 181 ``` 182 1834. Use **DataShareHelper** APIs to access the services provided by the provider, for example, adding, deleting, modifying, and querying data. 184 185 ```ts 186 // Construct a piece of data. 187 let key1 = 'name'; 188 let key2 = 'age'; 189 let key3 = 'isStudent'; 190 let key4 = 'Binary'; 191 let valueName1 = 'ZhangSan'; 192 let valueName2 = 'LiSi'; 193 let valueAge1 = 21; 194 let valueAge2 = 18; 195 let valueIsStudent1 = false; 196 let valueIsStudent2 = true; 197 let valueBinary = new Uint8Array([1, 2, 3]); 198 let valuesBucket: ValuesBucket = { key1: valueName1, key2: valueAge1, key3: valueIsStudent1, key4: valueBinary }; 199 let updateBucket: ValuesBucket = { key1: valueName2, key2: valueAge2, key3: valueIsStudent2, key4: valueBinary }; 200 let predicates = new dataSharePredicates.DataSharePredicates(); 201 let valArray = ['*']; 202 if (dsHelper != undefined) { 203 // Insert a piece of data. 204 (dsHelper as dataShare.DataShareHelper).insert(dseUri, valuesBucket, (err, data) => { 205 console.info(`dsHelper insert result:${data}`); 206 }); 207 // Update data. 208 (dsHelper as dataShare.DataShareHelper).update(dseUri, predicates, updateBucket, (err, data) => { 209 console.info(`dsHelper update result:${data}`); 210 }); 211 // Query data. 212 (dsHelper as dataShare.DataShareHelper).query(dseUri, predicates, valArray, (err, data) => { 213 console.info(`dsHelper query result:${data}`); 214 }); 215 // Delete data. 216 (dsHelper as dataShare.DataShareHelper).delete(dseUri, predicates, (err, data) => { 217 console.info(`dsHelper delete result:${data}`); 218 }); 219 } 220 ``` 221 2225. Subscribe to data. 223 224 ```ts 225 function onCallback(err: BusinessError, node: dataShare.RdbDataChangeNode) { 226 console.info("uri " + JSON.stringify(node.uri)); 227 console.info("templateId " + JSON.stringify(node.templateId)); 228 console.info("data length " + node.data.length); 229 for (let i = 0; i < node.data.length; i++) { 230 console.info("data " + node.data[i]); 231 } 232 } 233 234 let key21: string = "p1"; 235 let value21: string = "select * from TBL00"; 236 let key22: string = "p2"; 237 let value22: string = "select name from TBL00"; 238 let template: dataShare.Template = { 239 predicates: { 240 key21: value21, 241 key22: value22, 242 }, 243 scheduler: "" 244 } 245 if(dsHelper != undefined) 246 { 247 (dsHelper as dataShare.DataShareHelper).addTemplate(dseUri, "111", template); 248 } 249 let templateId: dataShare.TemplateId = { 250 subscriberId: "111", 251 bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient" 252 } 253 if(dsHelper != undefined) { 254 // When the DatamgrService modifies data, onCallback is invoked to return the data queried based on the rules in the template. 255 let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("rdbDataChange", [dseUri], templateId, onCallback); 256 } 257 ``` 258 259## Accessing Process Data 260 261The following walks you through on how to host process data. 262 263### (Optional) Data Provider Application 264 265In the **module.json5** file, set the data to be hosted in **proxyData**. For details about the configuration, see [module.json5 Configuration File](../quick-start/module-configuration-file.md). 266 267> **NOTE** 268> 269> - The configuration of **proxyData** is optional. 270> - If **proxyData** is not configured, the hosted data cannot be accessed by other applications. 271> - If **proxyData** is not configured, you do not need to use the full data path. For example, you can use **weather** instead of **datashareproxy://com.acts.ohos.data.datasharetest/weather** when publishing, subscribing to, and querying data. 272 273**Table 3** proxyData in module.json5 274 275| Name | Description | Mandatory | 276| ----------------------- | ----------------------------- | ---- | 277| uri | URI of the data proxy, which is the unique identifier for cross-application data access. | Yes | 278| requiredReadPermission | Permission required for reading data from the data proxy. If this parameter is not set, other applications are not allowed to access data. For details about the permissions, see [Permissions for All Applications](../security/AccessToken/permissions-for-all.md).| No | 279| requiredWritePermission | Permission required for writing data to the data proxy. If this parameter is not set, other applications are not allowed to write data to the dta proxy. For details about the permissions, see [Permissions for All Applications](../security/AccessToken/permissions-for-all.md).| No | 280 281**module.json5 example** 282 283```json 284"proxyData": [ 285 { 286 "uri": "datashareproxy://com.acts.ohos.data.datasharetest/weather", 287 "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO", 288 "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING" 289 } 290] 291``` 292 293### Data Consumer Application 294 2951. Import dependencies. 296 297 ```ts 298 import { dataShare } from '@kit.ArkData'; 299 import { UIAbility } from '@kit.AbilityKit'; 300 import { window } from '@kit.ArkUI'; 301 import { BusinessError } from '@kit.BasicServicesKit'; 302 ``` 303 3042. Define the URI string for communicating with the data provider. 305 306 ```ts 307 let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/weather'); 308 ``` 309 3103. Create a **DataShareHelper** instance. 311 312 ```ts 313 let dsHelper: dataShare.DataShareHelper | undefined = undefined; 314 let abilityContext: Context; 315 316 export default class EntryAbility extends UIAbility { 317 onWindowStageCreate(windowStage: window.WindowStage) { 318 abilityContext = this.context; 319 dataShare.createDataShareHelper(abilityContext, dseUri, {isProxy : true}, (err, data) => { 320 dsHelper = data; 321 }); 322 } 323 } 324 ``` 325 3264. Use the **DataShareHelper** APIs to access the services provided by the provider, for example, adding, deleting, modifying, and querying data. 327 328 ```ts 329 // Construct two pieces of data. The first data is not configured with proxyDatas and cannot be accessed by other applications. 330 let data : Array<dataShare.PublishedItem> = [ 331 {key:"city", subscriberId:"11", data:"xian"}, 332 {key:"datashareproxy://com.acts.ohos.data.datasharetest/weather", subscriberId:"11", data:JSON.stringify("Qing")}]; 333 // Publish data. 334 if (dsHelper != undefined) { 335 let result: Array<dataShare.OperationResult> = await (dsHelper as dataShare.DataShareHelper).publish(data, "com.acts.ohos.data.datasharetestclient"); 336 } 337 ``` 338 3395. Subscribe to data. 340 341 ```ts 342 function onPublishCallback(err: BusinessError, node:dataShare.PublishedDataChangeNode) { 343 console.info("onPublishCallback"); 344 } 345 let uris:Array<string> = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/weather"]; 346 if (dsHelper != undefined) { 347 let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("publishedDataChange", uris, "11", onPublishCallback); 348 } 349 ``` 350 351## Accessing Dynamic Data 352 353Only the data provider is involved. The following walks you through on how to dynamically enable silent access. 354 355### Data Provider Application 356 357The data provider calls the **enableSilentProxy** API to dynamically enable silent access. This API must be used with the **isSilentProxyEnable** field in the **data_share_config.json** file. For details, see [**data_share_config.json** configuration](./share-data-by-datashareextensionability.md). 358 359> **NOTE** 360> 361> - In the **data_share_config.json** file, the default value of **isSilentProxyEnable** is **true**, which means silent access is enabled. 362> - To verify whether silent access is enabled, the system first checks the silent access status set by the **enableSilentProxy** or **disableSilentProxy** API called, and then checks the value of **isSilentProxyEnable** in the **data_share_config.json** file. 363> - If **enableSilentProxy** or **disableSilentProxy** has not been called, the value of **isSilentProxyEnable** in the **data_share_config.json** file is preferentially checked. 364> - Silent access is enabled by default if **enableSilentProxy** or **disableSilentProxy** has not been called and **isSilentProxyEnable** in the **data_share_config.json** file is not configured. 365 3661. Import dependencies. 367 368 ```ts 369 import { dataShare } from '@kit.ArkData'; 370 import { UIAbility } from '@kit.AbilityKit'; 371 import { window } from '@kit.ArkUI'; 372 ``` 373 3742. Define the URI string for communicating with the data provider. 375 376 ```ts 377 let dseUri = ('datashare:///com.acts.datasharetest/entry/DB00/TBL00'); 378 ``` 379 3803. Create a **DataShareHelper** instance. 381 382 ```ts 383 let abilityContext: Context; 384 385 export default class EntryAbility extends UIAbility { 386 onWindowStageCreate(windowStage: window.WindowStage) { 387 abilityContext = this.context; 388 dataShare.enableSilentProxy(abilityContext, dseUri); 389 } 390 } 391 ``` 392