share-data-by-silent-access.md 13.6 KB
Newer Older
H
f  
hanlu 已提交
1
# 通过数据管理服务实现数据共享静默访问
G
ge-yafang 已提交
2 3 4 5


## 场景介绍

H
f  
hanlu 已提交
6
典型跨应用访问数据的用户场景下,数据提供方会存在多次被拉起的情况。
G
ge-yafang 已提交
7

H
f  
hanlu 已提交
8
为了降低数据提供方拉起次数,提高访问速度,OpenHarmony提供了一种不拉起数据提供方直接访问数据库的方式,即静默数据访问。
G
ge-yafang 已提交
9

H
f  
hanlu 已提交
10
静默数据访问通过数据管理服务进行数据的访问和修改,无需拉起数据提供方。
G
ge-yafang 已提交
11

H
f  
hanlu 已提交
12
数据管理服务仅支持数据库的基本访问或数据托管,如果有业务处理,需要将业务处理封装成接口,给数据访问方调用。
H
f  
hanlu 已提交
13

H
f  
hanlu 已提交
14
如果业务过于复杂,无法放到数据访问方,建议通过DataShareExtensionAbility拉起数据提供方实现功能。
H
f  
hanlu 已提交
15

G
ge-yafang 已提交
16 17 18

## 运作机制

H
f  
hanlu 已提交
19
可以通过数据管理服务进行代理访问的数据分为以下两种:
H
f  
hanlu 已提交
20

H
f  
hanlu 已提交
21
- 持久化数据:归属于数据提供方的数据库,这类数据存储于数据提供方的沙箱,可以在数据提供方中通过声明的方式进行共享,按表为粒度配置为可以被其他应用访问的数据表。
H
f  
hanlu 已提交
22 23


H
f  
hanlu 已提交
24
- 过程数据:托管在数据管理服务上的过程数据,这类数据存储于数据管理服务的沙箱,格式为json或byte数据,无人订阅10天后自动删除。
H
f  
hanlu 已提交
25 26


H
f  
hanlu 已提交
27 28 29 30 31 32 33 34
| 数据类型  | 存储位置      | 数据格式        | 有效期          | 适用场景                              |
| ----- | --------- | ----------- | ------------ | --------------------------------- |
| 持久化数据 | 数据提供方的沙箱  | 数据库中的数据表    | 永久存储         | 适用于数据格式类似关系型数据库的相关场景,如日程,会议等      |
| 过程数据  | 数据管理服务的沙箱 | json或byte数据 | 无人订阅10天后自动删除 | 适用于数据有时效性且数据格式较简单的相关场景,如步数,天气,心率等 |



图1 静默数据访问视图
G
ge-yafang 已提交
35 36 37 38 39 40

![silent_dataShare](figures/silent_dataShare.jpg)

- 和跨应用数据共享方式不同的是,静默数据访问借助数据管理服务通过目录映射方式直接读取数据提供方的配置,按规则进行预处理后,并访问数据库。

- 数据访问方如果使用静默数据访问方式,URI需严格按照如下格式:
H
f  
hanlu 已提交
41
  datashareproxy://{bundleName}/{dataPath}
G
ge-yafang 已提交
42 43 44

  数据管理服务会读取对应bundleName作为数据提供方应用,读取配置,进行权限校验并访问对应数据。

H
f  
hanlu 已提交
45
  dataPath为数据标识,可以自行定义,在同一个数据提供方应用中需要保持唯一。
G
ge-yafang 已提交
46 47


H
f  
hanlu 已提交
48
## 约束与限制
G
ge-yafang 已提交
49

H
f  
hanlu 已提交
50
- 目前持久化数据中仅关系型数据库支持静默数据访问方式。
G
ge-yafang 已提交
51
- 整个系统最多同时并发16路查询,有多出来的查询请求需要排队处理。
H
f  
hanlu 已提交
52
- 持久化数据不支持代理创建数据库,如果需要创建数据库,需要拉起数据提供方。
H
f  
hanlu 已提交
53
- 数据提供方如果是normal级别签名的应用,配置的数据读写权限必须为system_basic及以上权限。
H
f  
hanlu 已提交
54 55 56 57 58 59


## 接口说明

以下是静默数据访问的相关接口,大部分为异步接口。异步接口均有callback和Promise两种返回形式,下表均以callback形式为例,更多接口及使用方式请见[数据共享](../reference/apis/js-apis-data-dataShare.md)

H
f  
hanlu 已提交
60
### 通用接口
H
f  
hanlu 已提交
61 62 63 64 65

| 接口名称                                     | 描述                   |
| ---------------------------------------- | -------------------- |
| createDataShareHelper(context: Context, uri: string, options: DataShareHelperOptions, callback: AsyncCallback<DataShareHelper>): void | 创建DataShareHelper实例。 |

H
f  
hanlu 已提交
66
### 持久化数据
H
f  
hanlu 已提交
67 68 69 70 71

| 接口名称                                     | 描述                   |
| ---------------------------------------- | -------------------- |
| insert(uri: string, value: ValuesBucket, callback: AsyncCallback<number>): void | 向目标表中插入一行数据。         |
| delete(uri: string, predicates: dataSharePredicates.DataSharePredicates, callback: AsyncCallback<number>): void | 从数据库中删除一条或多条数据记录。    |
H
f  
hanlu 已提交
72 73
| query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array<string>, callback: AsyncCallback<DataShareResultSet>): void | 查询数据库中的数据。           |
| update(uri: string, predicates: dataSharePredicates.DataSharePredicates, value: ValuesBucket, callback: AsyncCallback<number>): void | 更新数据库中的数据记录。         |
H
f  
hanlu 已提交
74 75 76
| addTemplate(uri: string, subscriberId: string, template: Template): void | 添加一个指定订阅者的数据模板。      |
| on(type: 'rdbDataChange', uris: Array<string>, templateId: TemplateId, callback: AsyncCallback<RdbDataChangeNode>): Array<OperationResult | 订阅指定URI和模板对应的数据变更事件。 |

H
f  
hanlu 已提交
77
### 过程数据
H
f  
hanlu 已提交
78 79 80 81 82 83 84 85 86 87 88 89 90 91

| 接口名称                                     | 描述                 |
| ---------------------------------------- | ------------------ |
| publish(data: Array<PublishedItem>, bundleName: string, version: number, callback: AsyncCallback<Array<OperationResult>>): void | 发布数据,将数据托管至数据管理服务。 |
| on(type: 'publishedDataChange', uris: Array<string>, subscriberId: string, callback: AsyncCallback<PublishedDataChangeNode>): Array<OperationResult> | 订阅已发布数据的数据变更通知。    |



## 持久化数据实现说明

首先,以共享一个关系型数据库为例,说明开发步骤。

### 数据提供方应用的开发

H
f  
hanlu 已提交
92
1. 数据提供方需要在module.json5中的proxyDatas节点定义要共享的表的标识,读写权限和基本信息。
H
f  
hanlu 已提交
93

H
f  
hanlu 已提交
94
   **表1** module.json5中proxyDatas节点对应的属性字段
H
f  
hanlu 已提交
95 96 97 98

   | 属性名称                    | 备注说明                                     | 必填   |
   | ----------------------- | ---------------------------------------- | ---- |
   | uri                     | 数据使用的URI,是跨应用数据访问的唯一标识。                  | 是    |
N
fix  
niudongyao 已提交
99 100
   | requiredReadPermission  | 标识从该数据代理读取数据时所需要的权限,不配置默认不允许其他APP访问数据。支持权限可参考[权限列表](../security/permission-list.md)。            | 否    |
   | requiredWritePermission | 标识从该数据代理修改数据时所需要的权限,不配置默认不允许其他APP修改数据。支持权限可参考[权限列表](../security/permission-list.md)。          | 否    |
H
f  
hanlu 已提交
101 102
   | metadata                | 数据源的信息,包含name和resource字段。<br /> name类型固定为"dataProperties",是配置的唯一标识。 <br /> resource类型固定为"$profile:{fileName}",表示配置文件的名称为{fileName}.json。 | 是    |

H
f  
hanlu 已提交
103
   **module.json5配置样例:**
H
f  
hanlu 已提交
104 105

   ```json
H
f  
hanlu 已提交
106 107 108 109
   "proxyDatas":[
     {
       "uri": "datashareproxy://com.acts.ohos.data.datasharetest/test",
       "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO",
N
fix  
niudongyao 已提交
110
       "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING",
H
f  
hanlu 已提交
111 112 113 114 115 116
       "metadata": {
         "name": "dataProperties",
         "resource": "$profile:my_config"
       }
     }
   ]
H
f  
hanlu 已提交
117
   ```
H
f  
hanlu 已提交
118
   **表2** my_config.json对应属性字段
H
f  
hanlu 已提交
119

H
f  
hanlu 已提交
120 121 122 123 124
   | 属性名称  | 备注说明                                     | 必填   |
   | ----- | ---------------------------------------- | ---- |
   | path  | 指定数据源路径,目前支持关系型数据库,配置为库名/表名              | 是    |
   | type  | 标识数据库类型,目前支持配置为rdb,表示关系型数据库。             | 是    |
   | scope | 数据库所在范围。<br>1.module表示数据库位于本模块下;<br>2.application表示数据库位于本应用下。 | 否    |
H
f  
hanlu 已提交
125

H
f  
hanlu 已提交
126
   **my_config.json配置样例**
H
f  
hanlu 已提交
127 128

   ```json
H
f  
hanlu 已提交
129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
   {
     "path": "DB00/TBL00",
     "type": "rdb",
     "scope": "application"
   }
   ```

### 数据访问方应用的开发


1. 导入基础依赖包。

   ```js
   import dataShare from '@ohos.data.dataShare';
   import dataSharePredicates from '@ohos.data.dataSharePredicates';
H
f  
hanlu 已提交
144 145
   ```

H
f  
hanlu 已提交
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226
2. 定义与数据提供方通信的URI字符串。

   ```js
   let dseUri = ('datashareproxy://com.acts.ohos.data.datasharetest/test');
   ```

3. 创建工具接口类对象。

   ```js
   let dsHelper;
   let abilityContext;

   export default class EntryAbility extends UIAbility {
     onWindowStageCreate(windowStage) {
       abilityContext = this.context;
       dataShare.createDataShareHelper(abilityContext, "", {
         isProxy: true
       }, (err, data) => {
         dsHelper = data;
       });
     }
   }
   ```

4. 获取到接口类对象后,便可利用其提供的接口访问提供方提供的服务,如进行数据的增、删、改、查等。

   ```js
   // 构建一条数据
   let valuesBucket = {
     'name': 'ZhangSan', 'age': 21, 'isStudent': false, 'Binary': new Uint8Array([1, 2, 3])
   };
   let updateBucket = {
     'name': 'LiSi', 'age': 18, 'isStudent': true, 'Binary': new Uint8Array([1, 2, 3])
   };
   let predicates = new dataSharePredicates.DataSharePredicates();
   let valArray = ['*'];
   // 插入一条数据
   dsHelper.insert(dseUri, valuesBucket, (err, data) => {
     console.info(`dsHelper insert result:${data}`);
   });
   // 更新数据
   dsHelper.update(dseUri, predicates, updateBucket, (err, data) => {
     console.info(`dsHelper update result:${data}`);
   });
   // 查询数据
   dsHelper.query(dseUri, predicates, valArray, (err, data) => {
     console.info(`dsHelper query result:${data}`);
   });
   // 删除指定的数据
   dsHelper.delete(dseUri, predicates, (err, data) => {
     console.info(`dsHelper delete result:${data}`);
   });
   ```

5. 对指定的数据进行订阅。

   ```js
   function onCallback(err, node: dataShare.RdbDataChangeNode) {
       console.info("uri " + JSON.stringify(node.uri));
       console.info("templateId " + JSON.stringify(node.templateId));
       console.info("data length " + node.data.length);
       for (let i = 0; i < node.data.length; i++) {
           console.info("data " + node.data[i]);
       }
   }

   let template = {
       predicates: {
           "p1": "select * from TBL00",
           "p2": "select name from TBL00",
       },
       scheduler: ""
   }
   dsProxyHelper.addTemplate(dseUri, "111", template);
   let templateId: dataShare.TemplateId = {
       subscriberId: "111",
       bundleNameOfOwner: "com.acts.ohos.data.datasharetestclient"
   }
   // 使用数据管理服务修改数据时触发onCallback回调,回调内容是template中的规则查到的数据
   let result: Array<dataShare.OperationResult> = dsProxyHelper.on("rdbDataChange", [dseUri], templateId, onCallback);
   ```
H
f  
hanlu 已提交
227 228 229

## 过程数据实现说明

H
f  
hanlu 已提交
230
以托管一份过程数据为例,说明开发步骤。
H
f  
hanlu 已提交
231 232 233

### 数据提供方应用的开发(可选)

H
f  
hanlu 已提交
234
数据提供方需要在module.json5中的proxyDatas节点定义过程数据的标识,读写权限和基本信息。
H
f  
hanlu 已提交
235

H
f  
hanlu 已提交
236
> 注意:
H
f  
hanlu 已提交
237
>
H
f  
hanlu 已提交
238 239 240
> - 该步骤为可选,可以不对module.json5中的proxyDatas进行配置。
> - 不配置proxyDatas时,托管数据不允许其他应用访问。
> - 不配置proxyDatas时,数据标识可以为简写,发布、订阅、查询数据可以使用简写的数据标识,如weather,可以不用全写为datashareproxy://com.acts.ohos.data.datasharetest/weather
H
f  
hanlu 已提交
241

H
f  
hanlu 已提交
242
**表3** module.json5中proxyDatas节点对应的属性字段
H
f  
hanlu 已提交
243 244 245 246

| 属性名称                    | 备注说明                          | 必填   |
| ----------------------- | ----------------------------- | ---- |
| uri                     | 数据使用的URI,是跨应用数据访问的唯一标识。       | 是    |
N
fix  
niudongyao 已提交
247 248
| requiredReadPermission  | 标识从该数据代理读取数据时所需要的权限,不配置默认不允许其他APP访问数据。支持权限可参考[权限列表](../security/permission-list.md)。 | 否    |
| requiredWritePermission | 标识从该数据代理修改数据时所需要的权限,不配置默认不允许其他APP访问数据。支持权限可参考[权限列表](../security/permission-list.md)。 | 否    |
H
f  
hanlu 已提交
249

H
f  
hanlu 已提交
250
**module.json5配置样例:**
H
f  
hanlu 已提交
251 252

```json
H
f  
hanlu 已提交
253 254 255 256
"proxyDatas": [
  {
    "uri": "datashareproxy://com.acts.ohos.data.datasharetest/weather",
    "requiredReadPermission": "ohos.permission.GET_BUNDLE_INFO",
N
fix  
niudongyao 已提交
257
    "requiredWritePermission": "ohos.permission.KEEP_BACKGROUND_RUNNING"
H
f  
hanlu 已提交
258 259
  }
]
H
f  
hanlu 已提交
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278
```

### 数据访问方应用的开发

1. 导入基础依赖包。

   ```js
   import dataShare from '@ohos.data.dataShare';
   ```

2. 创建工具接口类对象。

   ```js
   let dsHelper;
   let abilityContext;

   export default class EntryAbility extends UIAbility {
     onWindowStageCreate(windowStage) {
       abilityContext = this.context;
H
f  
hanlu 已提交
279
       dataShare.createDataShareHelper(abilityContext, "", {isProxy : true}, (err, data) => {
H
f  
hanlu 已提交
280 281 282 283 284
         dsHelper = data;
       });
     }
   }
   ```
G
ge-yafang 已提交
285

H
f  
hanlu 已提交
286
3. 获取到接口类对象后,便可利用其提供的接口访问提供方提供的服务,如进行数据的增、删、改、查等。
G
ge-yafang 已提交
287

H
f  
hanlu 已提交
288
   ```js
H
f  
hanlu 已提交
289
   // 构建两条数据,第一条为免配置的数据,仅自己使用
H
f  
hanlu 已提交
290 291 292 293 294 295
   let data : Array<dataShare.PublishedItem> = [
     {key:"city", subscriberId:"11", data:"xian"},
     {key:"datashareproxy://com.acts.ohos.data.datasharetest/weather", subscriberId:"11", data:JSON.stringify("Qing")}];
   // 发布数据
    let result: Array<dataShare.OperationResult> = await dsProxyHelper.publish(data, "com.acts.ohos.data.datasharetestclient");
   ```
G
ge-yafang 已提交
296

H
f  
hanlu 已提交
297
4. 对指定的数据进行订阅。
G
ge-yafang 已提交
298

H
f  
hanlu 已提交
299 300 301 302 303 304 305
   ```js
   function onPublishCallback(err, node:dataShare.PublishedDataChangeNode) {
       console.info("onPublishCallback");
   }
   let uris:Array<string> = ["city", "datashareproxy://com.acts.ohos.data.datasharetest/weather"];
   let result: Array<dataShare.OperationResult> = dsProxyHelper.on("publishedDataChange", uris, "11", onPublishCallback);
   ```
G
ge-yafang 已提交
306

H
f  
hanlu 已提交
307

G
ge-yafang 已提交
308