• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# 通过数据管理服务实现数据共享静默访问
2
3
4## 场景介绍
5
6典型跨应用访问数据的用户场景下,数据提供方会存在多次被拉起的情况。
7
8为了降低数据提供方拉起次数,提高访问速度,OpenHarmony提供了一种不拉起数据提供方直接访问数据库的方式,即静默数据访问。
9
10静默数据访问通过数据管理服务进行数据的访问和修改,无需拉起数据提供方。
11
12数据管理服务仅支持数据库的基本访问或数据托管,如果有业务处理,需要将业务处理封装成接口,给数据访问方调用。
13
14如果业务过于复杂,无法放到数据访问方,建议通过[DataShareExtensionAbility](../reference/apis/js-apis-application-dataShareExtensionAbility.md)拉起数据提供方实现功能。
15
16
17## 运作机制
18
19可以通过数据管理服务进行代理访问的数据分为以下两种:
20
21- 持久化数据:归属于数据提供方的数据库,这类数据存储于数据提供方的沙箱,可以在数据提供方中通过声明的方式进行共享,按表为粒度配置为可以被其他应用访问的数据表。
22
23
24- 过程数据:托管在数据管理服务上的过程数据,这类数据存储于数据管理服务的沙箱,格式为json或byte数据,无人订阅10天后自动删除。
25
26
27| 数据类型  | 存储位置      | 数据格式        | 有效期          | 适用场景                              |
28| ----- | --------- | ----------- | ------------ | --------------------------------- |
29| 持久化数据 | 数据提供方的沙箱  | 数据库中的数据表    | 永久存储         | 适用于数据格式类似关系型数据库的相关场景,如日程,会议等      |
30| 过程数据  | 数据管理服务的沙箱 | json或byte数据 | 无人订阅10天后自动删除 | 适用于数据有时效性且数据格式较简单的相关场景,如步数,天气,心率等 |
31
3233
34图1 静默数据访问视图
35
36![silent_dataShare](figures/silent_dataShare.jpg)
37
38- 和跨应用数据共享方式不同的是,静默数据访问借助数据管理服务通过目录映射方式直接读取数据提供方的配置,按规则进行预处理后,并访问数据库。
39
40- 数据访问方如果使用静默数据访问方式,URI需严格按照如下格式:
41  datashareproxy://{bundleName}/{dataPath}
42
43  数据管理服务会读取对应bundleName作为数据提供方应用,读取配置,进行权限校验并访问对应数据。
44
45  dataPath为数据标识,可以自行定义,在同一个数据提供方应用中需要保持唯一。
46
47
48## 约束与限制
49
50- 目前持久化数据中仅关系型数据库支持静默数据访问方式。
51- 整个系统最多同时并发16路查询,有多出来的查询请求需要排队处理。
52- 持久化数据不支持代理创建数据库,如果需要创建数据库,需要拉起数据提供方。
53- 数据提供方如果是normal级别签名的应用,配置的数据读写权限必须为system_basic及以上权限。
54
55
56## 接口说明
57
58以下是静默数据访问的相关接口,大部分为异步接口。异步接口均有callback和Promise两种返回形式,下表均以callback形式为例,更多接口及使用方式请见[数据共享](../reference/apis/js-apis-data-dataShare.md)。
59
60### 通用接口
61
62| 接口名称                                     | 描述                   |
63| ---------------------------------------- | -------------------- |
64| createDataShareHelper(context: Context, uri: string, options: DataShareHelperOptions, callback: AsyncCallback<DataShareHelper>): void | 创建DataShareHelper实例。 |
65
66### 持久化数据
67
68| 接口名称                                     | 描述                   |
69| ---------------------------------------- | -------------------- |
70| insert(uri: string, value: ValuesBucket, callback: AsyncCallback<number>): void | 向目标表中插入一行数据。         |
71| delete(uri: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback<number>): void | 从数据库中删除一条或多条数据记录。    |
72| query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array<string>, callback: AsyncCallback<DataShareResultSet>): void | 查询数据库中的数据。           |
73| update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback<number>): void | 更新数据库中的数据记录。         |
74| addTemplate(uri: string, subscriberId: string, template: Template): void | 添加一个指定订阅者的数据模板。      |
75| on(type: 'rdbDataChange', uris: Array<string>, templateId: TemplateId, callback: AsyncCallback<RdbDataChangeNode>): Array<OperationResult | 订阅指定URI和模板对应的数据变更事件。 |
76
77### 过程数据
78
79| 接口名称                                     | 描述                 |
80| ---------------------------------------- | ------------------ |
81| publish(data: Array<PublishedItem>, bundleName: string, version: number, callback: AsyncCallback<Array<OperationResult>>): void | 发布数据,将数据托管至数据管理服务。 |
82| on(type: 'publishedDataChange', uris: Array<string>, subscriberId: string, callback: AsyncCallback<PublishedDataChangeNode>): Array<OperationResult> | 订阅已发布数据的数据变更通知。    |
83
84
85
86## 持久化数据实现说明
87
88首先,以共享一个关系型数据库为例,说明开发步骤。
89
90### 数据提供方应用的开发
91
921. 数据提供方需要在module.json5中的proxyDatas节点定义要共享的表的标识,读写权限和基本信息。
93
94   **表1** module.json5中proxyDatas节点对应的属性字段
95
96   | 属性名称                    | 备注说明                                     | 必填   |
97   | ----------------------- | ---------------------------------------- | ---- |
98   | uri                     | 数据使用的URI,是跨应用数据访问的唯一标识。                  | 是    |
99   | requiredReadPermission  | 标识从该数据代理读取数据时所需要的权限,不配置默认不允许其他APP访问数据。支持权限可参考[权限列表](../security/permission-list.md)。            | 否    |
100   | requiredWritePermission | 标识从该数据代理修改数据时所需要的权限,不配置默认不允许其他APP修改数据。支持权限可参考[权限列表](../security/permission-list.md)。          | 否    |
101   | metadata                | 数据源的信息,包含name和resource字段。<br /> name类型固定为"dataProperties",是配置的唯一标识。 <br /> resource类型固定为"$profile:{fileName}",表示配置文件的名称为{fileName}.json。 | 是    |
102
103   **module.json5配置样例:**
104
105   ```json
106   "proxyDatas":[
107     {
108       "uri": "datashareproxy://com.acts.ohos.data.datasharetest/test",
109       "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO",
110       "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING",
111       "metadata": {
112         "name": "dataProperties",
113         "resource": "$profile:my_config"
114       }
115     }
116   ]
117   ```
118   **表2** my_config.json对应属性字段
119
120   | 属性名称  | 备注说明                                     | 必填   |
121   | ----- | ---------------------------------------- | ---- |
122   | path  | 指定数据源路径,目前支持关系型数据库,配置为库名/表名              | 是    |
123   | type  | 标识数据库类型,目前支持配置为rdb,表示关系型数据库。             | 是    |
124   | scope | 数据库所在范围。<br>1.module表示数据库位于本模块下;<br>2.application表示数据库位于本应用下。 | 否    |
125
126   **my_config.json配置样例**
127
128   ```json
129   {
130     "path": "DB00/TBL00",
131     "type": "rdb",
132     "scope": "application"
133   }
134   ```
135
136### 数据访问方应用的开发
137
138
1391. 导入基础依赖包。
140
141   ```ts
142   import dataShare from '@ohos.data.dataShare';
143   import dataSharePredicates from '@ohos.data.dataSharePredicates';
144   import UIAbility from '@ohos.app.ability.UIAbility'
145   import { ValuesBucket } from '@ohos.data.ValuesBucket'
146   import window from '@ohos.window'
147   import { BusinessError } from '@ohos.base'
148   ```
149
1502. 定义与数据提供方通信的URI字符串。
151
152   ```ts
153   let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/test');
154   ```
155
1563. 创建工具接口类对象。
157
158   ```ts
159   let dsHelper: dataShare.DataShareHelper | undefined = undefined;
160   let abilityContext: Context;
161
162   export default class EntryAbility extends UIAbility {
163     onWindowStageCreate(windowStage: window.WindowStage) {
164       abilityContext = this.context;
165       dataShare.createDataShareHelper(abilityContext, "", {
166         isProxy: true
167       }, (err, data) => {
168         dsHelper = data;
169       });
170     }
171   }
172   ```
173
1744. 获取到接口类对象后,便可利用其提供的接口访问提供方提供的服务,如进行数据的增、删、改、查等。
175
176   ```ts
177   // 构建一条数据
178   let key1 = 'name';
179   let key2 = 'age';
180   let key3 = 'isStudent';
181   let key4 = 'Binary';
182   let valueName1 = 'ZhangSan';
183   let valueName2 = 'LiSi';
184   let valueAge1 = 21;
185   let valueAge2 = 18;
186   let valueIsStudent1 = false;
187   let valueIsStudent2 = true;
188   let valueBinary = new Uint8Array([1, 2, 3]);
189   let valuesBucket: ValuesBucket = { key1: valueName1, key2: valueAge1, key3: valueIsStudent1, key4: valueBinary };
190   let updateBucket: ValuesBucket = { key1: valueName2, key2: valueAge2, key3: valueIsStudent2, key4: valueBinary };
191   let predicates = new dataSharePredicates.DataSharePredicates();
192   let valArray = ['*'];
193   if (dsHelper != undefined) {
194     // 插入一条数据
195     (dsHelper as dataShare.DataShareHelper).insert(dseUri, valuesBucket, (err, data) => {
196       console.info(`dsHelper insert result:${data}`);
197     });
198     // 更新数据
199     (dsHelper as dataShare.DataShareHelper).update(dseUri, predicates, updateBucket, (err, data) => {
200       console.info(`dsHelper update result:${data}`);
201     });
202     // 查询数据
203     (dsHelper as dataShare.DataShareHelper).query(dseUri, predicates, valArray, (err, data) => {
204       console.info(`dsHelper query result:${data}`);
205     });
206     // 删除指定的数据
207     (dsHelper as dataShare.DataShareHelper).delete(dseUri, predicates, (err, data) => {
208       console.info(`dsHelper delete result:${data}`);
209     });
210   }
211   ```
212
2135. 对指定的数据进行订阅。
214
215   ```ts
216   function onCallback(err: BusinessError, node: dataShare.RdbDataChangeNode) {
217     console.info("uri " + JSON.stringify(node.uri));
218     console.info("templateId " + JSON.stringify(node.templateId));
219     console.info("data length " + node.data.length);
220     for (let i = 0; i < node.data.length; i++) {
221       console.info("data " + node.data[i]);
222     }
223   }
224
225   let key21: string = "p1";
226   let value21: string = "select * from TBL00";
227   let key22: string = "p2";
228   let value22: string = "select name from TBL00";
229   let template: dataShare.Template = {
230     predicates: {
231       key21: value21,
232       key22: value22,
233     },
234     scheduler: ""
235   }
236   if(dsHelper != undefined)
237   {
238     (dsHelper as dataShare.DataShareHelper).addTemplate(dseUri, "111", template);
239   }
240   let templateId: dataShare.TemplateId = {
241     subscriberId: "111",
242     bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient"
243   }
244   if(dsHelper != undefined) {
245     // 使用数据管理服务修改数据时触发onCallback回调,回调内容是template中的规则查到的数据
246     let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("rdbDataChange", [dseUri], templateId, onCallback);
247   }
248   ```
249
250## 过程数据实现说明
251
252以托管一份过程数据为例,说明开发步骤。
253
254### 数据提供方应用的开发(可选)
255
256数据提供方需要在module.json5中的proxyDatas节点定义过程数据的标识,读写权限和基本信息。
257
258> 注意:
259>
260> - 该步骤为可选,可以不对module.json5中的proxyDatas进行配置。
261> - 不配置proxyDatas时,托管数据不允许其他应用访问。
262> - 不配置proxyDatas时,数据标识可以为简写,发布、订阅、查询数据可以使用简写的数据标识,如weather,可以不用全写为datashareproxy://com.acts.ohos.data.datasharetest/weather
263
264**表3** module.json5中proxyDatas节点对应的属性字段
265
266| 属性名称                    | 备注说明                          | 必填   |
267| ----------------------- | ----------------------------- | ---- |
268| uri                     | 数据使用的URI,是跨应用数据访问的唯一标识。       | 是    |
269| requiredReadPermission  | 标识从该数据代理读取数据时所需要的权限,不配置默认不允许其他APP访问数据。支持权限可参考[权限列表](../security/permission-list.md)。 | 否    |
270| requiredWritePermission | 标识从该数据代理修改数据时所需要的权限,不配置默认不允许其他APP访问数据。支持权限可参考[权限列表](../security/permission-list.md)。 | 否    |
271
272**module.json5配置样例:**
273
274```json
275"proxyDatas": [
276  {
277    "uri": "datashareproxy://com.acts.ohos.data.datasharetest/weather",
278    "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO",
279    "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING"
280  }
281]
282```
283
284### 数据访问方应用的开发
285
2861. 导入基础依赖包。
287
288   ```ts
289   import dataShare from '@ohos.data.dataShare';
290   import UIAbility from '@ohos.app.ability.UIAbility'
291   import window from '@ohos.window'
292   import { BusinessError } from '@ohos.base'
293   ```
294
2952. 创建工具接口类对象。
296
297   ```ts
298   let dsHelper: dataShare.DataShareHelper | undefined = undefined;
299   let abilityContext: Context;
300
301   export default class EntryAbility extends UIAbility {
302     onWindowStageCreate(windowStage: window.WindowStage) {
303       abilityContext = this.context;
304       dataShare.createDataShareHelper(abilityContext, "", {isProxy : true}, (err, data) => {
305         dsHelper = data;
306       });
307     }
308   }
309   ```
310
3113. 获取到接口类对象后,便可利用其提供的接口访问提供方提供的服务,如进行数据的增、删、改、查等。
312
313   ```ts
314   // 构建两条数据,第一条为免配置的数据,仅自己使用
315   let data : Array<dataShare.PublishedItem> = [
316     {key:"city", subscriberId:"11", data:"xian"},
317     {key:"datashareproxy://com.acts.ohos.data.datasharetest/weather", subscriberId:"11", data:JSON.stringify("Qing")}];
318   // 发布数据
319   if (dsHelper != undefined) {
320     let result: Array<dataShare.OperationResult> = await (dsHelper as dataShare.DataShareHelper).publish(data, "com.acts.ohos.data.datasharetestclient");
321   }
322   ```
323
3244. 对指定的数据进行订阅。
325
326   ```ts
327   function onPublishCallback(err: BusinessError, node:dataShare.PublishedDataChangeNode) {
328     console.info("onPublishCallback");
329   }
330   let uris:Array<string> = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/weather"];
331   if (dsHelper != undefined) {
332     let result: Array<dataShare.OperationResult> = (dsHelper as dataShare.DataShareHelper).on("publishedDataChange", uris, "11", onPublishCallback);
333   }
334   ```
335
336337
338