1# Silent Access via DatamgrService (ArkTS) (for System Applications Only) 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 the access, OpenHarmony provides the silent access feature, which allows access to the database without starting the data provider. 9 10In silent access, **DatamgrService** accesses and modifies data without starting the data provider. 11 12However, **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 processing is too complex to be encapsulated, 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 **DatamgrService**. It is stored in the **DatamgrService** sandbox directory, and is automatically deleted 10 days after no subscription. 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 31 32**Figure 1** Silent access 33 34 35 36- Different from **DataShareExtensionAbility**, 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. 37 38- The URI of the data consumer must be in the **datashareproxy://{*bundleName*}/{*dataPath*}** format. 39 40 **DatamgrService** obtains the data provider application based on **bundleName**, reads the configuration, verifies the permission, and accesses data. 41 42 **dataPath** identifies the data. It can be customized and must be unique in the same data provider application. 43 44- 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. 45 46 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 the **appIndex** and **user** parameters are supported. 47 48 - **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 application of the data provider. 49 50 Currently, cloned applications are supported only in silent access mode. 51 52 - The value of **user** must be an integer. It is the user ID of the data provider. For details about the definition of **user** and how to obtain it, see [user](../reference/apis-basic-services-kit/js-apis-osAccount.md#getactivatedosaccountlocalids9). If **user** is not set, the user ID of the data consumer is used. Currently, cross-user access supports the add, delete, modify, and query operations, and does not support subscription notification. 53 54 Currently, only the main space and privacy space support cross-user access, and the data consumer must have the ohos.permission.INTERACT_ACROSS_LOCAL_ACCOUNTS permission. 55 56## Constraints 57 58- Currently, only the RDB stores support silent access. 59- The system supports a maximum of 32 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 94Data 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 status set by **enableSilentProxy** and **disableSilentProxy**. 95 96| API | Description | 97| ---------------------------------------- | ------------------ | 98| 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.| 99| 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 cannot be executed.| 100 101## Accessing Persistent Data 102 103The following walks you through on how to share an RDB store. 104 105### Data Provider Application Development 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 [Application Permissions](../security/AccessToken/app-permissions.md).<br>**NOTE**: The permission constraints for silent access are different from that for **DataShareExtensionAbility**. It is important to understand the difference and prevent confusion. For details, see [DataShareExtensionAbility](share-data-by-datashareextensionability.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 [Application Permissions](../security/AccessToken/app-permissions.md).<br>**NOTE**: The permission constraints for silent access are different from that for **DataShareExtensionAbility**. It is important to understand the difference and prevent confusion. For details, see [DataShareExtensionAbility](share-data-by-datashareextensionability.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 A data table contains all the data accessible through a URI. Ensure that all data in a table falls under the same permission scope. To effectively implement data isolation at the table level, you are advised to store data with different scopes in separate tables and configure appropriate permission constraints for each table. For security-critical data, you are advised to configure an allowlist of data consumers to prevent unauthorized access. For details, see the **allowLists** field in the **my_config.json** example. 119 120 **module.json5 example** 121 122 ```json 123 // The following uses settingsdata as an example. 124 "proxyData": [ 125 { 126 "uri": "datashareproxy://com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE", 127 // Configure permissions based on actual situation. The permissions configured here are examples only. 128 "requiredReadPermission": "ohos.permission.MANAGE_SECURE_SETTINGS", 129 "requiredWritePermission": "ohos.permission.MANAGE_SECURE_SETTINGS", 130 "metadata": { 131 "name": "dataProperties", 132 "resource": "$profile:my_config" 133 } 134 } 135 ] 136 ``` 137 **Table 2** Fields in my_config.json 138 139 | Name | Description | Mandatory | 140 | ----- | ---------------------------------------- | ---- | 141 | path | Data source path, in the **Database_name/Table_name** format. Currently, only RDB stores are supported. | Yes | 142 | type | Database type. Currently, only **rdb** is supported. | Yes | 143 | scope | Scope of the database.<br>1. **module** indicates that the database is located in this module.<br>2. **application** indicates that the database is located in this application.| No | 144 | allowLists | List of applications that can access the data. **allowLists** consists of two fields: **appIdentifier** and **onlyMain**.<br>It allows a maximum of 256 records. In cross-application data access, the data consumers are checked against the settings here. If the data consumer is not listed in **allowlists**, the data access will be rejected. If **allowLists** is not configured, allowlist verification is skipped. No matter whether **allowLists** is configured, the read and write permissions in [Table 1](#data-provider-application-development) are always verified.<br>- **appIdentifier**: unique identifier (string) of the application allocated by the cloud. The data provider should obtain it from the data consumer.<br>For details about **appIdentifier**, see [SignatureInfo](../reference/apis-ability-kit/js-apis-bundleManager-bundleInfo.md#signatureinfo).<br>- **onlyMain**: a Boolean value indicating whether the data is accessible only to the application. The value **true** means only the application can access the data. The value **false** means both the application and its clone can access the data. This feature is available only to silent access.| No | 145 146 **my_config.json example** 147 148 ```json 149 { 150 "path": "DB00/TBL00", 151 "type": "rdb", 152 "scope": "application", 153 "allowLists":[ 154 {"appIdentifier": "appIdentifier1", "onlyMain": false}, 155 {"appIdentifier": "appIdentifier2", "onlyMain": true} 156 ] 157 } 158 ``` 159 160### Data Consumer Application Development 161 162 1631. Import dependencies. 164 165 ```ts 166 import { dataShare, dataSharePredicates, ValuesBucket } from '@kit.ArkData'; 167 import { UIAbility } from '@kit.AbilityKit'; 168 import { window } from '@kit.ArkUI'; 169 import { BusinessError } from '@kit.BasicServicesKit' 170 ``` 171 1722. Define the URI string for communicating with the data provider. 173 174 ```ts 175 let dseUri = ('datashareproxy://com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE'); 176 ``` 177 1783. Use **createDataShareHelper()** to pass the URI to create a **DataShareHelper** object. 179 180 ```ts 181 let dsHelper: dataShare.DataShareHelper | undefined = undefined; 182 let abilityContext: Context; 183 184 export default class EntryAbility extends UIAbility { 185 onWindowStageCreate(windowStage: window.WindowStage) { 186 abilityContext = this.context; 187 dataShare.createDataShareHelper(abilityContext, dseUri, { 188 isProxy: true 189 }, (err, data) => { 190 dsHelper = data; 191 }); 192 } 193 } 194 ``` 195 1964. After obtaining the **DataShareHelper** object, use the APIs provided by the object to access the services provided by the provider, for example, **insert()**, **delete()**, **update()**, or **query()** to add, delete, modify, and query data. 197 198 ```ts 199 // Construct a piece of data. 200 let key1 = 'name'; 201 let key2 = 'age'; 202 let key3 = 'isStudent'; 203 let key4 = 'Binary'; 204 let valueName1 = 'ZhangSan'; 205 let valueName2 = 'LiSi'; 206 let valueAge1 = 21; 207 let valueAge2 = 18; 208 let valueIsStudent1 = false; 209 let valueIsStudent2 = true; 210 let valueBinary = new Uint8Array([1, 2, 3]); 211 let valuesBucket: ValuesBucket = { key1: valueName1, key2: valueAge1, key3: valueIsStudent1, key4: valueBinary }; 212 let updateBucket: ValuesBucket = { key1: valueName2, key2: valueAge2, key3: valueIsStudent2, key4: valueBinary }; 213 let predicates = new dataSharePredicates.DataSharePredicates(); 214 let valArray = ['*']; 215 if (dsHelper != undefined) { 216 // Insert a piece of data. 217 (dsHelper as dataShare.DataShareHelper).insert(dseUri, valuesBucket, (err, data) => { 218 console.info(`dsHelper insert result:${data}`); 219 }); 220 // Update data. 221 (dsHelper as dataShare.DataShareHelper).update(dseUri, predicates, updateBucket, (err, data) => { 222 console.info(`dsHelper update result:${data}`); 223 }); 224 // Query data. 225 (dsHelper as dataShare.DataShareHelper).query(dseUri, predicates, valArray, (err, data) => { 226 console.info(`dsHelper query result:${data}`); 227 }); 228 // Delete data. 229 (dsHelper as dataShare.DataShareHelper).delete(dseUri, predicates, (err, data) => { 230 console.info(`dsHelper delete result:${data}`); 231 }); 232 } 233 ``` 234 2355. Subscribe to data. 236 237 ```ts 238 function onCallback(err: BusinessError, node: dataShare.RdbDataChangeNode) { 239 console.info("uri " + JSON.stringify(node.uri)); 240 console.info("templateId " + JSON.stringify(node.templateId)); 241 console.info("data length " + node.data.length); 242 for (let i = 0; i < node.data.length; i++) { 243 console.info("data " + node.data[i]); 244 } 245 } 246 247 let key21: string = "p1"; 248 let value21: string = "select * from TBL00"; 249 let key22: string = "p2"; 250 let value22: string = "select name from TBL00"; 251 let template: dataShare.Template = { 252 predicates: { 253 key21: value21, 254 key22: value22, 255 }, 256 scheduler: "" 257 } 258 if(dsHelper != undefined) 259 { 260 (dsHelper as dataShare.DataShareHelper).addTemplate(dseUri, "111", template); 261 } 262 let templateId: dataShare.TemplateId = { 263 subscriberId: "111", 264 bundleNameOfOwner: "com.ohos.settingsdata" 265 } 266 if(dsHelper != undefined) { 267 // When DatamgrService modifies data, onCallback is invoked to return the data queried based on the rules in the template. 268 let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("rdbDataChange", [dseUri], templateId, onCallback); 269 } 270 ``` 271 272## Accessing Process Data 273 274The following walks you through on how to host process data. 275 276### (Optional) Data Provider Application Development 277 278In 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). 279 280> **NOTE** 281> 282> - The configuration of **proxyData** is optional. 283> - If **proxyData** is not configured, the hosted data cannot be accessed by other applications. 284 285**Table 3** proxyData in module.json5 286 287| Name | Description | Mandatory | 288| ----------------------- | ----------------------------- | ---- | 289| uri | URI of the data proxy, which is the unique identifier for cross-application data access. | Yes | 290| 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 [Application Permissions](../security/AccessToken/app-permissions.md).<br>**NOTE**<br>The permission constraints for silent access are different from that for [DataShareExtensionAbility](share-data-by-datashareextensionability.md). It is important to understand the difference and prevent confusion. For details, see [DataShareExtensionAbility](share-data-by-datashareextensionability.md). | No | 291| 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 [Application Permissions](../security/AccessToken/app-permissions.md).<br>**NOTE**<br/>The permission constraints for silent access are different from that for [DataShareExtensionAbility](share-data-by-datashareextensionability.md). It is important to understand the difference and prevent confusion. For details, see [DataShareExtensionAbility](share-data-by-datashareextensionability.md). | No | 292 293**module.json5 example** 294 295```json 296// The following is an example only. Configure it as required. 297"proxyData": [ 298 { 299 "uri": "datashareproxy://com.acts.ohos.data.datasharetest/weather", 300 // Configure permissions based on actual situation. The permissions configured here are examples only. 301 "requiredReadPermission": "ohos.permission.READ_WEATHER_DATA", 302 "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING" 303 } 304] 305``` 306 307### Data Consumer Application Development 308 3091. Import dependencies. 310 311 ```ts 312 import { dataShare } from '@kit.ArkData'; 313 import { UIAbility } from '@kit.AbilityKit'; 314 import { window } from '@kit.ArkUI'; 315 import { BusinessError } from '@kit.BasicServicesKit'; 316 ``` 317 3182. Define the URI string for communicating with the data provider. 319 320 ```ts 321 let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/weather'); 322 ``` 323 3243. Create a **DataShareHelper** instance. 325 326 ```ts 327 let dsHelper: dataShare.DataShareHelper | undefined = undefined; 328 let abilityContext: Context; 329 330 export default class EntryAbility extends UIAbility { 331 onWindowStageCreate(windowStage: window.WindowStage) { 332 abilityContext = this.context; 333 dataShare.createDataShareHelper(abilityContext, dseUri, {isProxy : true}, (err, data) => { 334 dsHelper = data; 335 }); 336 } 337 } 338 ``` 339 3404. Use the **DataShareHelper** APIs to access the services provided by the provider, for example, adding, deleting, modifying, and querying data. 341 342 ```ts 343 // Construct two pieces of data. The first data is not configured with proxyDatas and cannot be accessed by other applications. 344 let data : Array<dataShare.PublishedItem> = [ 345 {key:"city", subscriberId:"11", data:"xian"}, 346 {key:"datashareproxy://com.acts.ohos.data.datasharetest/weather", subscriberId:"11", data:JSON.stringify("Qing")}]; 347 // Publish data. 348 if (dsHelper != undefined) { 349 let result: Array<dataShare.OperationResult> = await (dsHelper as dataShare.DataShareHelper).publish(data, "com.acts.ohos.data.datasharetestclient"); 350 } 351 ``` 352 3535. Subscribe to data. 354 355 ```ts 356 function onPublishCallback(err: BusinessError, node:dataShare.PublishedDataChangeNode) { 357 console.info("onPublishCallback"); 358 } 359 let uris:Array<string> = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/weather"]; 360 if (dsHelper != undefined) { 361 let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("publishedDataChange", uris, "11", onPublishCallback); 362 } 363 ``` 364 365## Accessing Dynamic Data 366 367Only the data provider is involved. The following walks you through on how to dynamically enable silent access. 368 369### Data Provider Application Development 370 371The 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). 372 373> **NOTE** 374> 375> - The configuration of the **isSilentProxyEnable** field is optional. The default value is **true**, indicating that silent access is enabled. 376> - 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. 377> - If **enableSilentProxy** or **disableSilentProxy** has not been called, the value of **isSilentProxyEnable** in the **data_share_config.json** file is preferentially checked. 378> - 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. 379 3801. Import dependencies. 381 382 ```ts 383 import { dataShare } from '@kit.ArkData'; 384 import { UIAbility } from '@kit.AbilityKit'; 385 import { window } from '@kit.ArkUI'; 386 ``` 387 3882. Define the URI string for communicating with the data provider. 389 390 ```ts 391 let dseUri = ('datashareproxy:///com.ohos.settingsdata/entry/DB00/TBL00'); 392 ``` 393 3943. Create a **DataShareHelper** instance. 395 396 ```ts 397 let abilityContext: Context; 398 399 export default class EntryAbility extends UIAbility { 400 onWindowStageCreate(windowStage: window.WindowStage) { 401 abilityContext = this.context; 402 dataShare.enableSilentProxy(abilityContext, dseUri); 403 } 404 } 405 ``` 406 407 408