提交 1ef1d88c 编写于 作者: W wusongqing

Added fa-dataability and fa-serviceability

Signed-off-by: Nwusongqing <wusongqing@huawei.com>
上级 b6fa7cc6
# Data Ability Development
## Basic Concepts
A Data ability helps applications manage access to data stored by themselves and other applications. It also provides APIs for sharing data with other applications either on the same device or across devices.
Data ability providers can customize data access-related APIs such as data inserting, deleting, updating, and querying, as well as file opening, and share data with other applications through these open APIs.
## Creating a Data Ability
### 1. Implementation of the Data Subsystem
1. To meet the basic requirements of the database storage service, implement the **Insert**, **Query**, **Update**, and **Delete** APIs in the **Data** class to provide batch data processing. The traversal logic has been implemented by the **BatchInsert** and **ExecuteBatch** APIs.
2. The APIs used in the lifecycle of the Data ability are as follows:
- onInitialized
Called during ability initialization to initialize the relational database (RDB).
- update
Updates data in the database.
- query
Queries data in the database.
- delete
Deletes one or multiple data records from the database.
- normalizeUri
Normalizes the URI. A normalized URI applies to cross-device use, persistence, backup, and restore. When the context changes, it ensures that the same data item can be referenced.
- batchInsert
Inserts multiple data records into the database.
- denormalizeUri
Converts a normalized URI generated by **normalizeUri** into a denormalized URI.
- insert
Inserts a data record into the database.
- openFile
Opens a file.
- getFileTypes
Obtains the MIME type of a file.
- getType
Obtains the MIME type matching the data specified by the URI.
- executeBatch
Operates data in the database in batches.
- call
A customized API.
The following code snippet shows how to create a Data ability:
```javascript
import dataAbility from '@ohos.data.dataability'
import dataRdb from '@ohos.data.rdb'
const TABLE_NAME = 'book'
const STORE_CONFIG = { name: 'book.db', encryptKey: new Uint8Array([]) }
const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS book(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, age INTEGER, introduction TEXT NOT NULL)'
let rdbStore = undefined
export default {
onInitialized(abilityInfo) {
console.info('DataAbility onInitialized, abilityInfo:' + abilityInfo.bundleName)
dataRdb.getRdbStore(STORE_CONFIG, 1, (err, store) => {
console.info('DataAbility getRdbStore callback')
store.executeSql(SQL_CREATE_TABLE, [])
rdbStore = store
});
},
insert(uri, valueBucket, callback) {
console.info('DataAbility insert start')
rdbStore.insert(TABLE_NAME, valueBucket, callback)
},
batchInsert(uri, valueBuckets, callback) {
console.info('DataAbility batch insert start')
for (let i = 0;i < valueBuckets.length; i++) {
console.info('DataAbility batch insert i=' + i)
if (i < valueBuckets.length - 1) {
rdbStore.insert(TABLE_NAME, valueBuckets[i], (num: number) => {
console.info('DataAbility batch insert ret=' + num)
})
} else {
rdbStore.insert(TABLE_NAME, valueBuckets[i], callback)
}
}
},
query(uri, columns, predicates, callback) {
console.info('DataAbility query start')
let rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates)
rdbStore.query(rdbPredicates, columns, callback)
},
update(uri, valueBucket, predicates, callback) {
console.info('DataAbilityupdate start')
let rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates)
rdbStore.update(valueBucket, rdbPredicates, callback)
},
delete(uri, predicates, callback) {
console.info('DataAbilitydelete start')
let rdbPredicates = dataAbility.createRdbPredicates(TABLE_NAME, predicates)
rdbStore.delete(rdbPredicates, callback)
}
};
```
### 2. Subsystem Configuration
| JSON Field | Description |
| ------------- | ------------------------------------------------------------ |
| "name" | Ability name, corresponding to the **Data** class name derived from **Ability**. |
| "type" | Ability type, which is **Data** for a Data ability. |
| "uri" | URI used for communication. |
| "visible" | Whether the Data ability is visible to other applications. When this parameter is set to **true**, the Data ability can communicate with other applications.|
**config.json configuration example**
```json
"abilities":[{
"srcPath": "DataAbility",
"name": ".DataAbility",
"icon": "$media:icon",
"srcLanguage": "ets",
"description": "$string:description_dataability",
"type": "data",
"visible": true,
"uri": "dataability://ohos.samples.etsdataability.DataAbility"
}]
```
## Accessing a Data ability
### 1. Preparing for JS Application Development
Basic dependency packages:
1. @ohos.ability.featureAbility
2. @ohos.data.dataability
3. @ohos.data.rdb
URI string used for communication with the Data ability.
### 2. JS Application Development APIs
Create a utility API object.
```js
// Different from the URI defined in the config.json file, the URI passed in the parameter has an extra slash (/), because there is a DeviceID parameter between the second and the third slash (/).
var urivar = "dataability:///com.ix.DataAbility"
var DAHelper = featureAbility.acquireDataAbilityHelper(
urivar
);
```
Construct RDB data.
```js
var valuesBucket = {"name": "gaolu"}
var da = new ohos_data_ability.DataAbilityPredicates()
var valArray =new Array("value1");
var cars = new Array({"batchInsert1" : "value1",});
```
Use **insert** to insert data to the Data subsystem.
```js
// Callback mode:
DAHelper.insert(
urivar,
valuesBucket,
(error, data) => {
expect(typeof(data)).assertEqual("number")
}
);
// Promise mode:
var datainsert = await DAHelper.insert(
urivar,
valuesBucket
);
```
Use **delete** to delete data from the Data subsystem.
```js
// Callback mode:
DAHelper.delete(
urivar,
da,
(error, data) => {
expect(typeof(data)).assertEqual("number")
}
);
// Promise mode:
var datadelete = await DAHelper.delete(
urivar,
da,
);
```
Use **update** to update data in the Data subsystem.
```js
// Callback mode:
DAHelper.update(
urivar
valuesBucket,
da,
(error, data) => {
expect(typeof(data)).assertEqual("number")
}
);
// Promise mode:
var dataupdate = await DAHelper.update(
urivar,
valuesBucket,
da,
);
```
Use **query** to query data in the Data subsystem.
```js
// Callback mode:
DAHelper.query(
urivar,
valArray,
da,
(error, data) => {
expect(typeof(data)).assertEqual("object")
}
);
// Promise mode:
var dataquery = await DAHelper.query(
urivar,
valArray,
da
);
```
Use **batchInsert** to insert data in batches to the Data subsystem.
```js
// Callback mode:
DAHelper.batchInsert(
urivar,
cars,
(error, data) => {
expect(typeof(data)).assertEqual("number")
}
);
// Promise mode:
var databatchInsert = await DAHelper.batchInsert(
urivar,
cars
);
```
Use **executeBatch** to process data in batches in the Data subsystem.
```js
// Callback mode:
DAHelper.executeBatch(
urivar,
[
{
uri: urivar,
type: featureAbility.DataAbilityOperationType.TYPE_INSERT,
valuesBucket: {"executeBatch" : "value1",},
predicates: da,
expectedCount:0,
PredicatesBackReferences: {},
interrupted:true,
}
],
(error, data) => {
expect(typeof(data)).assertEqual("object")
}
);
// Promise mode:
var dataexecuteBatch = await DAHelper.executeBatch(
urivar,
[
{
uri: urivar,
type: featureAbility.DataAbilityOperationType.TYPE_INSERT,
valuesBucket:
{
"executeBatch" : "value1",
},
predicates: da,
expectedCount:0,
PredicatesBackReferences: {},
interrupted:true,
}
]
);
```
## Development Example
The following sample is provided to help you better understand how to develop a Data ability:
- [eTSDataAbility](https://gitee.com/openharmony/app_samples/tree/master/ability/eTSDataAbility)
This **eTSDataAbility** sample shows how to:
Create a Data ability in the **data.ts** file in the **DataAbility** directory.
Encapsulate the process of accessing the Data ability in the **MainAbility** directory.
# Service Ability Development
## Basic Concepts
A Service ability is used to run tasks in the background, such as playing music or downloading files. It does not provide a UI for user interaction. Service abilities can be started by other applications or abilities and can remain running in the background even after the user switches to another application.
## Creating a Service Ability<a name="section17436202895812"></a>
1. Create a child class of the **Ability** class and override the following Service ability-related lifecycle callbacks to implement your own logic for processing requests to interact with your Service ability:
- onStart()
This callback is invoked for initializing a Service ability when the Service ability is being created. This callback is invoked only once in the entire lifecycle of a Service ability. The **Want** object passed to this callback must be null.
- onCommand()
This callback is invoked every time a Service ability is created on a client. You can calculate calling statistics and perform initialization operations in this callback.
- onConnect()
This callback is invoked when another ability is connected to the Service ability. It returns an **IRemoteObject**. You can use this callback to generate a channel for the other ability to interact with the Service ability during inter-process communication (IPC). An ability can connect to the same Service ability for multiple times. When the first client is connected to a Service ability, the system calls **onConnect()** to generate an **IRemoteObject** for the Service ability, and the generated **IRemoteObject** will then be cached and used for all clients that are connected to this Service ability without having to call **onConnect()** again.
- onDisconnect()
This callback is invoked when another ability is disconnected from the Service ability.
- onStop()
This callback is invoked when a Service ability is being destroyed. You should override this callback for your Service ability to clear its resources, such as threads and registered listeners.
The following code snippet shows how to create a Service ability:
```javascript
export default {
onStart(want) {
console.log('ServiceAbility onStart');
},
onCommand(want, restart, startId) {
console.log('ServiceAbility onCommand');
},
onConnect(want) {
console.log('ServiceAbility OnConnect');
},
onDisconnect() {
console.log('ServiceAbility OnDisConnect');
},
onStop() {
console.log('ServiceAbility onStop');
},
}
```
2. Register a Service ability.
You must declare your Service ability in the **config.json** file by setting its **type** attribute to **service**.
```javascript
{
"module": {
"abilities": [
{
"name": ".ServiceAbility",
"type": "service",
"visible": true
...
}
]
...
}
...
}
```
## Starting the Service Ability<a name="section944219415599"></a>
The **Ability** class provides the **startAbility()** method for you to start another Service ability by passing a **Want** object.
To set information about the target Service ability, you can first construct a **Want** object with the **bundleName** and **abilityName** parameters specified. The meanings of the parameters are as follows:
- **bundleName** indicates the name of the bundle to which the target ability belongs.
- **abilityName** indicates the target ability name.
The following code snippet shows how to start a Service ability running on the local device:
```javascript
import featureAbility from '@ohos.ability.featureability';
var promise = await featureAbility.startAbility(
{
want:
{
bundleName: "com.jstest.serviceability",
abilityName: "com.jstest.serviceability.MainAbility",
},
}
);
```
- After the preceding code is executed, the **startAbility()** method is called to start the Service ability.
- If the Service ability is not running, the system calls **onStart()** to initialize the Service ability, and then calls **onCommand()** on the Service ability.
- If the Service ability is running, the system directly calls **onCommand()** on the Service ability.
- Stopping a Service ability
Once created, the Service ability keeps running in the background. The system does not stop or destroy it unless memory resources must be reclaimed. You can call **terminateAbility()** on a Service ability to stop it or call **stopAbility()** on another ability to stop the specified Service ability.
## Connecting to a Local Service Ability<a name="section126857614018"></a>
If you need to connect a Service ability to a Page ability or to a Service ability in another application, you must first implement the **IAbilityConnection** API for the connection. A Service ability allows other abilities to connect to it through **connectAbility()**.
When calling **connectAbility()**, you should pass a **Want** object containing information about the target Service ability and an **IAbilityConnection** object to the method. **IAbilityConnection** provides the following callbacks that you should implement: **onConnect()**, **onDisconnect()**, and **onFailed()**. The **onConnect()** callback is invoked when a Service ability is connected, **onDisconnect()** is invoked when a Service ability is unexpectedly disconnected, and **onFailed()** is invoked when a connection to a Service ability fails.
The following code snippet shows how to implement the callbacks:
```javascript
var mRemote;
function onConnectCallback(element, remote){
console.log('ConnectAbility onConnect Callback')
mRemote = remote;
}
function onDisconnectCallback(element){
console.log('ConnectAbility onDisconnect Callback')
}
function onFailedCallback(code){
console.log('ConnectAbility onFailed Callback')
}
```
The following code snippet shows how to connect to a local Service ability:
```javascript
import featureAbility from '@ohos.ability.featureability';
var connId = featureAbility.connectAbility(
{
bundleName: "com.jstest.serviceability",
abilityName: "com.jstest.serviceability.MainAbility",
},
{
onConnect: onConnectCallback,
onDisconnect: onDisconnectCallback,
onFailed: onFailedCallback,
},
);
```
When a Service ability is connected, the **onConnect()** callback is invoked and returns an **IRemoteObject** defining the proxy used for communicating with the Service ability. OpenHarmony provides a default implementation of the **IRemoteObject** interface. You can inherit **rpc.RemoteObject** to implement your own class of **IRemoteObject**.
The following code snippet shows how the Service ability instance returns itself to the calling ability:
```javascript
import rpc from "@ohos.rpc";
var mMyStub;
export default {
onStart(want) {
class MyStub extends rpc.RemoteObject{
constructor(des) {
if (typeof des === 'string') {
super(des);
}
return null;
}
onRemoteRequest(code, message, reply, option) {
}
}
mMyStub = new MyStub("ServiceAbility-test");
},
onCommand(want, restart, startId) {
console.log('ServiceAbility onCommand');
},
onConnect(want) {
console.log('ServiceAbility OnConnect');
return mMyStub;
},
onDisconnect() {
console.log('ServiceAbility OnDisConnect');
},
onStop() {
console.log('ServiceAbility onStop');
},
}
```
## Connecting to a Remote Service Ability<a name="section126857614019"></a>
If you need to connect a Service ability to a Page ability on another device or to a Service ability in another application on another device, you must first implement the **IAbilityConnection** interface for the connection. A Service ability allows other abilities on another device to connect to it through **connectAbility()**.
When calling **connectAbility()**, you should pass a **Want** object containing information about the target Service ability and an **IAbilityConnection** object to the method. **IAbilityConnection** provides the following callbacks that you should implement: **onConnect()**, **onDisconnect()**, and **onFailed()**. The **onConnect()** callback is invoked when a Service ability is connected, **onDisconnect()** is invoked when a Service ability is unexpectedly disconnected, and **onFailed()** is invoked when a connection to a Service ability fails.
The following code snippet shows how to implement the callbacks:
```javascript
var mRemote;
function onConnectCallback(element, remote){
console.log('ConnectRemoteAbility onConnect Callback')
mRemote = remote;
}
function onDisconnectCallback(element){
console.log('ConnectRemoteAbility onDisconnect Callback')
}
function onFailedCallback(code){
console.log('ConnectRemoteAbility onFailed Callback')
}
```
The **Want** of the target Service ability must contain the remote **deviceId**, which can be obtained through **deviceManager**.
The following code snippet shows how to connect to a remote Service ability:
```javascript
import featureAbility from '@ohos.ability.featureability';
var connId = featureAbility.connectAbility(
{
deviceId: deviceId,
bundleName: "com.jstest.serviceability",
abilityName: "com.jstest.serviceability.MainAbility",
},
{
onConnect: onConnectCallback,
onDisconnect: onDisconnectCallback,
onFailed: onFailedCallback,
},
);
```
When a Service ability is connected, the **onConnect()** callback is invoked and returns an **IRemoteObject** defining the proxy used for communicating with the Service ability. OpenHarmony provides a default implementation of the **IRemoteObject** interface. You can inherit **rpc.RemoteObject** to implement your own class of **IRemoteObject**.
The following code snippet shows how the Service ability instance returns itself to the calling ability:
```javascript
import rpc from "@ohos.rpc";
var mMyStub;
export default {
onStart(want) {
class MyStub extends rpc.RemoteObject{
constructor(des) {
if (typeof des === 'string') {
super(des);
}
return null;
}
onRemoteRequest(code, message, reply, option) {
}
}
mMyStub = new MyStub("ServiceAbility-test");
},
onCommand(want, restart, startId) {
console.log('ServiceAbility onCommand');
},
onConnect(want) {
console.log('ServiceAbility OnConnect');
return mMyStub;
},
onDisconnect() {
console.log('ServiceAbility OnDisConnect');
},
onStop() {
console.log('ServiceAbility onStop');
},
}
```
## Development Example
The following sample is provided to help you better understand how to develop a Service ability:
- [eTSServiceAbility](https://gitee.com/openharmony/app_samples/tree/master/ability/eTSServiceAbility)
This **eTSServiceAbility** sample shows how to:
Create a local Service ability in the **service.ts** file in the **ServiceAbility** directory.
Encapsulate the process of starting and connecting to the local Service ability in the **MainAbility** directory.
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册