• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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![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- 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&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.|
93| 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 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 from '@ohos.data.dataShare';
154   import dataSharePredicates from '@ohos.data.dataSharePredicates';
155   import UIAbility from '@ohos.app.ability.UIAbility';
156   import { ValuesBucket } from '@ohos.data.ValuesBucket';
157   import window from '@ohos.window';
158   import { BusinessError } from '@ohos.base';
159   ```
160
1612. Define the URI string for communicating with the data provider.
162
163   ```ts
164   let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/test');
165   ```
166
1673. Create a **DataShareHelper** instance.
168
169   ```ts
170   let dsHelper: dataShare.DataShareHelper | undefined = undefined;
171   let abilityContext: Context;
172
173   export default class EntryAbility extends UIAbility {
174     onWindowStageCreate(windowStage: window.WindowStage) {
175       abilityContext = this.context;
176       dataShare.createDataShareHelper(abilityContext, dseUri, {
177         isProxy: true
178       }, (err, data) => {
179         dsHelper = data;
180       });
181     }
182   }
183   ```
184
1854. Use **DataShareHelper** APIs to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
186
187   ```ts
188   // Construct a piece of data.
189   let key1 = 'name';
190   let key2 = 'age';
191   let key3 = 'isStudent';
192   let key4 = 'Binary';
193   let valueName1 = 'ZhangSan';
194   let valueName2 = 'LiSi';
195   let valueAge1 = 21;
196   let valueAge2 = 18;
197   let valueIsStudent1 = false;
198   let valueIsStudent2 = true;
199   let valueBinary = new Uint8Array([1, 2, 3]);
200   let valuesBucket: ValuesBucket = { key1: valueName1, key2: valueAge1, key3: valueIsStudent1, key4: valueBinary };
201   let updateBucket: ValuesBucket = { key1: valueName2, key2: valueAge2, key3: valueIsStudent2, key4: valueBinary };
202   let predicates = new dataSharePredicates.DataSharePredicates();
203   let valArray = ['*'];
204   if (dsHelper != undefined) {
205     // Insert a piece of data.
206     (dsHelper as dataShare.DataShareHelper).insert(dseUri, valuesBucket, (err, data) => {
207       console.info(`dsHelper insert result:${data}`);
208     });
209     // Update data.
210     (dsHelper as dataShare.DataShareHelper).update(dseUri, predicates, updateBucket, (err, data) => {
211       console.info(`dsHelper update result:${data}`);
212     });
213     // Query data.
214     (dsHelper as dataShare.DataShareHelper).query(dseUri, predicates, valArray, (err, data) => {
215       console.info(`dsHelper query result:${data}`);
216     });
217     // Delete data.
218     (dsHelper as dataShare.DataShareHelper).delete(dseUri, predicates, (err, data) => {
219       console.info(`dsHelper delete result:${data}`);
220     });
221   }
222   ```
223
2245. Subscribe to data.
225
226   ```ts
227   function onCallback(err: BusinessError, node: dataShare.RdbDataChangeNode) {
228     console.info("uri " + JSON.stringify(node.uri));
229     console.info("templateId " + JSON.stringify(node.templateId));
230     console.info("data length " + node.data.length);
231     for (let i = 0; i < node.data.length; i++) {
232       console.info("data " + node.data[i]);
233     }
234   }
235
236   let key21: string = "p1";
237   let value21: string = "select * from TBL00";
238   let key22: string = "p2";
239   let value22: string = "select name from TBL00";
240   let template: dataShare.Template = {
241     predicates: {
242       key21: value21,
243       key22: value22,
244     },
245     scheduler: ""
246   }
247   if(dsHelper != undefined)
248   {
249     (dsHelper as dataShare.DataShareHelper).addTemplate(dseUri, "111", template);
250   }
251   let templateId: dataShare.TemplateId = {
252     subscriberId: "111",
253     bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient"
254   }
255   if(dsHelper != undefined) {
256     // When the DatamgrService modifies data, onCallback is invoked to return the data queried based on the rules in the template.
257     let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("rdbDataChange", [dseUri], templateId, onCallback);
258   }
259   ```
260
261## Accessing Process Data
262
263The following walks you through on how to host process data.
264
265### (Optional) Data Provider Application
266
267In 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).
268
269> **NOTE**
270>
271> - The configuration of **proxyData** is optional.
272> - If **proxyData** is not configured, the hosted data cannot be accessed by other applications.
273> - 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.
274
275**Table 3** proxyData in module.json5
276
277| Name                   | Description                         | Mandatory  |
278| ----------------------- | ----------------------------- | ---- |
279| uri                     | URI of the data proxy, which is the unique identifier for cross-application data access.      | Yes   |
280| 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   |
281| 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   |
282
283**module.json5 example**
284
285```json
286"proxyData": [
287  {
288    "uri": "datashareproxy://com.acts.ohos.data.datasharetest/weather",
289    "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO",
290    "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING"
291  }
292]
293```
294
295### Data Consumer Application
296
2971. Import dependencies.
298
299   ```ts
300   import dataShare from '@ohos.data.dataShare';
301   import UIAbility from '@ohos.app.ability.UIAbility';
302   import window from '@ohos.window';
303   import { BusinessError } from '@ohos.base';
304   ```
305
3062. Define the URI string for communicating with the data provider.
307
308   ```ts
309   let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/weather');
310   ```
311
3123. Create a **DataShareHelper** instance.
313
314   ```ts
315   let dsHelper: dataShare.DataShareHelper | undefined = undefined;
316   let abilityContext: Context;
317
318   export default class EntryAbility extends UIAbility {
319     onWindowStageCreate(windowStage: window.WindowStage) {
320       abilityContext = this.context;
321       dataShare.createDataShareHelper(abilityContext, dseUri, {isProxy : true}, (err, data) => {
322         dsHelper = data;
323       });
324     }
325   }
326   ```
327
3284. Use the **DataShareHelper** APIs to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
329
330   ```ts
331   // Construct two pieces of data. The first data is not configured with proxyDatas and cannot be accessed by other applications.
332   let data : Array<dataShare.PublishedItem> = [
333     {key:"city", subscriberId:"11", data:"xian"},
334     {key:"datashareproxy://com.acts.ohos.data.datasharetest/weather", subscriberId:"11", data:JSON.stringify("Qing")}];
335   // Publish data.
336   if (dsHelper != undefined) {
337     let result: Array<dataShare.OperationResult> = await (dsHelper as dataShare.DataShareHelper).publish(data, "com.acts.ohos.data.datasharetestclient");
338   }
339   ```
340
3415. Subscribe to data.
342
343   ```ts
344   function onPublishCallback(err: BusinessError, node:dataShare.PublishedDataChangeNode) {
345     console.info("onPublishCallback");
346   }
347   let uris:Array<string> = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/weather"];
348   if (dsHelper != undefined) {
349     let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("publishedDataChange", uris, "11", onPublishCallback);
350   }
351   ```
352
353## Accessing Dynamic Data
354
355Only the data provider is involved. The following walks you through on how to dynamically enable silent access.
356
357### Data Provider Application
358
359The 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).
360
361> **NOTE**
362>
363> - In the **data_share_config.json** file, the default value of **isSilentProxyEnable** is **true**, which means silent access is enabled.
364> - 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.
365> - If **enableSilentProxy** or **disableSilentProxy** has not been called, the value of **isSilentProxyEnable** in the **data_share_config.json** file is preferentially checked.
366> - 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.
367
3681. Import dependencies.
369
370   ```ts
371   import dataShare from '@ohos.data.dataShare';
372   import UIAbility from '@ohos.app.ability.UIAbility';
373   import window from '@ohos.window';
374   ```
375
3762. Define the URI string for communicating with the data provider.
377
378   ```ts
379   let dseUri = ('datashare:///com.acts.datasharetest/entry/DB00/TBL00');
380   ```
381
3823. Create a **DataShareHelper** instance.
383
384   ```ts
385   let abilityContext: Context;
386
387   export default class EntryAbility extends UIAbility {
388     onWindowStageCreate(windowStage: window.WindowStage) {
389       abilityContext = this.context;
390       dataShare.enableSilentProxy(abilityContext, dseUri);
391     }
392   }
393   ```
394
395
396