提交 c2f1522e 编写于 作者: F fangjinliang

Merge branch 'master' of https://gitee.com/openharmony/docs into br_333

Signed-off-by: Nfangjinliang <fangjinliang1@huawei.com>
......@@ -9,6 +9,7 @@
- [Getting Started with Application Development](quick-start/Readme-EN.md)
- [Directory Structure](quick-start/package-structure.md)
- Development
- [Ability Development](ability/Readme-EN.md)
- [UI Development](ui/Readme-EN.md)
- Basic Feature Development
- [Window Manager](windowmanager/Readme-EN.md)
......
# Ability Development
- [Ability Framework Overview](ability-brief.md)
- FA Model
- [FA Model Overview](fa-brief.md)
- [Page Ability Development](fa-pageability.md)
- [Service Ability Development](fa-serviceability.md)
- [Data Ability Development](fa-dataability.md)
- [FA Widget Development](fa-formability.md)
- Other
- [Ability Assistant Usage](ability-assistant-guidelines.md)
# FA Widget Development
## Widget Overview
A Form ability presents a widget, which is a set of UI components used to display important information or operations for an application. It provides users with direct access to a desired application service, without requiring them to open the application.
A widget displays brief information about an application on the UI of another application (host application, currently system applications only) and provides basic interactive features such as opening a UI page or sending a message. The widget client is responsible for displaying the service widget.
Basic concepts:
- Widget provider
The widget provider is an atomic service that provides the content to be displayed. It controls the display content, component layout, and component click events of a widget.
- Widget client
The widget client is an application that displays the widget content and controls the position where the widget is displayed in the host application.
- Widget Manager
The Widget Manager is a resident agent that manages widgets added to the system and provides functions such as periodic widget update.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> The widget client and provider do not keep running all the time. The Widget Manager starts the widget provider to obtain widget information when a widget is added, deleted, or updated.
You only need to develop widget content as the widget provider. The system automatically handles the work done by the widget client and Widget Manager.
The widget provider controls the widget content to display, component layout, and click events bound to components.
## Scenario
Form ability development refers to the development conducted by the widget provider based on the Feature Ability (FA) model(fa-brief.md). As a widget provider, you need to carry out the following operations:
- Develop the lifecycle callback functions in **FormAbility**.
- Create a **FormBindingData** object.
- Update a widget through **FormProvider**.
- Develop the widget UI page.
## Available APIs
The table below describes the lifecycle callback functions provided **FormAbility**.
**Table 1** FormAbility APIs
| API | Description |
| :----------------------------------------------------------- | :------------------------------------------- |
| onCreate(want: Want): formBindingData.FormBindingData | Called to notify the widget provider that a **Form** instance (widget) has been created. |
| onCastToNormal(formId: string): void | Called to notify the widget provider that a temporary widget has been converted to a normal one.|
| onUpdate(formId: string): void | Called to notify the widget provider that a widget has been updated. |
| onVisibilityChange(newStatus: { [key: string]: number }): void | Called to notify the widget provider of the change of widget visibility. |
| onEvent(formId: string, message: string): void | Called to instruct the widget provider to receive and process the widget event. |
| onDestroy(formId: string): void | Called to notify the widget provider that a **Form** instance (widget) has been destroyed. |
| onConfigurationUpdated(config: Configuration): void; | Called when the configuration of the environment where the ability is running is updated. |
For details about the **FormProvider** APIs, see [FormProvider](../reference/apis/js-apis-formprovider.md).
**Table 2** FormProvider APIs
| API | Description |
| :----------------------------------------------------------- | :------------------------------------------------ |
| setFormNextRefreshTime(formId: string, minute: number, callback: AsyncCallback&lt;void&gt;): void; | Sets the next refresh time for a widget. This API uses an asynchronous callback to return the result. |
| setFormNextRefreshTime(formId: string, minute: number): Promise&lt;void&gt;; | Sets the next refresh time for a widget. This API uses a promise to return the result.|
| updateForm(formId: string, formBindingData: FormBindingData, callback: AsyncCallback&lt;void&gt;): void; | Updates a widget. This API uses an asynchronous callback to return the result. |
| updateForm(formId: string, formBindingData: FormBindingData): Promise&lt;void&gt;; | Updates a widget. This API uses a promise to return the result. |
## How to Develop
### Creating a Form Ability
To create a widget in the FA model, you need to implement the lifecycle callback functions of **FormAbility**. The sample code is as follows:
1. Import the required modules.
```javascript
import formBindingData from '@ohos.application.formBindingData'
import formInfo from '@ohos.application.formInfo'
import formProvider from '@ohos.application.formProvider'
```
2. Implement the lifecycle callback functions of **FormAbility**.
```javascript
export default {
onCreate(want) {
console.log('FormAbility onCreate');
// Persistently store widget information for subsequent use, such as widget instance retrieval and update.
let obj = {
"title": "titleOnCreate",
"detail": "detailOnCreate"
};
let formData = formBindingData.createFormBindingData(obj);
return formData;
},
onCastToNormal(formId) {
// Called when the widget client converts the temporary widget into a normal one. The widget provider should do something to respond to the conversion.
console.log('FormAbility onCastToNormal');
},
onUpdate(formId) {
// To support scheduled update, periodic update, or update requested by the widget client for a widget, override this method for data update.
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) {
// Called when the widget client initiates an event about visibility changes. The widget provider should do something to respond to the notification.
console.log('FormAbility onVisibilityChange');
},
onEvent(formId, message) {
// If the widget supports event triggering, override this method and implement the trigger.
console.log('FormAbility onEvent');
},
onDestroy(formId) {
// Delete widget data.
console.log('FormAbility onDestroy');
},
onAcquireFormState(want) {
console.log('FormAbility onAcquireFormState');
return formInfo.FormState.READY;
},
}
```
### Configuring config.json for the Form Ability
Configure the **config.json** file for the **Form** ability.
- The **js** module in the **config.json** file provides the JavaScript resources of the **Form** ability. The internal field structure is described as follows:
| Field| Description | Data Type| Default |
| -------- | ------------------------------------------------------------ | -------- | ------------------------ |
| name | Name of a JavaScript component. The default value is **default**. | String | No |
| pages | Route information about all pages in the JavaScript component, including the page path and page name. The value is an array, in which each element represents a page. The first element in the array represents the home page of the JavaScript FA.| Array | No |
| window | Window-related configurations. This field applies only to phones, tablets, smart TVs, head units, and wearable devices.| Object | Yes |
| type | Type of the JavaScript component. Available values are as follows:<br>**normal**: indicates that the JavaScript component is an application instance.<br>**form**: indicates that the JavaScript component is a widget instance.| String | Yes (initial value: **normal**)|
| mode | Development mode of the JavaScript component. | Object | Yes (initial value: left empty) |
A configuration example is as follows:
```json
"js": [{
"name": "widget",
"pages": ["pages/index/index"],
"window": {
"designWidth": 720,
"autoDesignWidth": true
},
"type": "form"
}]
```
- The **abilities** module in the **config.json** file corresponds to the **Form** ability. The internal field structure is described as follows:
| Field | Description | Data Type | Default |
| ------------------- | ------------------------------------------------------------ | ---------- | ------------------------ |
| name | Class name of the widget. The value is a string with a maximum of 127 bytes. | String | No |
| description | Description of the widget. The value can be a string or a resource index to descriptions in multiple languages. The value is a string with a maximum of 255 bytes.| String | Yes (initial value: left empty) |
| isDefault | Whether the widget is a default one. Each ability has only one default widget.<br>**true**: The widget is the default one.<br>**false**: The widget is not the default one.| Boolean | No |
| type | Type of the widget. Available values are as follows:<br>**Java**: indicates a Java-programmed widget.<br>**JS**: indicates a JavaScript-programmed widget.| String | No |
| colorMode | Color mode of the widget. Available values are as follows:<br>**auto**: The widget adopts the auto-adaptive color mode.<br>**dark**: The widget adopts the dark color mode.<br>**light**: The widget adopts the light color mode.| String | Yes (initial value: **auto**)|
| supportDimensions | Grid styles supported by the widget. Available values are as follows:<br>1 * 2: indicates a grid with one row and two columns.<br>2 * 2: indicates a grid with two rows and two columns.<br>2 * 4: indicates a grid with two rows and four columns.<br>4 * 4: indicates a grid with four rows and four columns.| String array| No |
| defaultDimension | Default grid style of the widget. The value must be available in the **supportDimensions** array of the widget.| String | No |
| landscapeLayouts | Landscape layouts for the grid styles. Values in this array must correspond to the values in the **supportDimensions** array. This field is required only by Java-programmed widgets.| String array| No |
| portraitLayouts | Portrait layouts for the grid styles. Values in this array must correspond to the values in the **supportDimensions** array. This field is required only by Java-programmed widgets.| String array| No |
| updateEnabled | Whether the widget can be updated periodically. Available values are as follows:<br>**true**: The widget can be updated periodically, depending on the update way you select, either at a specified interval (**updateDuration**) or at the scheduled time (**scheduledUpdateTime**). **updateDuration** is preferentially recommended.<br>**false**: The widget cannot be updated periodically.| Boolean | No |
| scheduledUpdateTime | Scheduled time to update the widget. The value is in 24-hour format and accurate to minute. | String | Yes (initial value: **0:0**) |
| updateDuration | Interval to update the widget. The value is a natural number, in the unit of 30 minutes.<br>If the value is **0**, this field does not take effect.<br>If the value is a positive integer ***N***, the interval is calculated by multiplying ***N*** and 30 minutes.| Number | Yes (initial value: **0**) |
| formConfigAbility | Name of the facility or activity used to adjust a widget. | String | Yes (initial value: left empty) |
| formVisibleNotify | Whether the widget is allowed to use the widget visibility notification. | String | Yes (initial value: left empty) |
| jsComponentName | Component name of the widget. The value is a string with a maximum of 127 bytes. This field is required only by JavaScript-programmed widgets.| String | No |
| metaData | Metadata of the widget. This field contains the array of the **customizeData** field. | Object | Yes (initial value: left empty) |
| customizeData | Custom information about the widget. | Object array | Yes (initial value: left empty) |
A configuration example is as follows:
```json
"abilities": [{
"name": "FormAbility",
"description": "This is a FormAbility",
"formsEnabled": true,
"icon": "$media:icon",
"label": "$string:form_FormAbility_label",
"srcPath": "FormAbility",
"type": "service",
"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
}]
}]
```
### Widget Data Persistence
Mostly, the widget provider is started only when it needs to obtain information about a widget. The Widget Manager supports multi-instance management and uses the widget ID to identify an instance. If the widget provider supports widget data modification, it must persistently store the data based on the widget ID, so that it can access the data of the target widget when obtaining, updating, or starting a widget.
```javascript
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"];
// Persistently store widget information for subsequent use, such as widget instance retrieval and update.
storeFormInfo(formId, formName, tempFlag, want);
let obj = {
"title": "titleOnCreate",
"detail": "detailOnCreate"
};
let formData = formBindingData.createFormBindingData(obj);
return formData;
}
```
You should override **onDestroy** to delete widget data.
```javascript
onDestroy(formId) {
// Delete widget data.
deleteFormInfo(formId);
console.log('FormAbility onDestroy');
}
```
For details about the persistence method, see [Lightweight Data Store Development](../database/database-preference-guidelines.md).
Note that the **Want** passed by the widget client to the widget provider contains a temporary flag, indicating whether the requested widget is a temporary one.
Normal widget: a widget that will be persistently used by the widget client
Temporary widget: a widget that is temporarily used by the widget client
Data of a temporary widget is not persistently stored. If the widget framework is killed and restarted, data of a temporary widget will be deleted. However, the widget provider is not notified of which widget is deleted, and still keeps the data. Therefore, the widget provider should implement data clearing. In addition, the widget client may convert a temporary widget into a normal one. If the conversion is successful, the widget provider should process the widget ID and store the data persistently. This prevents the widget provider from deleting persistent data when clearing temporary widgets.
### Developing the Widget UI Page
You can use HML, CSS, and JSON to develop the UI page for a JavaScript-programmed widget.
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> Currently, only the JavaScript-based web-like development paradigm can be used to develop the widget UI.
- HML:
```html
<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:
```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:
```json
{
"data": {
"title": "TitleDefault",
"detail": "TextDefault"
},
"actions": {
"routerEvent": {
"action": "router",
"abilityName": "com.example.MyApplication.hmservice.FormAbility",
"params": {
"message": "add detail"
}
}
}
}
```
Now you've got a widget shown below.
![fa-form-example](figures/fa-form-example.png)
此差异已折叠。
......@@ -18,12 +18,14 @@
- Media
- [Audio Management](js-apis-audio.md)
- [Media](js-apis-media.md)
- [Image Processing](js-apis-image.md)
- [Camera](js-apis-camera.md)
- Security
- [User Authentication](js-apis-useriam-userauth.md)
- [Access Control](js-apis-abilityAccessCtrl.md)
- Data Management
- [Lightweight Storage<sup>9+</sup>](js-apis-data-preferences.md)
- [Lightweight Storage](js-apis-data-storage.md)
- [Lightweight Storage](js-apis-data-storage.md)
- [Distributed Data Management](js-apis-distributed-data.md)
- [Relational Database](js-apis-data-rdb.md)
- [Result Set](js-apis-data-resultset.md)
......@@ -76,8 +78,6 @@
- [Application Context](js-apis-basic-features-app-context.md)
- [Console Logs](js-apis-basic-features-logs.md)
- [Page Routing](js-apis-basic-features-routes.md)
- [Pop-up Window](js-apis-basic-features-pop-up.md)
- [Application Configuration](js-apis-basic-features-configuration.md)
- [Timer](js-apis-basic-features-timer.md)
- [Setting the System Time](js-apis-system-time.md)
- [Animation](js-apis-basic-features-animator.md)
......
......@@ -3058,7 +3058,6 @@ Reads the buffer from the audio capturer. This API uses an asynchronous callback
audioCapturer.read(bufferSize, true, async(err, buffer) => {
if (!err) {
console.log("Success in reading the buffer data");
var number = fileio.writeSync(fd, buffer);
}
};
```
......
......@@ -1311,7 +1311,7 @@ Disconnects an A2DP connection.
```js
let a2dpSrc = bluetooth.getProfile(PROFILE_A2DP_SOURCE);
let boolean ret = a2dpSrc.disconnect('XX:XX:XX:XX:XX:XX');
let ret = a2dpSrc.disconnect('XX:XX:XX:XX:XX:XX');
```
......
......@@ -563,7 +563,7 @@ Enables listening for error events of the UDPSocket connection. This API uses an
**Example**
```
let udp = socket.constructUDPSocketInstance()
let udp = socket.constructUDPSocketInstance();
udp.on('error', err => {
console.log("on error, err:" + JSON.stringify(err))
});
......@@ -591,7 +591,7 @@ Disables listening for error events of the UDPSocket connection. This API uses a
**Example**
```
let udp = socket.constructUDPSocketInstance()
let udp = socket.constructUDPSocketInstance();
let callback = err =>{
console.log("on error, err:" + JSON.stringify(err));
}
......
# WLAN
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**<br/>
> The initial APIs of this module are supported since API version 8. Newly added APIs will be marked with a superscript to indicate their earliest API version.<br/>
The APIs described in this document are used only for non-universal products, such as routers.
## Modules to Import
```js
import wifiext from '@ohos.wifiext';
```
## wifiext.enableHotspot
enableHotspot(): boolean;
Enables the WLAN hotspot.
- Required permissions:
ohos.permission.MANAGE_WIFI_HOTSPOT_EXT
- System capability:
SystemCapability.Communication.WiFi.HotspotExt
- Return value
| **Type**| **Description**|
| -------- | -------- |
| boolean | Returns **true** if the operation is successful; returns **false** otherwise.|
## wifiext.disableHotspot
disableHotspot(): boolean;
Disables the WLAN hotspot.
- Required permissions:
ohos.permission.MANAGE_WIFI_HOTSPOT_EXT
- System capability:
SystemCapability.Communication.WiFi.HotspotExt
- Return value
| **Type**| **Description**|
| -------- | -------- |
| boolean | Returns **true** if the operation is successful; returns **false** otherwise.|
## wifiext.getSupportedPowerModel
getSupportedPowerModel(): Promise&lt;Array&lt;PowerModel&gt;&gt;
Obtains the supported power models. The method uses a promise to return the result.
- Required permissions:
ohos.permission.GET_WIFI_INFO
- System capability:
SystemCapability.Communication.WiFi.HotspotExt
- Return value
| Type| Description|
| -------- | -------- |
| Promise&lt;Array&lt;[PowerModel](#PowerModel)&gt;&gt; | Promise used to return the power models obtained.|
## PowerModel
Enumerates of the power models.
| Name| Default Value| Description|
| -------- | -------- | -------- |
| SLEEPING | 0 | Sleeping|
| GENERAL | 1 | General|
| THROUGH_WALL | 2 | Through_wall|
## wifiext.getSupportedPowerModel
getSupportedPowerModel(callback: AsyncCallback&lt;Array&lt;PowerModel&gt;&gt;): void
Obtains the supported power models. The method uses an asynchronous callback to return the result.
- Required permissions:
ohos.permission.GET_WIFI_INFO
- System capability:
SystemCapability.Communication.WiFi.HotspotExt
- Parameters
| Name| Type| Mandatory| Description|
| -------- | -------- | -------- | -------- |
| callback | AsyncCallback&lt;[PowerModel](#PowerModel)&gt; | Yes| Callback used to return the power models obtained.|
## wifiext.getPowerModel
getPowerModel(): Promise&lt;PowerModel&gt;
Obtains the power model. The method uses a promise to return the result.
- Required permissions:
ohos.permission.GET_WIFI_INFO
- System capability:
SystemCapability.Communication.WiFi.HotspotExt
- Return value
| Type| Description|
| -------- | -------- |
| Promise&lt;[PowerModel](#PowerModel)&gt; | Promise used to return the power model obtained.|
## wifiext.getPowerModel
getPowerModel(callback: AsyncCallback&lt;PowerModel&gt;): void
Obtains the power model. The method uses an asynchronous callback to return the result.
- Required permissions:
ohos.permission.GET_WIFI_INFO
- System capability:
SystemCapability.Communication.WiFi.HotspotExt
- Parameters
| Name| Type| Mandatory| Description|
| -------- | -------- | -------- | -------- |
| callback | AsyncCallback&lt;[PowerModel](#PowerModel)&gt; | Yes| Callback invoked to return the power mode obtained.|
## wifiext.setPowerModel
setPowerModel(model: PowerModel) : boolean;
Sets the power model.
- Required permissions:
ohos.permission.MANAGE_WIFI_HOTSPOT_EXT
- System capability:
SystemCapability.Communication.WiFi.HotspotExt
- Parameters
| Name| Type| Mandatory| Description|
| -------- | -------- | -------- | -------- |
| model | AsyncCallback&lt;[PowerModel](#PowerModel)&gt; | Yes| Power model to set.|
- Return value
| **Type**| **Description**|
| -------- | -------- |
| boolean | Returns **true** if the operation is successful; returns **false** otherwise.|
......@@ -73,6 +73,7 @@
- [TextInput](ts-basic-components-textinput.md)
- [TextPicker](ts-basic-components-textpicker.md)
- [TextTimer](ts-basic-components-texttimer.md)
- [TimePicker](ts-basic-components-timepicker.md)
- [Toggle](ts-basic-components-toggle.md)
- [TextClock](ts-basic-components-textclock.md)
- [Web](ts-basic-components-web.md)
......@@ -143,6 +144,7 @@
- [Action Sheet](ts-methods-action-sheet.md)
- [Custom Dialog Box](ts-methods-custom-dialog-box.md)
- [Date Picker Dialog Box](ts-methods-datepicker-dialog.md)
- [Time Picker Dialog Box](ts-methods-timepicker-dialog.md)
- [Text Picker Dialog Box](ts-methods-textpicker-dialog.md)
- [Menu](ts-methods-menu.md)
- Appendix
......
# DatePicker
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This component is supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version.
The **&lt;DatePicker&gt;** component allows users to select date and time.
The **\<DatePicker>** component allows users to select a date from the given range.
## Required Permissions
None
No
## Child Components
None
No
## APIs
DatePicker(value:{start?: Date, end?: Date, selected?: Date, type?: DatePickerType})
DatePicker(options?: DatePickerOptions)
Creates a date picker that allows users to select a date or time within the specified range.
Creates a date picker in the given date range.
- Parameters
| Name | Type | Mandatory | Default Value | Description |
- options parameters
| Name| Type| Mandatory| Default Value| Description|
| -------- | -------- | -------- | -------- | -------- |
| start | Date | No | Date('1970-1-1') | Start date of the date picker. |
| end | Date | No | Date('2100-12-31') | End date of the date picker. |
| selected | Date | No | Current system date or time | Selected date when **type** is set to **DatePickerType.Date** and selected time when **type** is set to **DatePickerType.Time**. |
| type | DatePickerType | No | DatePickerType.Date | Picker type, which can be date picker and time picker. The date picker is used by default. |
- DatePickerType enums
| Name | Description |
| -------- | -------- |
| Date | Date picker. |
| Time | Time picker. |
| start | Date | No| Date('1970-1-1') | Start date of the picker.|
| end | Date | No| Date('2100-12-31') | End date of the picker.|
| selected | Date | No| Current system date| Date of the selected item.|
## Attributes
| Name | Type | Default Value | Description |
| -------- | -------- | -------- |-------- |
| lunar | boolean | false | Whether to display the lunar calendar.<br/>- **true**: The lunar calendar is displayed.<br/>- **false**: The lunar calendar is not displayed. |
| useMilitaryTime | boolean | false | Whether the display time is in 24-hour format. The value cannot be dynamically modified. |
| Name| Type| Default Value| Description|
| -------- | -------- | -------- | -------- |
| lunar | boolean | false | Whether to display the lunar calendar.<br>-&nbsp;**true**: Display the lunar calendar.<br>-&nbsp;**false**: Do not display the lunar calendar.|
## Events
| Name | Description |
| Name| Description|
| -------- | -------- |
| onChange(callback: (value: DatePickerResult) =&gt; void) | This event is triggered when a date or time is selected. |
| onChange(callback:&nbsp;(value:&nbsp;DatePickerResult)&nbsp;=&gt;&nbsp;void) | Triggered when a date is selected.|
- DatePickerResult
| Name | Type | Description |
| -------- | -------- | -------- |
| year | number | Year of the selected date (when **type** is **DatePickerType.Date**). |
| month | number | Month of the selected date (when **type** is **DatePickerType.Date**). |
| day | number | Date of the selected date (when **type** is **DatePickerType.Date**). |
| hour | number | Hour portion of the selected time (when **type** is **DatePickerType.Time**). |
| minute | number | Minute portion of the selected time (when **type** is **DatePickerType.Time**). |
### DatePickerResult
| Name| Type| Description|
| -------- | -------- | -------- |
| year | number | Year of the selected date.|
| month | number | Month of the selected date.|
| day | number | Day of the selected date.|
## Example
### Date Picker (with Lunar Calendar)
### Date Picker Sample Code (With Lunar Calendar)
```
@Entry
......@@ -79,9 +67,8 @@ struct DatePickerExample01 {
Column() {
DatePicker({
start: new Date('1970-1-1'),
end: new Date('2200-1-1'),
end: new Date('2100-1-1'),
selected: this.selectedDate,
type: DatePickerType.Date
})
.lunar(true)
.onChange((date: DatePickerResult) => {
......@@ -93,8 +80,7 @@ struct DatePickerExample01 {
```
### Date Picker (Without Lunar Calendar)
### Date Picker Sample Code (No Lunar Calendar)
```
@Entry
......@@ -106,9 +92,8 @@ struct DatePickerExample02 {
Column() {
DatePicker({
start: new Date('1970-1-1'),
end: new Date('2200-1-1'),
end: new Date('2100-1-1'),
selected: this.selectedDate,
type: DatePickerType.Date
})
.lunar(false)
.onChange((date: DatePickerResult) => {
......@@ -120,31 +105,3 @@ struct DatePickerExample02 {
```
### Time Picker
```
@Entry
@Component
struct DatePickerExample03 {
private selectedTime: Date = new Date('2021-9-29 08:00:00')
build() {
Column() {
DatePicker({
start: new Date('00:00:00'),
end: new Date('23:59:59'),
selected: this.selectedTime,
type: DatePickerType.Time
})
.useMilitaryTime(true)
.onChange((date: DatePickerResult) => {
console.info('select current date is: ' + JSON.stringify(date))
})
}.width('100%')
}
}
```
![en-us_image_0000001256858401](figures/en-us_image_0000001256858401.gif)
# TimePicker
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This component is supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version.
The **\<TimePicker>** component allows users to select a time from the given range.
## Required Permissions
No
## Child Components
No
## APIs
TimePicker(options?: TimePickerOptions)
Creates a time picker whose default time range is from 00:00 to 23:59.
- options parameters
| Name| Type| Mandatory| Default Value| Description|
| -------- | -------- | -------- | -------- | -------- |
| selected | Date | No| Current system time| Time of the selected item.|
## Attributes
| Name| Type| Default Value| Description|
| -------- | -------- | -------- | -------- |
| useMilitaryTime | boolean | false | Whether to display time in 24-hour format. The value cannot be modified dynamically.|
## Events
| Name| Description|
| -------- | -------- |
| onChange(callback:&nbsp;(value:&nbsp;TimePickerResult )&nbsp;=&gt;&nbsp;void) | Triggered when a time is selected.|
### TimePickerResult
| Name| Type| Description|
| -------- | -------- | -------- |
| hour | number | Hour portion of the selected time.|
| minute | number | Minute portion of the selected time.|
## Example
### Time Picker
```
@Entry
@Component
struct TimePickerExample {
private selectedTime: Date = new Date('08-00')
build() {
Column() {
TimePicker({
selected: this.selectedTime,
})
.useMilitaryTime(true)
.onChange((date: TimePickerResult) => {
console.info('select current date is: ' + JSON.stringify(date))
})
}.width('100%')
}
}
```
![en-us_image_0000001251292933](figures/en-us_image_0000001251292933.gif)
......@@ -3,7 +3,7 @@
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This component is supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version.
You can display a date or time picker in a dialog box to allow users to select a date or time from the given range.
You can display a date picker in a dialog box to allow users to select a date from the given range.
## Required Permissions
......@@ -11,22 +11,20 @@ None
## DatePickerDialog.show
show(options?: DatePickerDialogOption)
show(options?: DatePickerDialogOptions)
Shows a date or time picker in the given settings.
Defines and displays a date picker dialog box.
- DatePickerDialogOption parameters
- options parameters
| Name| Type| Mandatory| Default Value| Description|
| -------- | -------- | -------- | -------- | -------- |
| start | Date | No| Date('1970-1-1') | Start date of the picker.|
| end | Date | No| Date('2100-12-31') | End date of the picker.|
| selected | Date | No| Current system date or time| Date or time of the selected item in the picker. When **type** is set to **DatePickerType.Date**, this parameter indicates the date of the selected item. When **type** is set to **DatePickerType.Time**, this parameter indicates the time of the selected item.|
| type | [DatePickerType](ts-basic-components-datepicker.md) | No| DatePickerType.Date | Picker type, which can be the date picker and time picker.|
| selected | Date | No| Current system date| Date of the selected item.|
| lunar | boolean | No| false | Whether to display the lunar calendar.|
| useMilitaryTime | boolean | No| false | Whether to display time in 24-hour format.|
| onAccept | (value: [DatePickerResult](ts-basic-components-datepicker.md)) => void | No| - | Triggered when the OK button in the dialog box is clicked.|
| onAccept | (value: [DatePickerResult](ts-basic-components-datepicker.md#DatePickerResult)) => void | No| - | Triggered when the OK button in the dialog box is clicked.|
| onCancel | () => void | No| - | Triggered when the Cancel button in the dialog box is clicked.|
| onChange | (value: [DatePickerResult](ts-basic-components-datepicker.md)) => void | No| - | Triggered when the selected item in the picker changes.|
| onChange | (value: [DatePickerResult](ts-basic-components-datepicker.md#DatePickerResult)) => void | No| - | Triggered when the selected item in the picker changes.|
## Example
......@@ -36,8 +34,6 @@ Shows a date or time picker in the given settings.
@Component
struct DatePickerDialogExample01 {
@State isLunar: boolean = true
@State isUseMilitaryTime: boolean = false
@State datePickerType: DatePickerType = DatePickerType.Date
selectedDate: Date = new Date("2000-1-1")
build() {
......@@ -48,15 +44,10 @@ struct DatePickerDialogExample01 {
start: new Date("2000-1-1"),
end: new Date("2005-1-1"),
selected: this.selectedDate,
type: this.datePickerType,
lunar: this.isLunar,
useMilitaryTime: this.isUseMilitaryTime,
onAccept: (value: DatePickerResult) => {
this.selectedDate.setFullYear(value.year, value.month, value.day)
console.info("DatePickerDialog:onAccept()" + JSON.stringify(value))
if (this.datePickerType == DatePickerType.Date) {
this.selectedDate.setFullYear(value.year, value.month, value.day)
} else if (this.datePickerType == DatePickerType.Time) {
this.selectedDate.setHours(value.hour, value.minute, value.second)
}
},
onCancel: () => {
......@@ -77,8 +68,6 @@ struct DatePickerDialogExample01 {
@Component
struct DatePickerDialogExample02 {
@State isLunar: boolean = false
@State isUseMilitaryTime: boolean = false
@State datePickerType: DatePickerType = DatePickerType.Date
selectedDate: Date = new Date("2000-1-1")
build() {
......@@ -89,97 +78,10 @@ struct DatePickerDialogExample02 {
start: new Date("2000-1-1"),
end: new Date("2005-1-1"),
selected: this.selectedDate,
type: this.datePickerType,
lunar: this.isLunar,
useMilitaryTime: this.isUseMilitaryTime,
onAccept: (value: DatePickerResult) => {
this.selectedDate.setFullYear(value.year, value.month, value.day)
console.info("DatePickerDialog:onAccept()" + JSON.stringify(value))
if (this.datePickerType == DatePickerType.Date) {
this.selectedDate.setFullYear(value.year, value.month, value.day)
} else if (this.datePickerType == DatePickerType.Time) {
this.selectedDate.setHours(value.hour, value.minute, value.second)
}
},
onCancel: () => {
console.info("DatePickerDialog:onCancel()")
},
onChange: (value: DatePickerResult) => {
console.info("DatePickerDialog:onChange()" + JSON.stringify(value))
}
})
})
}
}
}
```
### Time Picker Sample Code (24-Hour Clock)
```
@Entry
@Component
struct DatePickerDialogExample03 {
@State isLunar: boolean = false
@State isUseMilitaryTime: boolean = true
@State datePickerType: DatePickerType = DatePickerType.Time
selectedDate: Date = new Date("2000-1-1")
build() {
Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center,
justifyContent: FlexAlign.Center }) {
Button("DatePickerDialog").onClick(() => {
DatePickerDialog.show({
start: new Date("2000-1-1"),
end: new Date("2005-1-1"),
selected: this.selectedDate,
type: this.datePickerType,
lunar: this.isLunar,
useMilitaryTime: this.isUseMilitaryTime,
onAccept: (value: DatePickerResult) => {
console.info("DatePickerDialog:onAccept()" + JSON.stringify(value))
if (this.datePickerType == DatePickerType.Date) {
this.selectedDate.setFullYear(value.year, value.month, value.day)
} else if (this.datePickerType == DatePickerType.Time) {
this.selectedDate.setHours(value.hour, value.minute, value.second)
}
},
onCancel: () => {
console.info("DatePickerDialog:onCancel()")
},
onChange: (value: DatePickerResult) => {
console.info("DatePickerDialog:onChange()" + JSON.stringify(value))
}
})
})
}
}
}
```
### Time Picker Sample Code (12-Hour Clock)
```
@Entry
@Component
struct DatePickerDialogExample04 {
@State isLunar: boolean = false
@State isUseMilitaryTime: boolean = false
@State datePickerType: DatePickerType = DatePickerType.Time
selectedDate: Date = new Date("2000-1-1")
build() {
Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center,
justifyContent: FlexAlign.Center }) {
Button("DatePickerDialog").onClick(() => {
DatePickerDialog.show({
start: new Date("2000-1-1"),
end: new Date("2005-1-1"),
selected: this.selectedDate,
type: this.datePickerType,
lunar: this.isLunar,
useMilitaryTime: this.isUseMilitaryTime,
onAccept: (value: DatePickerResult) => {
console.info("DatePickerDialog:onAccept()" + JSON.stringify(value))
if (this.datePickerType == DatePickerType.Date) {
this.selectedDate.setFullYear(value.year, value.month, value.day)
} else if (this.datePickerType == DatePickerType.Time) {
this.selectedDate.setHours(value.hour, value.minute, value.second)
}
},
onCancel: () => {
......
# Time Picker Dialog Box
> ![icon-note.gif](public_sys-resources/icon-note.gif) **NOTE**
> This component is supported since API version 8. Updates will be marked with a superscript to indicate their earliest API version.
You can display a time picker in a dialog box to allow users to select a time from the given range, which is from 00:00 to 23:59 by default.
## Required Permissions
None
## TimePickerDialog.show
show(options?: TimePickerDialogOptions)
Defines and displays a time picker dialog box.
- options parameters
| Name| Type| Mandatory| Default Value| Description|
| -------- | -------- | -------- | -------- | -------- |
| selected | Date | No| Current system time| Time of the selected item.|
| useMilitaryTime | boolean | No| false | Whether to display time in 24-hour format.|
| onAccept | (value: [TimePickerResult](ts-basic-components-timepicker.md#TimePickerResult)) => void | No| - | Triggered when the OK button in the dialog box is clicked.|
| onCancel | () => void | No| - | Triggered when the Cancel button in the dialog box is clicked.|
| onChange | (value: [TimePickerResult](ts-basic-components-timepicker.md#TimePickerResult)) => void | No| - | Triggered when the selected item in the picker changes.|
## Example
### Time Picker Sample Code (24-Hour Clock)
```
@Entry
@Component
struct TimePickerDialogExample01 {
@State isUseMilitaryTime: boolean = true
build() {
Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center,
justifyContent: FlexAlign.Center }) {
Button("TimePickerDialog").onClick(() => {
TimePickerDialog.show({
useMilitaryTime: this.isUseMilitaryTime,
onAccept: (value: TimePickerResult) => {
this.selectedDate.setHours(value.hour, value.minute, value.second)
console.info("TimePickerDialog:onAccept()" + JSON.stringify(value))
},
onCancel: () => {
console.info("TimePickerDialog:onCancel()")
},
onChange: (value: TimePickerResult) => {
console.info("TimePickerDialog:onChange()" + JSON.stringify(value))
}
})
})
}
}
}
```
### Time Picker Sample Code (12-Hour Clock)
```
@Entry
@Component
struct TimePickerDialogExample02 {
@State isUseMilitaryTime: boolean = false
build() {
Flex({direction: FlexDirection.Column, alignItems: ItemAlign.Center,
justifyContent: FlexAlign.Center }) {
Button("TimePickerDialog").onClick(() => {
TimePickerDialog.show({
useMilitaryTime: this.isUseMilitaryTime,
onAccept: (value: TimePickerResult) => {
this.selectedDate.setHours(value.hour, value.minute, value.second)
console.info("TimePickerDialog:onAccept()" + JSON.stringify(value))
},
onCancel: () => {
console.info("TimePickerDialog:onCancel()")
},
onChange: (value: TimePickerResult) => {
console.info("TimePickerDialog:onChange()" + JSON.stringify(value))
}
})
})
}
}
}
```
# Application Development
# OpenHarmony Application Development Documentation
- [Application Development Overview](application-dev-guide.md)
- Quick Start
......
# Vibrator
## Overview
### Introduction
Developed on the Hardware Driver Foundation (HDF), the vibrator driver model makes vibrator driver development easier. This model masks the interaction between the device driver and system, provides unified and stable driver interfaces for the hardware service layer, and offers open interfaces and interface parsing capabilities for driver developers. This document provides guidance for developing vibrator drivers and deploying vibrators in different OSs. The figure below shows the vibrator driver model.
**Figure 1** Vibrator driver model
![Vibrator driver model](figures/vibrator_driver_model.png)
### Basic Concepts
The system controls device vibration by invoking the vibrator. There are two vibration modes:
- One-shot vibration
The vibrator vibrates for a specified duration.
- Periodic vibration
The vibrator vibrates with a preset effect. For example, if the preset effect is "haptic.clock.timer" = [600, 600, 200, 600], the vibrator waits for 600 ms, vibrates for 600 ms, waits for 200 ms, and vibrates for 600 ms.
### Working Principles
Based on the loading and running process (shown below) of the vibrator driver model, the relationships between key modules in the model and associated modules are clearly defined.
**Figure 2** How vibrator driver works
![How vibrator driver works](figures/vibrator_working.png)
The following uses the vibrator driver on the Hi3516D V300 development board of the standard system as an example to describe the driver loading and running process.
1. The vibrator host reads the vibrator management configuration from the Vibrator Host node of the device_info HCS (vibrator device information HCS).
2. The vibrator host parses the vibrator management configuration and associates it with the corresponding vibrator abstract driver.
3. The vibrator host reads the vibrator data configuration from the linear_vibrator_config HCS (vibrator private configuration HCS).
4. The vibrator host parses the vibrator data configuration and associates it with the corresponding vibrator haptic driver.
5. The vibrator proxy delivers an instruction to the vibrator stub.
6. The vibrator stub calls the vibrator controller.
7. The vibrator host initializes the vibrator abstract driver interfaces.
8. The vibrator haptic driver starts a thread to parse the vibrator haptic module.
9. The vibrator haptic driver calls the **Start** interface in the vibrator abstract driver.
10. The vibrator abstract driver calls the **Start** interface in the vibrator chipset driver.
## Development Guidelines
### When to Use
You can set different vibration effects as needed, for example, customizing vibration effects with different intensities and durations for buttons on the device, and customizing one-shot or periodic vibration effects with different intensities and durations for alarm clocks and incoming calls.
### Available APIs
The vibrator driver model supports static HDF Configuration Source (HCS) configurations and dynamic parameter configurations. The vibrator hardware service calls the **StartOnce** interface to trigger continuous vibration and calls the **Start** interface to trigger vibration with a specified effect. The table below lists the APIs provided by the vibrator driver model for the hardware service layer.
**Table 1** External APIs of the vibrator driver model
| API | Description |
| -------------------------------------- | -------------------------------------------------------- |
| int32_t StartOnce(uint32_t duration) | Triggers vibration with a given **duration**. |
| int32_t Start(const char *effectType) | Triggers vibration with a given effect, which is specified by **effectType**.|
| int32_t Stop(enum VibratorMode mode) | Stops vibration. |
### How to Develop
The vibrator driver model provides stable interfaces for the upper-layer hardware service to trigger a one-shot vibration with a given duration, trigger vibration with a given effect, and stop vibration. The model implements functionalities such as cross-OS migration and differentiated configurations. To develop a vibrator, perform the following steps:
1. Develop the vibrator abstract driver based on the driver entry. Specifically, implement the **Bind**, **Init**, **Release**, and **Dispatch** functions, configure resources, and parse HCS configurations.
- Call **HDF_INIT** to register the driver entry with the HDF. During driver loading, the HDF calls the **Bind** function and then the **Init** function to load the driver. If the **Init** function fails to be called, the HDF calls **Release** to release the driver resources and exit the vibrator driver model. The vibrator driver model uses the HCS as the configuration source code. For details about HCS fields, see [Driver Configuration Management](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf-manage.md). The driver entry function is defined as follows:
```c
/* Register the entry structure object of the vibrator abstract driver. */
struct HdfDriverEntry g_vibratorDriverEntry = {
.moduleVersion = 1, // Version of the vibrator module.
.moduleName = "HDF_VIBRATOR", // Vibrator module name. The value must be the same as the value of moduleName in the device_info.hcs file.
.Bind = BindVibratorDriver, // Function for binding a vibrator.
.Init = InitVibratorDriver, // Function for initializing a vibrator.
.Release = ReleaseVibratorDriver, // Function for releasing vibrator resources.
};
HDF_INIT(g_vibratorDriverEntry);
```
- Develop the vibrator abstract driver. Specifically, implement the **Bind**, **Init**, **Release**, and **Dispatch** functions.
```c
/* External service published by the vibrator driver. */
static int32_t DispatchVibrator(struct HdfDeviceIoClient *client,
int32_t cmd, struct HdfSBuf *data, struct HdfSBuf *reply)
{
int32_t loop;
for (loop = 0; loop < sizeof(g_vibratorCmdHandle) / sizeof(g_vibratorCmdHandle[0]); ++loop) {
if ((cmd == g_vibratorCmdHandle[loop].cmd) && (g_vibratorCmdHandle[loop].func != NULL)) {
return g_vibratorCmdHandle[loop].func(data, reply);
}
}
return HDF_SUCCESS;
}
/* Bind the external service provided by the vibrator driver to the HDF. */
int32_t BindVibratorDriver(struct HdfDeviceObject *device)
{
struct VibratorDriverData *drvData = NULL;
CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE);
drvData = (struct VibratorDriverData *)OsalMemCalloc(sizeof(*drvData));
CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_ERR_MALLOC_FAIL);
drvData->ioService.Dispatch = DispatchVibrator;
drvData->device = device;
device->service = &drvData->ioService;
g_vibratorDrvData = drvData;
return HDF_SUCCESS;
}
/* Entry function for vibrator driver initialization. */
int32_t InitVibratorDriver(struct HdfDeviceObject *device)
{
struct VibratorDriverData *drvData = NULL;
drvData->mode = VIBRATOR_MODE_BUTT;
drvData->state = VIBRATOR_STATE_IDLE;
......
if (CreateVibratorHaptic(device) != HDF_SUCCESS) {
HDF_LOGE("%s: init workQueue fail!", __func__);
return HDF_FAILURE;
}
return HDF_SUCCESS;
}
/* Release the resources allocated during vibrator driver initialization. */
void ReleaseVibratorDriver(struct HdfDeviceObject *device)
{
struct VibratorDriverData *drvData = NULL;
......
(void)DestroyVibratorHaptic();
(void)OsalMutexDestroy(&drvData->mutex);
(void)OsalMemFree(drvData);
g_vibratorDrvData = NULL;
}
```
- During system startup, the HDF configuration management loads the vibrator abstract driver based on the device information HCS and publishes the vibrator driver interfaces.
```c
/* Device information HCS. */
vibrator :: host {
hostName = "vibrator_host";
device_vibrator :: device {
device0 :: deviceNode {
policy = 2; // Policy for publishing the driver service.
priority = 100; // Driver startup priority (0–200). A larger value indicates a lower priority. The default value 100 is recommended. The sequence for loading devices with the same priority is random.
preload = 0; // Field for specifying whether to load the driver. The value 0 means to load the driver, and 2 means the opposite.
permission = 0664; // Permission for the driver to create a device node.
moduleName = "HDF_VIBRATOR"; // Driver name. The value must be the same as that of moduleName in the driver entry structure.
serviceName = "hdf_misc_vibrator"; // Name of the service provided by the driver. The name must be unique.
deviceMatchAttr = "hdf_vibrator_driver"; // Keyword matching the private data of the driver. The value must be the same as that of match_attr in the private data configuration table of the driver.
}
}
```
2. Create a vibrator haptic model and parse the haptic HCS configuration.
- Create a vibrator haptic model.
```hcs
/* Create a vibrator haptic model, allocate resources, and parse the haptic HCS configuration. */
int32_t CreateVibratorHaptic(struct HdfDeviceObject *device)
{
struct VibratorHapticData *hapticData = NULL;
CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(device, HDF_FAILURE);
hapticData = (struct VibratorHapticData *)OsalMemCalloc(sizeof(*hapticData));
CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(hapticData, HDF_ERR_MALLOC_FAIL);
g_vibratorHapticData = hapticData;
hapticData->supportHaptic = false;
if (OsalMutexInit(&hapticData->mutex) != HDF_SUCCESS) {
HDF_LOGE("%s: fail to init mutex", __func__);
goto EXIT;
}
DListHeadInit(&hapticData->effectSeqHead);
/* Parse the haptic HCS configuration. */
if (ParserVibratorHapticConfig(device->property) != HDF_SUCCESS) {
HDF_LOGE("%s: parser haptic config fail!", __func__);
goto EXIT;
}
return HDF_SUCCESS;
EXIT:
OsalMemFree(hapticData);
return HDF_FAILURE;
}
```
- The vibrator effect model uses the HCS. For details about HCS fields, see [Driver Configuration Management](https://gitee.com/openharmony/docs/blob/master/en/device-dev/driver/driver-hdf-manage.md).
```
/* Vibrator data configuration template (vibrator_config.hcs). */
root {
vibratorConfig {
boardConfig {
match_attr = "hdf_vibrator_driver"; // The value must be the same as that of the match_attr field configured for the vibrator.
vibratorAttr {
/* The value 0 means a rotor vibrator, and 1 means a linear vibrator. */
deviceType = 1; // Device type.
supportPreset = 1; // Supported preset type.
}
vibratorHapticConfig {
haptic_clock_timer {
effectName = "haptic.clock.timer";
type = 1; // The value 0 means the built-in mode, and 1 means the time sequence.
seq = [600, 600, 200, 600]; // Time sequence.
}
haptic_default_effect {
effectName = "haptic.default.effect";
type = 0;
seq = [0, 3, 800, 1];
}
}
}
}
}
```
3. Develop the interfaces for starting and stopping vibration. A timer will be created and destroyed based on the vibration effect.
The vibrator hardware service calls **StartOnce** to start one-shot vibration with a given duration and calls **StartEffect** to start vibration with a specified effect.
```c
/* Trigger vibration with a given duration. */
static int32_t StartOnce(struct HdfSBuf *data, struct HdfSBuf *reply)
{
uint32_t duration;
int32_t ret;
struct VibratorEffectCfg config;
struct VibratorDriverData *drvData = GetVibratorDrvData();
(void)reply;
......
config.cfgMode = VIBRATOR_MODE_ONCE;
config.duration = duration;
config.effect = NULL;
/* Create a timer based on the vibration effect. */
ret = StartHaptic(&config);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: start haptic fail!", __func__);
return ret;
}
return HDF_SUCCESS;
}
/* Trigger vibration with a given effect. */
static int32_t StartEffect(struct HdfSBuf *data, struct HdfSBuf *reply)
{
int32_t ret;
const char *effect = NULL;
struct VibratorEffectCfg config;
struct VibratorDriverData *drvData = GetVibratorDrvData();
(void)reply;
......
config.cfgMode = VIBRATOR_MODE_PRESET;
config.duration = 0;
config.effect = effect;
ret = StartHaptic(&config);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: start haptic fail!", __func__);
return ret;
}
return HDF_SUCCESS;
}
/* Stop vibration based on the specified vibration mode. */
static int32_t Stop(struct HdfSBuf *data, struct HdfSBuf *reply)
{
int32_t ret;
int32_t mode;
struct VibratorDriverData *drvData = GetVibratorDrvData();
(void)reply;
......
/* Stop vibration and destroy the timer. */
ret = StopHaptic();
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: stop haptic fail!", __func__);
return ret;
}
(void)OsalMutexLock(&drvData->mutex);
drvData->mode = VIBRATOR_MODE_BUTT;
(void)OsalMutexUnlock(&drvData->mutex);
return HDF_SUCCESS;
}
```
4. Implement the interfaces for the vibrator chipset driver.
- Register the vibrator chipset driver interfaces when the vibrator chipset driver is initialized successfully.
```c
/* Register the vibrator chipset driver interfaces. */
int32_t RegisterVibrator(struct VibratorOps *ops)
{
struct VibratorDriverData *drvData = GetVibratorDrvData();
CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(ops, HDF_FAILURE);
CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE);
(void)OsalMutexLock(&drvData->mutex);
drvData->ops.Start = ops->Start;
drvData->ops.StartEffect = ops->StartEffect;
drvData->ops.Stop = ops->Stop;
(void)OsalMutexUnlock(&drvData->mutex);
return HDF_SUCCESS;
}
```
- The vibrator driver model provides vibrator chipset driver interfaces. Implement these interfaces as follows:
```c
/* Start a linear vibrator to vibrate with a given duration. */
static int32_t StartLinearVibrator()
{
int32_t ret;
struct VibratorLinearDriverData *drvData = GetLinearVibratorData();
CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE);
......
ret = GpioWrite(drvData->gpioNum, GPIO_VAL_LOW);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: pull gpio%d to %d level failed", __func__, drvData->gpioNum, GPIO_VAL_LOW);
return ret;
}
return HDF_SUCCESS;
}
/* Start a linear vibration to vibrate with a given effect. */
static int32_t StartEffectLinearVibrator(uint32_t effectType)
{
(void)effectType;
HDF_LOGE("%s: vibrator set build-in effect no support!", __func__);
return HDF_SUCCESS;
}
/* Stop a linear vibration based on the specified vibration mode. */
static int32_t StopLinearVibrator()
{
int32_t ret;
struct VibratorLinearDriverData *drvData = GetLinearVibratorData();
CHECK_VIBRATOR_NULL_PTR_RETURN_VALUE(drvData, HDF_FAILURE);
......
ret = GpioWrite(drvData->gpioNum, GPIO_VAL_HIGH);
if (ret != HDF_SUCCESS) {
HDF_LOGE("%s: pull gpio%d to %d level failed", __func__, drvData->gpioNum, GPIO_VAL_HIGH);
return ret;
}
return HDF_SUCCESS;
}
```
......@@ -74,6 +74,7 @@
- [Startup](subsys-boot-overview.md)
- [init Module](subsys-boot-init.md)
- [appspawn Module](subsys-boot-appspawn.md)
- [appspawn Module for the Standard System](subsys-boot-appspawn-standard.md)
- [bootstrap Module](subsys-boot-bootstrap.md)
- [syspara Module](subsys-boot-syspara.md)
- [FAQs](subsys-boot-faqs.md)
......
# appspawn Module for the Standard System<a name="EN-US_TOPIC_0000001063680582"></a>
## Overview<a name="section56901555910"></a>
After being started by the init process, the appspawn process waits for inter-process communication (IPC) messages. Upon receiving a message, the appspawn process starts an application service based on the message content, and grants the corresponding permission to the application service.
### Introduction<a name="section56901555911"></a>
- Security control
<br>Support for setting of SELinux tags for applications
- Application process control
- Support for setting of AccessToken for applications
- Support for simultaneous stopping of all spawn application processes (after stopping of the appspawn process and before a restart)
- Cold start
<br>Support for cold start of applications by using the **aa** command
```
param set appspawn.cold.boot true // Enable cold start.
aa start -d 12345 -a $name -b $package -C
Example:
aa start -d 12345 -a ohos.acts.startup.sysparam.function.MainAbility -b ohos.acts.startup.sysparam.function -C
### Basic Concepts<a name="section56901555912"></a>
**appspawn** is a registered service name. The appspawn process receives requests from the client by listening to messages over the local socket. The message type is an **AppProperty** structure. It is defined in **base/startup/appspawn_standard/interfaces/innerkits/include/sclient_socket.h**.
**Table 1** Field description
<table><thead align="left"><tr id="row6650142913713"><th class="cellrowborder" valign="top" width="39.489999999999995%" id="mcps1.2.3.1.1"><p id="p17650112914379"><a name="p17650112914379"></a><a name="p17650112914379"></a>Field</p>
</th>
<th class="cellrowborder" valign="top" width="60.51%" id="mcps1.2.3.1.2"><p id="p865032916376"><a name="p865032916376"></a><a name="p865032916376"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row36506298373"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p76501029113715"><a name="p76501029113715"></a><a name="p76501029113715"></a>processName</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p2650329183715"><a name="p2650329183715"></a><a name="p2650329183715"></a>Name of the service process to be started. The value contains a maximum of 256 bytes.</p>
</td>
</tr>
<tr id="row36506298373"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p76501029113715"><a name="p76501029113715"></a><a name="p76501029113715"></a>bundleName</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p2650329183715"><a name="p2650329183715"></a><a name="p2650329183715"></a>Bundle name of the application to be started. The value contains a maximum of 256 bytes.</p>
</td>
</tr>
<tr id="row86501129183712"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p2065010298379"><a name="p2065010298379"></a><a name="p2065010298379"></a>soPath</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p13650192963715"><a name="p13650192963715"></a><a name="p13650192963715"></a>Path of the dynamic library specified by the application. The value contains a maximum of 256 bytes.</p>
</td>
</tr>
<tr id="row13650329103719"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p16501292377"><a name="p16501292377"></a><a name="p16501292377"></a>uid</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p186503291371"><a name="p186503291371"></a><a name="p186503291371"></a>UID of the application process to be started. The value must be a positive number.</p>
</td>
</tr>
<tr id="row187625816314"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p188771758833"><a name="p188771758833"></a><a name="p188771758833"></a>gid</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p187716587310"><a name="p187716587310"></a><a name="p187716587310"></a>GID of the application process to be started. The value must be a positive number.</p>
</td>
</tr>
<tr id="row187625816314"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p188771758833"><a name="p188771758833"></a><a name="p188771758833"></a>gidTable</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p187716587310"><a name="p187716587310"></a><a name="p187716587310"></a>Information about the application process group to be started. Its length is specified by **gidCount**. A maximum of 64 process groups are supported. The value must be a positive number.</p>
</td>
</tr>
<tr id="row187625816314"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p188771758833"><a name="p188771758833"></a><a name="p188771758833"></a>gidCount</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p187716587310"><a name="p187716587310"></a><a name="p187716587310"></a>Number of application process groups to be started.</p>
</td>
</tr>
<tr id="row106508294373"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p16501829183715"><a name="p16501829183715"></a><a name="p16501829183715"></a>accessTokenId</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p11650182953717"><a name="p11650182953717"></a><a name="p11650182953717"></a>Token ID for application process permission control.</p>
</td>
</tr>
<tr id="row106508294373"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p16501829183715"><a name="p16501829183715"></a><a name="p16501829183715"></a>apl</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p11650182953717"><a name="p11650182953717"></a><a name="p11650182953717"></a> APL for application process permission control. The value contains a maximum of 32 bytes.</p>
</td>
</tr>
</tbody>
</table>
## Development Guidelines<a name="section56901555913"></a>
The API definitions are provided in **base/startup/appspawn_standard/interfaces/innerkits/include/client_socket.h**. Table 2 is a list of available APIs.
### Available APIs<a name="section56901555914"></a>
**Table 2** Available APIs
<table><thead align="left"><tr id="row6650142913713"><th class="cellrowborder" valign="top" width="39.489999999999995%" id="mcps1.2.3.1.1"><p id="p17650112914379"><a name="p17650112914379"></a><a name="p17650112914379"></a>Field</p>
</th>
<th class="cellrowborder" valign="top" width="60.51%" id="mcps1.2.3.1.2"><p id="p865032916376"><a name="p865032916376"></a><a name="p865032916376"></a>Description</p>
</th>
</tr>
</thead>
<tbody><tr id="row36506298373"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p76501029113715"><a name="p76501029113715"></a><a name="p76501029113715"></a>CreateClient</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p2650329183715"><a name="p2650329183715"></a><a name="p2650329183715"></a>Creates a client.</p>
</td>
</tr>
<tr id="row36506298373"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p76501029113715"><a name="p76501029113715"></a><a name="p76501029113715"></a>CloseClient</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p2650329183715"><a name="p2650329183715"></a><a name="p2650329183715"></a>Closes a client.</p>
</td>
</tr>
<tr id="row86501129183712"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p2065010298379"><a name="p2065010298379"></a><a name="p2065010298379"></a>ConnectSocket</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p13650192963715"><a name="p13650192963715"></a><a name="p13650192963715"></a>Sends a connection request to the appspawn service.</p>
</td>
</tr>
<tr id="row13650329103719"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p16501292377"><a name="p16501292377"></a><a name="p16501292377"></a>WriteSocketMessage</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p186503291371"><a name="p186503291371"></a><a name="p186503291371"></a>Sends a message to the appspawn service.</p>
</td>
</tr>
<tr id="row187625816314"><td class="cellrowborder" valign="top" width="39.489999999999995%" headers="mcps1.2.3.1.1 "><p id="p188771758833"><a name="p188771758833"></a><a name="p188771758833"></a>ReadSocketMessage</p>
</td>
<td class="cellrowborder" valign="top" width="60.51%" headers="mcps1.2.3.1.2 "><p id="p187716587310"><a name="p187716587310"></a><a name="p187716587310"></a>Receives a message from the appspawn service.</p>
</td>
</tr>
</tbody>
</table>
### Development Example<a name="section56901555915"></a>
<br>The following is an example of using related APIs:
```
std::shared_ptr<AppSpawn::ClientSocket> clientSocket = std::make_unique<AppSpawn::ClientSocket>("AppSpawn");
if (clientSocket == nullptr) {
return -1;
}
if (clientSocket->CreateClient() != ERR_OK) {
return -1;
}
if (clientSocket->ConnectSocket() != ERR_OK) {
return -1;;
}
// Construct AppProperty based on the specified property.
clientSocket->WriteSocketMessage((void *)&property, sizeof(AppSpawn::AppProperty));
// Read the result.
int pid;
clientSocket->ReadSocketMessage((void *)&pid, sizeof(pid));
// Normally, the process ID of the application is returned. If the PID is less than or equal to 0, an error has occurred.
```
## FAQ<a name="section56901555916"></a>
### Cold Start Failure<a name="section56901555917"></a>
&emsp; **Symptom**
<br> &emsp; &emsp; Cold start failed because of a command execution failure.
&emsp; **Solution**
<br> &emsp; &emsp; 1. Check whether cold start is enabled.
<br> &emsp; &emsp; 2. Check whether the cold start command is correct.
......@@ -28,13 +28,13 @@ Ability assistant(Ability助手,简称为aa)是实现应用、原子化服
用于启动一个ability。
| 参数 | 参数说明 |
| --------- | ---------------------- |
| -h/--help | 帮助信息。 |
| -d | 可选参数,device id |
| -a | 必选参数,ability name |
| -b | 必选参数,bundle name |
| -D | 可选参数,调试模式 |
| 参数 | 参数说明 |
| --------- | -------------------------- |
| -h/--help | 帮助信息。 |
| -d | 可选参数,`device id` |
| -a | 必选参数,`ability name` |
| -b | 必选参数,`bundle name` |
| -D | 可选参数,调试模式 |
**返回值:**
......@@ -77,18 +77,17 @@ Ability assistant(Ability助手,简称为aa)是实现应用、原子化服
| -a/--all | - | 打印所有mission内的Ability。 |
| -l/--mission-list | type(缺省打印全部) | 打印任务栈信息。<br />type:<br />NORMAL <br />DEFAULT_STANDARD<br />DEFAULT_SINGLE<br />LAUNCHER |
| -e/--extension | elementName | 打印扩展组件信息。 |
| -u/--userId | UserId | 打印指定UserId的栈信息,需要和其他参数组合使用,例如 aa dump -a -u 100、aa dump -d -u 100、 |
| -u/--userId | UserId | 打印指定UserId的栈信息,需要和其他参数组合使用,例如 `aa dump -a -u 100``aa dump -d -u 100` |
| -d/--data | | 打印Data Ability。 |
| -i/--ability | AbilityRecord ID | 打印指定Ability详细信息 |
| -c/--client | | 打印Ability详细信息,需要和其他参数组合使用,例如 aa dump -a -c、aa dump -i 21 -c、 |
| -c/--client | | 打印Ability详细信息,需要和其他参数组合使用,例如 `aa dump -a -c``aa dump -i 21 -c` |
**使用方法:**
```
aa dump -a
```
- **force-stop**
通过bundle name强制停止一个进程。
......
......@@ -2,7 +2,10 @@
​ Ability是应用所具备能力的抽象,也是应用程序的重要组成部分。Ability是系统调度应用的最小单元,是能够完成一个独立功能的组件,一个应用可以包含一个或多个Ability。
​ Ability框架模型结构具有两种形态。第一种形态为FA模型,API 8及其更早版本的应用程序只能使用FA模型进行开发, FA模型将Ability分为FA(Feature Ability)和PA(Particle Ability)两种类型,其中FA支持Page Ability,PA支持Service Ability和Data Ability;从API9开始,Ability框架引入了Stage模型作为第二种应用形态,Stage模型将Ability分为PageAbility和ExtensionAbility两大类,其中ExtensionAbility又被扩展为ServiceExtensionAbility、FormExtensionAbility、DataShareExtensionAbility等等一系列ExtensionAbility,以便满足更多的使用场景。
​ Ability框架模型结构具有两种形态:
- 第一种形态为FA模型。API 8及其更早版本的应用程序只能使用FA模型进行开发。 FA模型将Ability分为FA(Feature Ability)和PA(Particle Ability)两种类型,其中FA支持Page Ability,PA支持Service Ability、Data Ability、以及FormAbility;
- 第二种形态为Stage模型。从API 9开始,Ability框架引入了Stage模型作为第二种应用形态,Stage模型将Ability分为PageAbility和ExtensionAbility两大类,其中ExtensionAbility又被扩展为ServiceExtensionAbility、FormExtensionAbility、DataShareExtensionAbility等等一系列ExtensionAbility,以便满足更多的使用场景。
​ Stage模型的设计,主要是为了方便开发者更加方便地开发出分布式环境下的复杂应用。下表给出了两种模型在设计上的差异:
......
......@@ -33,11 +33,11 @@ IDE文档中介绍,待IDE文档上库补充链接。
## TestRunner介绍
TestRunner是测试框架测试流程入口类,当测试流程启动时,系统会调用TestRunner内相关接口,开发者需要派生该类,并重写onPrepare、onRun方法。IDE在创建应用模板时会初始化一个默认TestRunner,并在onRun方法启动默认的TestAbility。开发者也可以修改TestAbility测试代码内容,也可以修改默认的TestRunner内onPrepare、onRun方法,自行实现测试代码。具体详细内容请参考TestRunnerAPI接口说明[TestRunner](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-testRunner.md)
TestRunner是测试框架测试流程入口类,当测试流程启动时,系统会调用TestRunner内相关接口,开发者需要派生该类,并重写onPrepare、onRun方法。IDE在创建应用模板时会初始化一个默认TestRunner,并在onRun方法启动默认的TestAbility。开发者也可以修改TestAbility测试代码内容,也可以修改默认的TestRunner内onPrepare、onRun方法,自行实现测试代码。具体详细内容请参考TestRunnerAPI接口说明[TestRunner](../reference/apis/js-apis-testRunner.md)
## AbilityMonitor介绍
AbilityMonitor是测试框架提供用来绑定并监听Ability类,开发者可以使用AbilityMonitor绑定Ability,并将AbilityMonitor添加到监听列表。绑定后Ability的创建、生命周期变化等会触发AbilityMonitor内相关回调函数,开发者可以在对应回调函数内进行测试验证。具体详细内容请参考AbilityMonitor API接口说明[AbilityMonitor](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-application-abilityMonitor.md)
AbilityMonitor是测试框架提供用来绑定并监听Ability类,开发者可以使用AbilityMonitor绑定Ability,并将AbilityMonitor添加到监听列表。绑定后Ability的创建、生命周期变化等会触发AbilityMonitor内相关回调函数,开发者可以在对应回调函数内进行测试验证。具体详细内容请参考AbilityMonitor API接口说明[AbilityMonitor](../reference/apis/js-apis-application-abilityMonitor.md)
**示例**
......@@ -112,7 +112,7 @@ abilityDelegator.startAbility(want, (err, data) => {
### 调度Ability生命周期
AbilityDelegator提供对Ability生命周期进行显示调度,支持Foreground、Background,配合AbilityMonitor中对Ability生命周期监听方法,可以完整的测试Ability生命周期变化。具体详细内容请参考AbilityDelegator API接口说明[AbilityDelegator](https://gitee.com/openharmony/docs/blob/master/zh-cn/application-dev/reference/apis/js-apis-application-abilityDelegator.md#abilitydelegator)
AbilityDelegator提供对Ability生命周期进行显示调度,支持Foreground、Background,配合AbilityMonitor中对Ability生命周期监听方法,可以完整的测试Ability生命周期变化。具体详细内容请参考AbilityDelegator API接口说明[AbilityDelegator](../reference/apis/js-apis-application-abilityDelegator.md)
### 执行shellCMD命令
......
# FA模型综述
## 整体架构
OpenHarmony用户程序的开发本质上就是开发Ability,OpenHarmony系统也是通过调度Ability,通过系统提供的一致性调度契约对Ability进行生命周期管理,从而实现对用户程序的调度。FA模型中Ability分为PageAbility、ServiceAbility和DataAbility三种类型。其中PageAbility具备ArkUI的Ability,是用户具体可见并可以交互的Ability实例;ServiceAbility也是Ability一种,但是没有UI,提供其他Ability调用自定义的服务,在后台运行;DataAbility也是没有UI,提供其他Ability进行数据的增删查服务,在后台运行。
OpenHarmony用户程序的开发本质上就是开发Ability,OpenHarmony系统也是通过调度Ability,通过系统提供的一致性调度契约对Ability进行生命周期管理,从而实现对用户程序的调度。
Ability框架在API 8及更早版本使用FA模型。FA模型中Ability分为PageAbility、ServiceAbility、DataAbility、FormAbility几种类型。其中:
- PageAbility是具备ArkUI实现的Ability,是用户具体可见并可以交互的Ability实例;
- ServiceAbility也是Ability一种,但是没有UI,提供其他Ability调用自定义的服务,在后台运行;
- DataAbility也是没有UI的Ability,提供其他Ability进行数据的增删查服务,在后台运行;
- FormAbility是卡片Ability,是一种界面展示形式。
## 应用包结构
**应用包结构如下图所示:**
![fa-package-info](figures/fa-package-info.png)
应用包结构的配置请参见[包结构说明](../quick-start/package-structure.md)
## 生命周期
**pageAbility生命周期回调如下图所示:**
在所有Ability中,PageAbility因为具有界面,也是应用的交互入口,因此生命周期更加复杂。
**PageAbility生命周期回调如下图所示:**
![fa-pageAbility-lifecycle](figures/fa-pageAbility-lifecycle.png)
开发者可以在 app.js/app.ets 中重写生命周期函数,在对应的生命周期函数内处理应用相应逻辑。
其他类型Ability的生命周期可参考PageAbility生命周期去除前后台切换以及`onShow`的部分进行理解。
开发者可以在 `app.js/app.ets` 中重写生命周期函数,在对应的生命周期函数内处理应用相应逻辑。
## 进程线程模型
......
......@@ -24,10 +24,10 @@
FA卡片开发,即基于[FA模型](fa-brief.md)的卡片提供方开发,主要涉及如下功能逻辑:
- 卡片生命周期回调函数FormAbility开发
- 开发卡片生命周期回调函数FormAbility
- 创建卡片数据FormBindingData对象。
- 通过FormProvider更新卡片。
- 卡片页面开发
- 开发卡片页面
## 接口说明
......@@ -164,7 +164,7 @@ Form需要在应用配置文件config.json中进行配置。
| scheduledUpdateTime | 表示卡片的定点刷新的时刻,采用24小时制,精确到分钟。 | 字符串 | 可缺省,缺省值为“0:0”。 |
| updateDuration | 表示卡片定时刷新的更新周期,单位为30分钟,取值为自然数。<br />当取值为0时,表示该参数不生效。<br />当取值为正整数N时,表示刷新周期为30*N分钟。 | 数值 | 可缺省,缺省值为“0”。 |
| formConfigAbility | 表示用于调整卡片的设施或活动的名称。 | 字符串 | 可缺省,缺省值为空。 |
| formVisibleNotify | 标识是否允许卡片使用卡片可见性通知 | 字符串 | 可缺省,缺省值为空。 |
| formVisibleNotify | 标识是否允许卡片使用卡片可见性通知 | 字符串 | 可缺省,缺省值为空。 |
| jsComponentName | 表示JS卡片的Component名称。字符串最大长度为127字节。仅当卡片类型为JS卡片时,需要配置该标签。 | 字符串 | 否 |
| metaData | 表示卡片的自定义信息,包含customizeData数组标签。 | 对象 | 可缺省,缺省值为空。 |
| customizeData | 表示自定义的卡片信息。 | 对象数组 | 可缺省,缺省值为空。 |
......
......@@ -40,7 +40,7 @@
* 配置应用启动类型
迁移当前只支持多实例应用,需要在在module.json5中配置launchType字段为standard
迁移当前只支持多实例应用,需要在在module.json5中配置launchType字段为standard
```javascript
"launchType": "standard"
......@@ -59,7 +59,7 @@
},
```
这个权限需要在应用首次启动的时候弹窗让用户授予,可以通过在ability的onWindowStageCreate中添加如下代码实现
这个权限需要在应用首次启动的时候弹窗让用户授予,可以通过在ability的onWindowStageCreate中添加如下代码实现
```javascript
requestPermissions = async () => {
......
......@@ -67,7 +67,7 @@
### 进程模型
​ OpenHarmony系统中的应用均满足单进程模型。所谓的单进程模型,是指不允许应用配置多进程,应用中所有的进程都是由系统创建和管理的。每个应用至多并存三进程:
​ OpenHarmony系统中的应用均满足单进程模型。所谓的单进程模型,是指不允许应用配置多进程,应用中所有的进程都是由系统创建和管理的。每个应用至多并存三进程:
- 主进程:运行所有的Ability组件、页面和业务逻辑;
......
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册