• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
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
19**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
27- Dynamic data: data stored in the memory of a device. It is automatically deleted after the device is restarted. 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. <br>The dynamic data refers to only the data set by **enableSilentProxy** and **disableSilentProxy**.|
35
36
37
38**Figure 1** Silent access
39
40![silent_dataShare](figures/silent_dataShare.jpg)
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- The URI of the data consumer must be in the **datashareproxy://{*bundleName*}/{*dataPath*}** format.
45
46  **DatamgrService** obtains the data provider application based on **bundleName**, reads the configuration, verifies the permission, and accesses data.
47
48  **dataPath** identifies the data. It can be customized and must be unique in the same data provider application.
49
50- 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.
51
52  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 **Proxy**, **appIndex**, and **user** parameters are supported. If the URI contains multiple question marks (?), the parameter following the question mark (?) must be **Proxy**. Otherwise, this parameter does not take effect.
53
54  - **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.
55
56  - **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.
57
58    Currently, cloned applications are supported only in silent access mode. When setting the URI and parameters for accessing an application clone, both **Proxy** and **appIndex** must be set. For example, **datashareproxy://{bundleName}/{dataPath}?Proxy=true&appIndex=1** indicates that the data consumer will access the first clone of the application in silent access mode.
59
60  - 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.
61
62    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.
63
64## Constraints
65
66- Currently, only the RDB stores support silent access.
67- The system supports a maximum of 16 concurrent query operations. Excess query requests need to be queued for processing.
68- The proxy is not allowed to create a database for persistent data. To create a database, you must start the data provider.
69- If the data provider is an application with a normal signature, the data read/write permission must be system_basic or higher.
70
71
72## Available APIs
73
74Most 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).
75
76### Universal APIs
77
78| API                                    | Description                  |
79| ---------------------------------------- | -------------------- |
80| createDataShareHelper(context: Context, uri: string, options: DataShareHelperOptions, callback: AsyncCallback&lt;DataShareHelper&gt;): void | Creates a **DataShareHelper** instance.|
81
82### APIs for Accessing Persistent Data
83
84| API                                    | Description                  |
85| ---------------------------------------- | -------------------- |
86| insert(uri: string, value: ValuesBucket, callback: AsyncCallback&lt;number&gt;): void | Inserts a row of data into a table.        |
87| delete(uri: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback&lt;number&gt;): void | Deletes one or more data records from the database.   |
88| query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array&lt;string&gt;, callback: AsyncCallback&lt;DataShareResultSet&gt;): void | Queries data in the database.          |
89| update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback&lt;number&gt;): void | Updates data in the database.        |
90| addTemplate(uri: string, subscriberId: string, template: Template): void | Adds a data template with the specified subscriber.     |
91| on(type: 'rdbDataChange', uris: Array&lt;string&gt;, templateId: TemplateId, callback: AsyncCallback&lt;RdbDataChangeNode&gt;): Array&lt;OperationResult&gt; | Subscribes to the changes of the data corresponding to the specified URI and template.|
92
93### APIs for Accessing Process Data
94
95| API                                    | Description                |
96| ---------------------------------------- | ------------------ |
97| publish(data: Array&lt;PublishedItem&gt;, bundleName: string, version: number, callback: AsyncCallback&lt;Array&lt;OperationResult&gt;&gt;): void | Publishes data to **DatamgrService**.|
98| on(type: 'publishedDataChange', uris: Array&lt;string&gt;, subscriberId: string, callback: AsyncCallback&lt;PublishedDataChangeNode&gt;): Array&lt;OperationResult&gt; | Subscribes to changes of the published data.   |
99
100### APIs for Accessing Dynamic Data
101
102| API                                    | Description                |
103| ---------------------------------------- | ------------------ |
104| enableSilentProxy(context: Context, uri?: string): Promise&lt;void&gt; | 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.|
105| disableSilentProxy(context: Context, uri?: string): Promise&lt;void&gt; | 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.|
106
107
108
109## Accessing Persistent Data
110
111The following walks you through on how to share an RDB store.
112
113### Data Provider Application Development
114
1151. 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).
116
117   **Table 1** proxyData in module.json5
118
119   | Name                   | Description                                    | Mandatory  |
120   | ----------------------- | ---------------------------------------- | ---- |
121   | uri                     | URI of the data proxy, which is the unique identifier for cross-application data access.                 | Yes   |
122   | 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   |
123   | 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   |
124   | 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   |
125
126   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.
127
128   **module.json5 example**
129
130   ```json
131   // The following uses settingsdata as an example.
132   "proxyData": [
133     {
134       "uri": "datashareproxy://com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE",
135       // Configure permissions based on actual situation. The permissions configured here are examples only.
136       "requiredReadPermission": "ohos.permission.MANAGE_SECURE_SETTINGS",
137       "requiredWritePermission": "ohos.permission.MANAGE_SECURE_SETTINGS",
138       "metadata": {
139         "name": "dataProperties",
140         "resource": "$profile:my_config"
141       }
142     }
143   ]
144   ```
145   **Table 2** Fields in my_config.json
146
147   | Name | Description                                    | Mandatory  |
148   | ----- | ---------------------------------------- | ---- |
149   | path  | Data source path, in the **Database_name/Table_name** format. Currently, only RDB stores are supported.            | Yes   |
150   | type  | Database type. Currently, only **rdb** is supported.            | Yes   |
151   | 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   |
152   | allowLists          | List of applications that can access the data.<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. <br/>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>**allowLists** consists of two fields:<br/>- **appIdentifier**: unique identifier (string) of the application allocated by the cloud. The data provider should obtain it from the data consumer. 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  |
153
154   **my_config.json example**
155
156   ```json
157   {
158     "path": "DB00/TBL00",
159     "type": "rdb",
160     "scope": "application",
161     "allowLists":[
162           {"appIdentifier": "appIdentifier1", "onlyMain": false},
163           {"appIdentifier": "appIdentifier2", "onlyMain": true}
164     ]
165   }
166   ```
167
168### Data Consumer Application Development
169
170
1711. Import dependencies.
172
173   ```ts
174   import { dataShare, dataSharePredicates, ValuesBucket } from '@kit.ArkData';
175   import { UIAbility } from '@kit.AbilityKit';
176   import { window } from '@kit.ArkUI';
177   import { BusinessError } from '@kit.BasicServicesKit'
178   ```
179
1802. Define the URI string for communicating with the data provider.
181
182   ```ts
183   let dseUri = ('datashareproxy://com.ohos.settingsdata/entry/settingsdata/USER_SETTINGSDATA_SECURE');
184   ```
185
1863. Create a **DataShareHelper** instance.
187
188   ```ts
189   let dsHelper: dataShare.DataShareHelper | undefined = undefined;
190   let abilityContext: Context;
191
192   export default class EntryAbility extends UIAbility {
193     onWindowStageCreate(windowStage: window.WindowStage) {
194       abilityContext = this.context;
195       dataShare.createDataShareHelper(abilityContext, dseUri, {
196         isProxy: true
197       }, (err, data) => {
198         dsHelper = data;
199       });
200     }
201   }
202   ```
203
2044. Use the **DataShareHelper** APIs to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
205
206   ```ts
207   // Construct a piece of data.
208   let key1 = 'name';
209   let key2 = 'age';
210   let key3 = 'isStudent';
211   let key4 = 'Binary';
212   let valueName1 = 'ZhangSan';
213   let valueName2 = 'LiSi';
214   let valueAge1 = 21;
215   let valueAge2 = 18;
216   let valueIsStudent1 = false;
217   let valueIsStudent2 = true;
218   let valueBinary = new Uint8Array([1, 2, 3]);
219   let valuesBucket: ValuesBucket = { key1: valueName1, key2: valueAge1, key3: valueIsStudent1, key4: valueBinary };
220   let updateBucket: ValuesBucket = { key1: valueName2, key2: valueAge2, key3: valueIsStudent2, key4: valueBinary };
221   let predicates = new dataSharePredicates.DataSharePredicates();
222   let valArray = ['*'];
223   if (dsHelper != undefined) {
224     // Insert a piece of data.
225     (dsHelper as dataShare.DataShareHelper).insert(dseUri, valuesBucket, (err, data) => {
226       console.info(`dsHelper insert result:${data}`);
227     });
228     // Update data.
229     (dsHelper as dataShare.DataShareHelper).update(dseUri, predicates, updateBucket, (err, data) => {
230       console.info(`dsHelper update result:${data}`);
231     });
232     // Query data.
233     (dsHelper as dataShare.DataShareHelper).query(dseUri, predicates, valArray, (err, data) => {
234       console.info(`dsHelper query result:${data}`);
235     });
236     // Delete data.
237     (dsHelper as dataShare.DataShareHelper).delete(dseUri, predicates, (err, data) => {
238       console.info(`dsHelper delete result:${data}`);
239     });
240   }
241   ```
242
2435. Subscribe to data.
244
245   ```ts
246   function onCallback(err: BusinessError, node: dataShare.RdbDataChangeNode) {
247     console.info("uri " + JSON.stringify(node.uri));
248     console.info("templateId " + JSON.stringify(node.templateId));
249     console.info("data length " + node.data.length);
250     for (let i = 0; i < node.data.length; i++) {
251       console.info("data " + node.data[i]);
252     }
253   }
254
255   let key21: string = "p1";
256   let value21: string = "select * from TBL00";
257   let key22: string = "p2";
258   let value22: string = "select name from TBL00";
259   let template: dataShare.Template = {
260     predicates: {
261       key21: value21,
262       key22: value22,
263     },
264     scheduler: ""
265   }
266   if(dsHelper != undefined)
267   {
268     (dsHelper as dataShare.DataShareHelper).addTemplate(dseUri, "111", template);
269   }
270   let templateId: dataShare.TemplateId = {
271     subscriberId: "111",
272     bundleNameOfOwner: "com.ohos.settingsdata"
273   }
274   if(dsHelper != undefined) {
275     // When DatamgrService modifies data, onCallback is invoked to return the data queried based on the rules in the template.
276     let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("rdbDataChange", [dseUri], templateId, onCallback);
277   }
278   ```
279
280## Accessing Process Data
281
282The following walks you through on how to host process data.
283
284### (Optional) Data Provider Application Development
285
286In 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).
287
288> **NOTE**
289>
290> - The configuration of **proxyData** is optional.
291> - If **proxyData** is not configured, the hosted data cannot be accessed by other applications.
292> - 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.
293
294**Table 3** proxyData in module.json5
295
296| Name                   | Description                         | Mandatory  |
297| ----------------------- | ----------------------------- | ---- |
298| uri                     | URI of the data proxy, which is the unique identifier for cross-application data access.      | Yes   |
299| 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   |
300| 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**: 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   |
301
302**module.json5 example**
303
304```json
305// The following is an example only. Configure it as required.
306"proxyData": [
307  {
308    "uri": "datashareproxy://com.acts.ohos.data.datasharetest/weather",
309    // Configure permissions based on actual situation. The permissions configured here are examples only.
310    "requiredReadPermission": "ohos.permission.READ_WEATHER_DATA",
311    "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING"
312  }
313]
314```
315
316### Data Consumer Application Development
317
3181. Import dependencies.
319
320   ```ts
321   import { dataShare } from '@kit.ArkData';
322   import { UIAbility } from '@kit.AbilityKit';
323   import { window } from '@kit.ArkUI';
324   import { BusinessError } from '@kit.BasicServicesKit';
325   ```
326
3272. Define the URI string for communicating with the data provider.
328
329   ```ts
330   let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/weather');
331   ```
332
3333. Create a **DataShareHelper** instance.
334
335   ```ts
336   let dsHelper: dataShare.DataShareHelper | undefined = undefined;
337   let abilityContext: Context;
338
339   export default class EntryAbility extends UIAbility {
340     onWindowStageCreate(windowStage: window.WindowStage) {
341       abilityContext = this.context;
342       dataShare.createDataShareHelper(abilityContext, dseUri, {isProxy : true}, (err, data) => {
343         dsHelper = data;
344       });
345     }
346   }
347   ```
348
3494. Use the **DataShareHelper** APIs to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
350
351   ```ts
352   // Construct two pieces of data. The first data is not configured with proxyDatas and cannot be accessed by other applications.
353   let data : Array<dataShare.PublishedItem> = [
354     {key:"city", subscriberId:"11", data:"xian"},
355     {key:"datashareproxy://com.acts.ohos.data.datasharetest/weather", subscriberId:"11", data:JSON.stringify("Qing")}];
356   // Publish data.
357   if (dsHelper != undefined) {
358     let result: Array<dataShare.OperationResult> = await (dsHelper as dataShare.DataShareHelper).publish(data, "com.acts.ohos.data.datasharetestclient");
359   }
360   ```
361
3625. Subscribe to data.
363
364   ```ts
365   function onPublishCallback(err: BusinessError, node:dataShare.PublishedDataChangeNode) {
366     console.info("onPublishCallback");
367   }
368   let uris:Array<string> = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/weather"];
369   if (dsHelper != undefined) {
370     let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("publishedDataChange", uris, "11", onPublishCallback);
371   }
372   ```
373
374## Accessing Dynamic Data
375
376Only the data provider is involved. The following walks you through on how to dynamically enable silent access.
377
378### Data Provider Application Development
379
380The 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).
381
382> **NOTE**
383>
384> - In the **data_share_config.json** file, the default value of **isSilentProxyEnable** is **true**, which means silent access is enabled.
385> - 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.
386> - If **enableSilentProxy** or **disableSilentProxy** has not been called, the value of **isSilentProxyEnable** in the **data_share_config.json** file is preferentially checked.
387> - 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.
388
3891. Import dependencies.
390
391   ```ts
392   import { dataShare } from '@kit.ArkData';
393   import { UIAbility } from '@kit.AbilityKit';
394   import { window } from '@kit.ArkUI';
395   ```
396
3972. Define the URI string for communicating with the data provider.
398
399   ```ts
400   let dseUri = ('datashare:///com.ohos.settingsdata/entry/DB00/TBL00');
401   ```
402
4033. Create a **DataShareHelper** instance.
404
405   ```ts
406   let abilityContext: Context;
407
408   export default class EntryAbility extends UIAbility {
409     onWindowStageCreate(windowStage: window.WindowStage) {
410       abilityContext = this.context;
411       dataShare.enableSilentProxy(abilityContext, dseUri);
412     }
413   }
414   ```
415
416
417