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