1 -> DataAbility development
1.1 -> Scenario introduction
The ability based on data templates helps applications manage access to data stored by themselves and other applications, and provides a way to share data with other applications. Data can be used for data sharing between different applications on the same device and across devices.
The data provider can customize functions such as adding, deleting, modifying, querying, and opening files, and provide these APIs.
1.2 -> Interface Description
1.3 -> Development steps
1.3.1 -> Create Data
- You need to implement the business content of the Insert, Query, Update, and Delete APIs in Data. Ensure that it can meet the basic needs of database storage business. The BatchInsert and ExecuteBatch APIs have implemented traversal logic in the system, relying on the Insert, Query, Update, and Delete APIs to implement batch data processing.
The following is an example of how to create a data:
import featureAbility from '@ohos.ability.featureAbility'
import dataAbility from '@ohos.data.dataAbility'
import dataRdb from '@ohos.data.rdb'
const TABLE_NAME = 'book'
const STORE_CONFIG = { name: 'book.db' }
const SQL_CREATE_TABLE = 'CREATE TABLE IF NOT EXISTS book(id INTEGER PRIMARY KEY AUTOINCREMENT, name TEXT NOT NULL, introduction TEXT NOT NULL)'
let rdbStore: dataRdb.RdbStore = undefined
export default {
onInitialized(abilityInfo) {
console.info('DataAbility onInitialized, abilityInfo:' + abilityInfo.bundleName)
let context = featureAbility.getContext()
dataRdb.getRdbStore(context, 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], (err: any, 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)
}
};
- Subsystem configuration
Sample configuration for config.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"
}]
1.3.2 -> Visit Data
Pre-development preparation
You need to import the basic dependency package and obtain the URI string that communicates with the Data submodule.
The basic dependencies include:
@ohos.ability.featureAbility
@ohos.data.dataability
@ohos.data.rdb
DataAbility API development guide
- Create a tool interface class object.
// 作为参数传递的Uri,与config中定义的Uri的区别是多了一个"/",是因为作为参数传递的uri中,在第二个与第三个"/"中间,存在一个DeviceID的参数
import featureAbility from '@ohos.ability.featureAbility'
import ohos_data_ability from '@ohos.data.dataAbility'
import ohos_data_rdb from '@ohos.data.rdb'
var urivar = "dataability:///com.ix.DataAbility"
var DAHelper = featureAbility.acquireDataAbilityHelper(
urivar
);
- Build RDB data related to the database.
var valuesBucket = {"name": "gaolu"}
var da = new ohos_data_ability.DataAbilityPredicates()
var valArray =new Array("value1");
var cars = new Array({"batchInsert1" : "value1",});
- Call the insert method to insert data into the specified Data submodule.
// callback方式调用:
DAHelper.insert(
urivar,
valuesBucket,
(error, data) => {
console.log("DAHelper insert result: " + data)
}
);
// promise方式调用:
var datainsert = await DAHelper.insert(
urivar,
valuesBucket
);
- Call the delete method to delete the data specified in the Data submodule.
// callback方式调用:
DAHelper.delete(
urivar,
da,
(error, data) => {
console.log("DAHelper delete result: " + data)
}
);
// promise方式调用:
var datadelete = await DAHelper.delete(
urivar,
da,
);
- Call the update method to update the data in the specified Data submodule.
// callback方式调用:
DAHelper.update(
urivar
valuesBucket,
da,
(error, data) => {
console.log("DAHelper update result: " + data)
}
);
// promise方式调用:
var dataupdate = await DAHelper.update(
urivar,
valuesBucket,
da,
);
- Call the query method to find data in the specified Data submodule.
// callback方式调用:
DAHelper.query(
urivar,
valArray,
da,
(error, data) => {
console.log("DAHelper query result: " + data)
}
);
// promise方式调用:
var dataquery = await DAHelper.query(
urivar,
valArray,
da
);
- Call the batchInsert method to insert data into the specified data subsystem in batches.
// callback方式调用:
DAHelper.batchInsert(
urivar,
cars,
(error, data) => {
console.log("DAHelper batchInsert result: " + data)
}
);
// promise方式调用:
var databatchInsert = await DAHelper.batchInsert(
urivar,
cars
);
- Call the executeBatch method to batch process data to the specified Data submodule.
// callbacke方式调用:
DAHelper.executeBatch(
urivar,
[
{
uri: urivar,
type: featureAbility.DataAbilityOperationType.TYPE_INSERT,
valuesBucket: {"executeBatch" : "value1",},
predicates: da,
expectedCount:0,
predicatesBackReferences: null,
interrupted:true,
}
],
(error, data) => {
console.log("DAHelper executeBatch result: " + data)
}
);
// promise方式调用:
var dataexecuteBatch = await DAHelper.executeBatch(
urivar,
[
{
uri: urivar,
type: featureAbility.DataAbilityOperationType.TYPE_INSERT,
valuesBucket:
{
"executeBatch" : "value1",
},
predicates: da,
expectedCount:0,
predicatesBackReferences: null,
interrupted:true,
}
]
);
2-> FA card development
2.1 -> Card Overview
The card is a form of interface display, which can pre-position the important information or operation of the application to the card to achieve the purpose of direct service and reduce the level of experience.
Cards are often used to be embedded in other applications (currently only supported for system applications) as part of their interface, and support basic interactive functions such as pulling up pages and sending messages. The card user is responsible for displaying the card.
The basic concept of the card:
Card provider: provides meta-services for card display content, controlling card display content, control layout, and control click events.
Card User: The host app that displays the content of the card, controlling where the card is displayed in the host.
Card management service: A resident agent service for the cards added to the system, including the management and use of card objects and the periodic refresh of cards.
Illustrate:
Card users and providers are not required to run on a permanent basis, and when they need to add/delete/request an update card, the card management service will pull up the card provider to obtain the card information.
The developer only needs to develop the card content as the card provider, and the card user and card management services are automatically handled by the system.
The card provider controls what the card actually displays, the layout of the controls, and the click events.
2.2 -> Scenario introduction
FA card development, that is, the development of card providers based on the FA model, mainly involves the following functional logic:
Develop the LifecycleForm callback function for the life cycle of the card.
Create a FormBindingData object for card data.
Update the card via FormProvider.
Develop a card page.
2.3 -> Interface Description
2.4 -> Development steps
2.4.1 -> Create LifecycleForm
To create an FA model, you need to implement the LifecycleForm lifecycle interface. The specific sample code is as follows:
- Import the relevant module
import formBindingData from '@ohos.application.formBindingData'
import formInfo from '@ohos.application.formInfo'
import formProvider from '@ohos.application.formProvider'
- Implement the LifecycleForm life cycle interface
export default {
onCreate(want) {
console.log('FormAbility onCreate');
// 由开发人员自行实现,将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用
let obj = {
"title": "titleOnCreate",
"detail": "detailOnCreate"
};
let formData = formBindingData.createFormBindingData(obj);
return formData;
},
onCastToNormal(formId) {
// 使用方将临时卡片转换为常态卡片触发,提供方需要做相应的处理
console.log('FormAbility onCastToNormal');
},
onUpdate(formId) {
// 若卡片支持定时更新/定点更新/卡片使用方主动请求更新功能,则提供方需要覆写该方法以支持数据更新
console.log('FormAbility onUpdate');
let obj = {
"title": "titleOnUpdate",
"detail": "detailOnUpdate"
};
let formData = formBindingData.createFormBindingData(obj);
formProvider.updateForm(formId, formData).catch((error) => {
console.log('FormAbility updateForm, error:' + JSON.stringify(error));
});
},
onVisibilityChange(newStatus) {
// 使用方发起可见或者不可见通知触发,提供方需要做相应的处理
console.log('FormAbility onVisibilityChange');
},
onEvent(formId, message) {
// 若卡片支持触发事件,则需要覆写该方法并实现对事件的触发
console.log('FormAbility onEvent');
},
onDestroy(formId) {
// 删除卡片实例数据
console.log('FormAbility onDestroy');
},
onAcquireFormState(want) {
console.log('FormAbility onAcquireFormState');
return formInfo.FormState.READY;
},
}
2.4.2 -> Configure the card profile
Cards need to be configured in the app profile config.json.
The JS module is used for JS-related resources corresponding to the card, and the internal field structure is described:
The following is an example:
"js": [{
"name": "widget",
"pages": ["pages/index/index"],
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"type": "form"
}]
abilities module, which is used to correspond to the LifecycleForm of the card, and the internal field structure is described:
The following is an example:
"abilities": [{
"name": "FormAbility",
"description": "This is a FormAbility",
"formsEnabled": true,
"icon": "$media:icon",
"label": "$string:form_FormAbility_label",
"srcPath": "FormAbility",
"type": "service",
"srcLanguage": "ets",
"forms": [{
"colorMode": "auto",
"defaultDimension": "2*2",
"description": "This is a service widget.",
"formVisibleNotify": true,
"isDefault": true,
"jsComponentName": "widget",
"name": "widget",
"scheduledUpdateTime": "10:30",
"supportDimensions": ["2*2"],
"type": "JS",
"updateDuration": 1,
"updateEnabled": true
}]
}]
2.4.3 -> Persistence of card information
Since most card providers are not resident services, they will only be pulled up to obtain card information when they need to be used, and the card management service supports multi-instance management of cards, and the card ID corresponds to the instance ID, so if the card provider supports the configuration of card data, it is necessary to persistently manage the business data of the card according to the card ID, so that the correct card business data can be obtained when it is obtained, updated, and pulled up in the future.
onCreate(want) {
console.log('FormAbility onCreate');
let formId = want.parameters["ohos.extra.param.key.form_identity"];
let formName = want.parameters["ohos.extra.param.key.form_name"];
let tempFlag = want.parameters["ohos.extra.param.key.form_temporary"];
// 由开发人员自行实现,将创建的卡片信息持久化,以便在下次获取/更新该卡片实例时进行使用
storeFormInfo(formId, formName, tempFlag, want);
let obj = {
"title": "titleOnCreate",
"detail": "detailOnCreate"
};
let formData = formBindingData.createFormBindingData(obj);
return formData;
}
In addition, you need to adapt the onDestroy card deletion notification API to delete card instance data.
It should be noted that there is a temporary tag field in the Want data passed to the provider application by the card user when requesting the card, indicating whether the card requested is temporary.
Normal card: a card that will be persisted by the card user;
Temporary card: a card that will not be persisted by the card user;
Due to the non-persistent nature of temporary card data, in some scenarios, such as the card service framework dies and restarts, the temporary card data has been deleted in the card management service, and the corresponding card ID will not be notified to the provider, so the card provider needs to clean up the temporary card data that has not been deleted for a long time. At the same time, the corresponding card consumer may convert the previously requested temporary card to a normal card. If the conversion is successful, the card provider also needs to process the corresponding temporary card ID and convert the temporary card data recorded by the card provider into normal card data, so as to prevent the provider from deleting the temporary card information that has been converted to a normal card when cleaning up the temporary card that has not been deleted for a long time, resulting in the loss of card information.
2.4.4 -> Develop card pages
You can use hml+css+json to develop JS card pages:
illustrate
Currently, only the JS extension-like web development paradigm is supported to implement the UI page of the card.
hml:
<div class="container">
<stack>
<div class="container-img">
<image src="/common/widget.png" class="bg-img"></image>
</div>
<div class="container-inner">
<text class="title">{{title}}</text>
<text class="detail_text" onclick="routerEvent">{{detail}}</text>
</div>
</stack>
</div>
css:
.container {
flex-direction: column;
justify-content: center;
align-items: center;
}
.bg-img {
flex-shrink: 0;
height: 100%;
}
.container-inner {
flex-direction: column;
justify-content: flex-end;
align-items: flex-start;
height: 100%;
width: 100%;
padding: 12px;
}
.title {
font-size: 19px;
font-weight: bold;
color: white;
text-overflow: ellipsis;
max-lines: 1;
}
.detail_text {
font-size: 16px;
color: white;
opacity: 0.66;
text-overflow: ellipsis;
max-lines: 1;
margin-top: 6px;
}
json:
{
"data": {
"title": "TitleDefault",
"detail": "TextDefault"
},
"actions": {
"routerEvent": {
"action": "router",
"abilityName": "com.example.MyApplication.hmservice.FormAbility",
"params": {
"message": "add detail"
}
}
}
}
3 -> WantAgent development
3.1 -> Scenario Introduction
The WantAgent encapsulates an intent that can be triggered by the WantAgent.trigger API or passively by binding it to a notification.
Specific actions include: starting an Ability and publishing a Public Event.
3.2 -> Interface Description
3.3 -> Development steps
- Import the WantAgent module
import wantAgent from '@ohos.wantAgent';
- Create the WantAgentInfo information of the pull-up ability
private wantAgentObj = null //用于保存创建成功的wantAgent对象,后续使用其完成触发的动作。
//wantAgentInfo
var wantAgentInfo = {
wants: [
{
deviceId: "",
bundleName: "com.example.test",
abilityName: "com.example.test.MainAbility",
action: "",
entities: [],
uri: "",
parameters: {}
}
],
operationType: wantAgent.OperationType.START_ABILITY,
requestCode: 0,
wantAgentFlags:[wantAgent.WantAgentFlags.CONSTANT_FLAG]
}
- Create a WantAgentInfo information to publish public events
private wantAgentObj = null //用于保存创建成功的WantAgent对象,后续使用其完成触发的动作。
//wantAgentInfo
var wantAgentInfo = {
wants: [
{
action: "event_name", // 设置事件名
parameters: {}
}
],
operationType: wantAgent.OperationType.SEND_COMMON_EVENT,
requestCode: 0,
wantAgentFlags:[wantAgent.WantAgentFlags.CONSTANT_FLAG]
}
- Create a WantAgent and save the returned WantAgent object wantAgentObj for subsequent trigger operations.
//创建WantAgent
wantAgent.getWantAgent(wantAgentInfo, (err, wantAgentObj) => {
if (err.code) {
console.error("[WantAgent]getWantAgent err=" + JSON.stringify(err))
} else {
console.log("[WantAgent]getWantAgent success")
this.wantAgentObj = wantAgentObj
}
})
- Trigger WantAgent
//触发WantAgent
var triggerInfo = {
code:0
}
wantAgent.trigger(wantAgentObj, triggerInfo, (completeData) => {
console.log("[WantAgent]getWantAgent success, completeData: ", + JSON.stringify(completeData))
})
Top comments (0)