• 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. 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. <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 **Proxy** and **appIndex** can be added. 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 data provider application.
57
58    Currently, cloned applications can be accessed only in silent 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.
59
60## Constraints
61
62- Currently, only the RDB stores support silent access.
63- The system supports a maximum of 16 concurrent query operations. Excess query requests need to be queued for processing.
64- The proxy is not allowed to create a database for persistent data. To create a database, you must start the data provider.
65- If the data provider is an application with a normal signature, the data read/write permission must be system_basic or higher.
66
67
68## Available APIs
69
70Most 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).
71
72### Universal APIs
73
74| API                                    | Description                  |
75| ---------------------------------------- | -------------------- |
76| createDataShareHelper(context: Context, uri: string, options: DataShareHelperOptions, callback: AsyncCallback&lt;DataShareHelper&gt;): void | Creates a **DataShareHelper** instance.|
77
78### APIs for Accessing Persistent Data
79
80| API                                    | Description                  |
81| ---------------------------------------- | -------------------- |
82| insert(uri: string, value: ValuesBucket, callback: AsyncCallback&lt;number&gt;): void | Inserts a row of data into a table.        |
83| delete(uri: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback&lt;number&gt;): void | Deletes one or more data records from the database.   |
84| query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array&lt;string&gt;, callback: AsyncCallback&lt;DataShareResultSet&gt;): void | Queries data in the database.          |
85| update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback&lt;number&gt;): void | Updates data in the database.        |
86| addTemplate(uri: string, subscriberId: string, template: Template): void | Adds a data template with the specified subscriber.     |
87| on(type: 'rdbDataChange', uris: Array&lt;string&gt;, templateId: TemplateId, callback: AsyncCallback&lt;RdbDataChangeNode&gt;): Array&lt;OperationResult | Subscribes to the changes of the data corresponding to the specified URI and template.|
88
89### APIs for Accessing Process Data
90
91| API                                    | Description                |
92| ---------------------------------------- | ------------------ |
93| publish(data: Array&lt;PublishedItem&gt;, bundleName: string, version: number, callback: AsyncCallback&lt;Array&lt;OperationResult&gt;&gt;): void | Publishes data to **DatamgrService**.|
94| 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.   |
95
96### APIs for Accessing Dynamic Data
97
98| API                                    | Description                |
99| ---------------------------------------- | ------------------ |
100| 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.|
101| 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.|
102
103
104
105## Accessing Persistent Data
106
107The following walks you through on how to share an RDB store.
108
109### Data Provider Application
110
1111. 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).
112
113   **Table 1** proxyData in module.json5
114
115   | Name                   | Description                                    | Mandatory  |
116   | ----------------------- | ---------------------------------------- | ---- |
117   | uri                     | URI of the data proxy, which is the unique identifier for cross-application data access.                 | Yes   |
118   | 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).           | No   |
119   | 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).         | No   |
120   | 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   |
121
122   **module.json5 example**
123
124   ```json
125   "proxyData":[
126     {
127       "uri": "datashareproxy://com.acts.ohos.data.datasharetest/test",
128       "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO",
129       "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING",
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>- **module** indicates that the database is located in this module.<br>- **application** indicates that the database is located in this application.| No   |
144
145   **my_config.json example**
146
147   ```json
148   {
149     "path": "DB00/TBL00",
150     "type": "rdb",
151     "scope": "application"
152   }
153   ```
154
155### Data Consumer Application
156
157
1581. Import dependencies.
159
160   ```ts
161   import { dataShare, dataSharePredicates, ValuesBucket } from '@kit.ArkData';
162   import { UIAbility } from '@kit.AbilityKit';
163   import { window } from '@kit.ArkUI';
164   import { BusinessError } from '@kit.BasicServicesKit'
165   ```
166
1672. Define the URI string for communicating with the data provider.
168
169   ```ts
170   let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/test');
171   ```
172
1733. Create a **DataShareHelper** instance.
174
175   ```ts
176   let dsHelper: dataShare.DataShareHelper | undefined = undefined;
177   let abilityContext: Context;
178
179   export default class EntryAbility extends UIAbility {
180     onWindowStageCreate(windowStage: window.WindowStage) {
181       abilityContext = this.context;
182       dataShare.createDataShareHelper(abilityContext, dseUri, {
183         isProxy: true
184       }, (err, data) => {
185         dsHelper = data;
186       });
187     }
188   }
189   ```
190
1914. Use the **DataShareHelper** APIs to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
192
193   ```ts
194   // Construct a piece of data.
195   let key1 = 'name';
196   let key2 = 'age';
197   let key3 = 'isStudent';
198   let key4 = 'Binary';
199   let valueName1 = 'ZhangSan';
200   let valueName2 = 'LiSi';
201   let valueAge1 = 21;
202   let valueAge2 = 18;
203   let valueIsStudent1 = false;
204   let valueIsStudent2 = true;
205   let valueBinary = new Uint8Array([1, 2, 3]);
206   let valuesBucket: ValuesBucket = { key1: valueName1, key2: valueAge1, key3: valueIsStudent1, key4: valueBinary };
207   let updateBucket: ValuesBucket = { key1: valueName2, key2: valueAge2, key3: valueIsStudent2, key4: valueBinary };
208   let predicates = new dataSharePredicates.DataSharePredicates();
209   let valArray = ['*'];
210   if (dsHelper != undefined) {
211     // Insert a piece of data.
212     (dsHelper as dataShare.DataShareHelper).insert(dseUri, valuesBucket, (err, data) => {
213       console.info(`dsHelper insert result:${data}`);
214     });
215     // Update data.
216     (dsHelper as dataShare.DataShareHelper).update(dseUri, predicates, updateBucket, (err, data) => {
217       console.info(`dsHelper update result:${data}`);
218     });
219     // Query data.
220     (dsHelper as dataShare.DataShareHelper).query(dseUri, predicates, valArray, (err, data) => {
221       console.info(`dsHelper query result:${data}`);
222     });
223     // Delete data.
224     (dsHelper as dataShare.DataShareHelper).delete(dseUri, predicates, (err, data) => {
225       console.info(`dsHelper delete result:${data}`);
226     });
227   }
228   ```
229
2305. Subscribe to data.
231
232   ```ts
233   function onCallback(err: BusinessError, node: dataShare.RdbDataChangeNode) {
234     console.info("uri " + JSON.stringify(node.uri));
235     console.info("templateId " + JSON.stringify(node.templateId));
236     console.info("data length " + node.data.length);
237     for (let i = 0; i < node.data.length; i++) {
238       console.info("data " + node.data[i]);
239     }
240   }
241
242   let key21: string = "p1";
243   let value21: string = "select * from TBL00";
244   let key22: string = "p2";
245   let value22: string = "select name from TBL00";
246   let template: dataShare.Template = {
247     predicates: {
248       key21: value21,
249       key22: value22,
250     },
251     scheduler: ""
252   }
253   if(dsHelper != undefined)
254   {
255     (dsHelper as dataShare.DataShareHelper).addTemplate(dseUri, "111", template);
256   }
257   let templateId: dataShare.TemplateId = {
258     subscriberId: "111",
259     bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient"
260   }
261   if(dsHelper != undefined) {
262     // When DatamgrService modifies data, onCallback is invoked to return the data queried based on the rules in the template.
263     let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("rdbDataChange", [dseUri], templateId, onCallback);
264   }
265   ```
266
267## Accessing Process Data
268
269The following walks you through on how to host process data.
270
271### (Optional) Data Provider Application
272
273In 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).
274
275> **NOTE**
276>
277> - The configuration of **proxyData** is optional.
278> - If **proxyData** is not configured, the hosted data cannot be accessed by other applications.
279> - 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.
280
281**Table 3** proxyData in module.json5
282
283| Name                   | Description                         | Mandatory  |
284| ----------------------- | ----------------------------- | ---- |
285| uri                     | URI of the data proxy, which is the unique identifier for cross-application data access.      | Yes   |
286| 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).| No   |
287| 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).| No   |
288
289**module.json5 example**
290
291```json
292"proxyData": [
293  {
294    "uri": "datashareproxy://com.acts.ohos.data.datasharetest/weather",
295    "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO",
296    "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING"
297  }
298]
299```
300
301### Data Consumer Application
302
3031. Import dependencies.
304
305   ```ts
306   import { dataShare } from '@kit.ArkData';
307   import { UIAbility } from '@kit.AbilityKit';
308   import { window } from '@kit.ArkUI';
309   import { BusinessError } from '@kit.BasicServicesKit';
310   ```
311
3122. Define the URI string for communicating with the data provider.
313
314   ```ts
315   let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/weather');
316   ```
317
3183. Create a **DataShareHelper** instance.
319
320   ```ts
321   let dsHelper: dataShare.DataShareHelper | undefined = undefined;
322   let abilityContext: Context;
323
324   export default class EntryAbility extends UIAbility {
325     onWindowStageCreate(windowStage: window.WindowStage) {
326       abilityContext = this.context;
327       dataShare.createDataShareHelper(abilityContext, dseUri, {isProxy : true}, (err, data) => {
328         dsHelper = data;
329       });
330     }
331   }
332   ```
333
3344. Use the **DataShareHelper** APIs to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
335
336   ```ts
337   // Construct two pieces of data. The first data is not configured with proxyDatas and cannot be accessed by other applications.
338   let data : Array<dataShare.PublishedItem> = [
339     {key:"city", subscriberId:"11", data:"xian"},
340     {key:"datashareproxy://com.acts.ohos.data.datasharetest/weather", subscriberId:"11", data:JSON.stringify("Qing")}];
341   // Publish data.
342   if (dsHelper != undefined) {
343     let result: Array<dataShare.OperationResult> = await (dsHelper as dataShare.DataShareHelper).publish(data, "com.acts.ohos.data.datasharetestclient");
344   }
345   ```
346
3475. Subscribe to data.
348
349   ```ts
350   function onPublishCallback(err: BusinessError, node:dataShare.PublishedDataChangeNode) {
351     console.info("onPublishCallback");
352   }
353   let uris:Array<string> = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/weather"];
354   if (dsHelper != undefined) {
355     let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("publishedDataChange", uris, "11", onPublishCallback);
356   }
357   ```
358
359## Accessing Dynamic Data
360
361Only the data provider is involved. The following walks you through on how to dynamically enable silent access.
362
363### Data Provider Application
364
365The 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).
366
367> **NOTE**
368>
369> - In the **data_share_config.json** file, the default value of **isSilentProxyEnable** is **true**, which means silent access is enabled.
370> - 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.
371> - If **enableSilentProxy** or **disableSilentProxy** has not been called, the value of **isSilentProxyEnable** in the **data_share_config.json** file is preferentially checked.
372> - 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.
373
3741. Import dependencies.
375
376   ```ts
377   import { dataShare } from '@kit.ArkData';
378   import { UIAbility } from '@kit.AbilityKit';
379   import { window } from '@kit.ArkUI';
380   ```
381
3822. Define the URI string for communicating with the data provider.
383
384   ```ts
385   let dseUri = ('datashare:///com.acts.datasharetest/entry/DB00/TBL00');
386   ```
387
3883. Create a **DataShareHelper** instance.
389
390   ```ts
391   let abilityContext: Context;
392
393   export default class EntryAbility extends UIAbility {
394     onWindowStageCreate(windowStage: window.WindowStage) {
395       abilityContext = this.context;
396       dataShare.enableSilentProxy(abilityContext, dseUri);
397     }
398   }
399   ```
400