• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Sharing Data Using DataShareExtensionAbility
2
3
4## When to Use
5
6If complex services are involved in cross-application data access, you can use **DataShareExtensionAbility** to start the application of the data provider to implement data access.
7
8You need to implement flexible service logics via callbacks of the service provider.
9
10
11## Working Principles
12
13There are two roles in **DataShare**:
14
15- Data provider: implements operations, such as adding, deleting, modifying, and querying data, and opening a file, using [DataShareExtensionAbility](../reference/apis/js-apis-application-dataShareExtensionAbility.md).
16
17- Data consumer: accesses the data provided by the provider using [createDataShareHelper()](../reference/apis/js-apis-data-dataShare.md#datasharecreatedatasharehelper).
18
19**Figure 1** Data sharing mechanism
20
21![dataShare](figures/dataShare.jpg)
22
23- The **DataShareExtensionAbility** module, as the data provider, implements services related to data sharing between applications.
24
25- The **DataShareHelper** module, as the data consumer, provides APIs for accessing data, including adding, deleting, modifying, and querying data.
26
27- The data consumer communicates with the data provider via inter-process communication (IPC). The data provider can be implemented through a database or other data storage.
28
29- The **ResultSet** module is implemented through shared memory. Shared memory stores the result sets, and interfaces are provided to traverse result sets.
30
31
32## How to Develop
33
34
35### Data Provider Application Development (Only for System Applications)
36
37[DataShareExtensionAbility](../reference/apis/js-apis-application-dataShareExtensionAbility.md) provides the following APIs. You can override these APIs as required.
38
39- **onCreate**: called by the server to initialize service logic when the DataShare client connects to the DataShareExtensionAbility server.
40
41- **insert**: called to insert data upon the request of the client. Data insertion must be implemented in this callback on the server.
42
43- **update**: called to update data upon the request of the client. Data update must be implemented in this callback on the server.
44
45- **delete**: called to delete data upon the request of the client. Data deletion must be implemented in this callback on the server.
46
47- **query**: called to query data upon the request of the client. Data query must be implemented in this callback on the server.
48
49- **batchInsert**: called to batch insert data upon the request of the client. Batch data insertion must be implemented in this callback on the server.
50
51- **normalizeUri**: converts the URI provided by the client to the URI used by the server.
52
53- **denormalizeUri**: converts the URI used by the server to the initial URI passed by the client.
54
55Before implementing a **DataShare** service, you need to create a **DataShareExtensionAbility** object in the DevEco Studio project as follows:
56
571. In the **ets** directory of the **Module** project, right-click and choose **New > Directory** to create a directory named **DataShareExtAbility**.
58
592. Right-click the **DataShareAbility** directory, and choose **New > ArkTS File** to create a file named **DataShareExtAbility.ets**.
60
613. In the **DataShareExtAbility.ets** file, import the **@ohos.application.DataShareExtensionAbility** module. You can override the service implementation as required. For example, if the data provider provides only the data insertion, deletion, and query services, you can override only these APIs.
62
63   ```ts
64   import Extension from '@ohos.application.DataShareExtensionAbility';
65   import dataSharePredicates from '@ohos.data.dataSharePredicates';
66   import relationalStore from '@ohos.data.relationalStore';
67   import Want from '@ohos.app.ability.Want';
68   import { BusinessError } from '@ohos.base'
69   ```
70
714. Implement the data provider services. For example, implement data storage of the data provider by using a database, reading and writing files, or accessing the network.
72
73   ```ts
74   const DB_NAME = 'DB00.db';
75   const TBL_NAME = 'TBL00';
76   const DDL_TBL_CREATE = "CREATE TABLE IF NOT EXISTS "
77     + TBL_NAME
78     + ' (id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT, age INTEGER, isStudent BOOLEAN, Binary BINARY)';
79
80   let rdbStore: relationalStore.RdbStore;
81   let result: string;
82
83   export default class DataShareExtAbility extends Extension {
84     // Override onCreate().
85     onCreate(want: Want, callback: Function) {
86       result = this.context.cacheDir + '/datashare.txt';
87       // Create an RDB store.
88       relationalStore.getRdbStore(this.context, {
89         name: DB_NAME,
90         securityLevel: relationalStore.SecurityLevel.S1
91       }, (err, data) => {
92         rdbStore = data;
93         rdbStore.executeSql(DDL_TBL_CREATE, [], (err) => {
94           console.info(`DataShareExtAbility onCreate, executeSql done err:${err}`);
95         });
96         if (callback) {
97           callback();
98         }
99       });
100     }
101
102     // Override query().
103     query(uri: string, predicates: dataSharePredicates.DataSharePredicates, columns: Array<string>, callback: Function) {
104       if (predicates === null || predicates === undefined) {
105         console.info('invalid predicates');
106       }
107       try {
108         rdbStore.query(TBL_NAME, predicates, columns, (err, resultSet) => {
109           if (resultSet !== undefined) {
110             console.info(`resultSet.rowCount:${resultSet.rowCount}`);
111           }
112           if (callback !== undefined) {
113             callback(err, resultSet);
114           }
115         });
116       } catch (err) {
117         let code = (err as BusinessError).code;
118         let message = (err as BusinessError).message
119         console.error(`Failed to query. Code:${code},message:${message}`);
120       }
121     }
122     // Override other APIs as required.
123   };
124   ```
125
1265. Define **DataShareExtensionAbility** in **module.json5**.
127
128     **Table 1** Fields in module.json5
129
130   | Field| Description| Mandatory|
131   | -------- | -------- | -------- |
132   | name | Ability name, corresponding to the **ExtensionAbility** class name derived from **Ability**.| Yes|
133   | type | Ability type. The value is **dataShare**, indicating the development is based on the **datashare** template.| Yes|
134   | uri | URI used for communication. It is the unique identifier for the data consumer to connect to the provider.| Yes|
135   | exported | Whether it is visible to other applications. Data sharing is allowed only when the value is **true**.| Yes|
136   | readPermission | Permission required for accessing data. If this parameter is not set, the read permission is not verified by default.| No|
137   | writePermission | Permission required for modifying data. If this parameter is not set, write permission verification is not performed by default.| No|
138   | metadata   | Configuration for silent access, including the **name** and **resource** fields.<br>The **name** field identifies the configuration, which has a fixed value of **ohos.extension.dataShare**.<br>The **resource** field has a fixed value of **$profile:data_share_config**, which indicates that the profile name is **data_share_config.json**.| **metadata** is mandatory when the ability launch type is **singleton**. For details about the ability launch type, see **launchType** in the [Internal Structure of the abilities Attribute](../quick-start/module-structure.md#internal-structure-of-the-abilities-attribute).|
139
140   **module.json5 example**
141
142   ```json
143   "extensionAbilities": [
144     {
145       "srcEntry": "./ets/DataShareExtAbility/DataShareExtAbility.ets",
146       "name": "DataShareExtAbility",
147       "icon": "$media:icon",
148       "description": "$string:description_datashareextability",
149       "type": "dataShare",
150       "uri": "datashare://com.samples.datasharetest.DataShare",
151       "exported": true,
152       "metadata": [{"name": "ohos.extension.dataShare", "resource": "$profile:data_share_config"}]
153     }
154   ]
155   ```
156
157   **Table 2** Fields in the data_share_config.json file
158
159   | Field           | Description                                                    | Mandatory|
160   | ------------------- | ------------------------------------------------------------ | ---- |
161   | tableConfig         | Label configuration.                                                  | Yes  |
162   | uri                 | Range for which the configuration takes effect. The URI supports the following formats in descending order by priority:<br>- *: indicates all databases and tables.<br>- **datashare:///{bundleName}/{moduleName}/{storeName}**: specifies a database.<br>- **datashare:///{bundleName}/{moduleName}/{storeName}/{tableName}**: specifies a table.<br>If URIs of different formats are configured, only the URI with higher priority takes effect. | Yes  |
163   | crossUserMode       | Whether data is shared by multiple users.<br>The value **1** means to share data between multiple users, and the value **2** means the opposite.| Yes  |
164   | isSilentProxyEnable | Whether silent access is disabled for the ExtensionAbility.<br>The value **false** means to disable silent access; the value **true** means the opposite. The default value is **true**.<br>If the application has multiple ExtensionAbilities and this field is set to **false** for one of them, silent access is disabled for the application.<br>If the data provider has called **enableSilentProxy** or **disableSilentProxy**, silent access is enabled or disabled based on the API settings. Otherwise, the setting here takes effect. | No  |
165
166   **data_share_config.json Example**
167
168   ```json
169   {
170       "tableConfig":[
171           {
172               "uri":"*",
173               "crossUserMode":1
174           },
175           {
176               "uri":"datashare:///com.acts.datasharetest/entry/DB00",
177               "crossUserMode":1
178           },
179           {
180               "uri":"datashare:///com.acts.datasharetest/entry/DB00/TBL00",
181               "crossUserMode":2
182           }
183       ],
184       "isSilentProxyEnable":true
185   }
186   ```
187
188
189### Data Consumer Application Development
190
1911. Import the dependencies.
192
193   ```ts
194   import UIAbility from '@ohos.app.ability.UIAbility';
195   import dataShare from '@ohos.data.dataShare';
196   import dataSharePredicates from '@ohos.data.dataSharePredicates';
197   import { ValuesBucket } from '@ohos.data.ValuesBucket'
198   import window from '@ohos.window';
199   ```
200
2012. Define the URI string for communicating with the data provider.
202
203   ```ts
204   // Different from the URI defined in the module.json5 file, the URI passed in the parameter has an extra slash (/), because there is a DeviceID parameter between the second and the third slash (/).
205   let dseUri = ('datashare:///com.samples.datasharetest.DataShare');
206   ```
207
2083. Create a **DataShareHelper** instance.
209
210   ```ts
211   let dsHelper: dataShare.DataShareHelper | undefined = undefined;
212   let abilityContext: Context;
213
214   export default class EntryAbility extends UIAbility {
215     onWindowStageCreate(windowStage: window.WindowStage) {
216       abilityContext = this.context;
217       dataShare.createDataShareHelper(abilityContext, dseUri, (err, data) => {
218         dsHelper = data;
219       });
220     }
221   }
222   ```
223
2244. Use the APIs provided by **DataShareHelper** to access the services provided by the provider, for example, adding, deleting, modifying, and querying data.
225
226   ```ts
227   // Construct a piece of data.
228   let key1 = 'name';
229   let key2 = 'age';
230   let key3 = 'isStudent';
231   let key4 = 'Binary';
232   let valueName1 = 'ZhangSan';
233   let valueName2 = 'LiSi';
234   let valueAge1 = 21;
235   let valueAge2 = 18;
236   let valueIsStudent1 = false;
237   let valueIsStudent2 = true;
238   let valueBinary = new Uint8Array([1, 2, 3]);
239   let valuesBucket: ValuesBucket = { key1: valueName1, key2: valueAge1, key3: valueIsStudent1, key4: valueBinary };
240   let updateBucket: ValuesBucket = { key1: valueName2, key2: valueAge2, key3: valueIsStudent2, key4: valueBinary };
241   let predicates = new dataSharePredicates.DataSharePredicates();
242   let valArray = ['*'];
243   if (dsHelper != undefined) {
244     // Insert a piece of data.
245     (dsHelper as dataShare.DataShareHelper).insert(dseUri, valuesBucket, (err, data) => {
246       console.info(`dsHelper insert result:${data}`);
247     });
248     // Update data.
249     (dsHelper as dataShare.DataShareHelper).update(dseUri, predicates, updateBucket, (err, data) => {
250       console.info(`dsHelper update result:${data}`);
251     });
252     // Query data.
253     (dsHelper as dataShare.DataShareHelper).query(dseUri, predicates, valArray, (err, data) => {
254       console.info(`dsHelper query result:${data}`);
255     });
256     // Delete data.
257     (dsHelper as dataShare.DataShareHelper).delete(dseUri, predicates, (err, data) => {
258       console.info(`dsHelper delete result:${data}`);
259     });
260   }
261   ```