preface
In the last article, we wrote an HDF driver and operation of LED hardware on Hongmeng. In this article, we will try to build an App with a simple interface and experience the front-end development process of Hongmeng.
Environment to prepare
1. Install DevEco Studio
Win10 下载 deveco-studio-2.0.12.201.exe 下载 deveco-studio-2.0.12.201.exe 下载 deveco-studio-2.0.12.201.exe
Specify the installation directory
Set optional shortcuts and environment variables
All the way to the next step.
Once you agree to the user agreement, you can start normally.
2. Update the SDK
From the menu Setting->HarmonyOS SDK->SDK Platforms, select Js and Java to install the new SDK.
Also in the SDK Tools, select the new version of Previewer
Click Apply to update
New project
Go to File->New Project… Select Smart Vision and create an empty template application.
Fill in the project name MyUiAPP and click Finish to create a project.
If gradle download is too slow or the version is different, you can download it directly from the following website
https://services.gradle.org/distributions/
Copy the code
The directory structure
Let’s first analyze the directory structure, do Android development will feel more friendly.
1. APP
The HarmonyOS Application Package is released as APP Pack (Application Package), which consists of one or more HAP (HarmonyOS Ability Package) and pack.info that describes the properties of each HAP. HAP is the Ability deployment package, and the HarmonyOS application code is built around the Ability component.
An HAP is a module package composed of codes, resources, third-party libraries and application configuration files, which can be divided into entry and feature module types.
- entry: Indicates the main module of the application. There must be only one APP for the same device type
entry
The type ofHAP
, can be installed and run independently. - feature: Dynamic feature module of the application. a
APP
It can contain one or morefeature
The type ofHAP
Or not. Only containsAbility
theHAP
To be able to run independently.
2. Ability
Ability is the abstraction of the capabilities of an application, and an application can encompass one or more abilities. Ability can be divided into two types: FA (Feature Ability) and PA (Particle Ability). FA/PA is a basic component of an application to realize specific service functions. FA has a UI interface, while PA does not.
3. Resource files
Application resource files (strings, images, and audio files) are stored in the Resources directory for easy use and maintenance. The Resources directory contains two categories of directories: base and qualifier directories and rawfile directories.
4. Configuration file
The config file (config.json) is the Ability information of the application, which states the Ability of the application and the permissions required by the application.
- Global application configuration information, including the application package name, manufacturer, and version.
- Configuration information of an application on a specific device, including the backup and restoration capabilities and network security capabilities of the application.
HAP
Package configuration information, including eachAbility
Basic properties that must be defined (such as package name, class name, type, andAbility
And the permissions required by the application to access the system or other protected parts of the application.
5. JS UI framework
JS UI framework is a high performance cross-device UI development framework, supporting declarative programming and cross-device polymorphic UI.
-
Declarative programming
The JavaScript UI framework uses HTML and CSS declarative programming language as the development language of page layout and page style, while the page business logic supports JavaScript language of ECMAScript specification. JS UI framework provides declarative programming, can let developers avoid writing UI state switch code, view configuration information more intuitive.
-
Across the device
The development framework supports the ability to display UI across devices, automatically maps to different device types during runtime, without the awareness of developers, and reduces the cost of multi-device adaptation for developers.
-
A high performance
The framework includes many core controls, such as lists, images, and various container components, and optimizes the rendering process for declarative syntax.
The JS UI Framework has as its Porting Layer the Application, front end Framework, Engine, and platform Porting Layer.
Air quality monitoring UI
1. Create a home page
The air quality monitoring App contains two interfaces (Page). After the project is created, a Page named Index will be generated, which can be used as the home Page.
2. Create a detail page
Right-click in the Pages directory and choose New->JS Page from the pop-up menu.
Enter the page name detail,
After the detail Page is created, the application project directory is shown in the figure below. Each Page contains three files: layout file HML, style file CSS, and business logic code JS.
3. Develop a home page
The app’s home page mainly shows the city’s air quality. The home page has two screens in total (multiple screens can be set as required), and each screen displays the air quality information of a city, including AQI index, city name, pollutant index, update time and information source.
3.1 Creating a Root Node
Modify entry/SRC/main/js/default/pages/index/index. The HML, join the root node div:
<div class="container">
</div>
Copy the code
3.2 Creating a Style
Modify entry/SRC/main/js/default/pages/index/index. The CSS
.container {
flex-direction: column;
height: 480px;
width: 960px;
}
Copy the code
3.3 Adding a Title Bar
The title bar includes an exit button and a title, and the two controls are aligned horizontally
<div class="container"> <div class="header" onclick="exitApp"> <image class="back" src="common/ic_back.png"></image> <text class="title"> Air quality </text>Copy the code
Note that the common/ IC_back.png icon resource is imported first.
3.4 Adding a title bar style
Modify the entry/SRC/main/js/default/pages/detail/detail. CSS, add the following code, set the height of the components, such as margin, color attributes.
.header {
width: 960px;
height: 72px;
}
.back {
width: 36px;
height: 36px;
margin-left: 39px;
margin-top: 23px;
}
.title {
width: 296px;
height: 40px;
margin-top: 20px;
margin-left: 21px;
color: #e6e6e6;
}
Copy the code
3.5 Adding an exit event
Onclick =”exitApp” sets the div component’s click event. When the click event is triggered on the title bar, the function exitApp is executed in the index.js file with the following code:
exitApp() {
console.log('start exit');
app.terminate();
console.log('end exit');
}
Copy the code
The app.terminate() function implements the program exit function; To use this function, you need to import the app module and write the following code at the top of the index.js file:
import app from '@system.app'
Copy the code
In the Previewer window, you can preview the effects of the interface
3.6 Sliding Components
Swiper is required to swipe left and right on multiple screens for urban air quality information.
Add a child node swiper to the root node and modify index.hml
<swiper class="swiper" index="{{swiperPage}}" duration="500" onchange="swiperChange">
</swiper>
Copy the code
Add styles and modify index.css
.swiper {
height: 385px;
width: 960px;
}
Copy the code
Bind the swiperPage variable, swiperChange event, and modify index.js
Import router from'@system.router' import app from'@system. app' export default { {// Default is first page swiperPage: 0}, onInit (){}, exitApp(){console.log('start exit'); app.terminate(); console.log('end exit'); }, //swiper swiper callback event, save the index value of the current swiper, each swiper will save the index value in the swiperPage variable swiperChange (e) {this.swiperPage = e.index; }}Copy the code
Add two sub-components stack (absolute layout) in swiper. Add text, image, progress and other components to each stack component to display corresponding information.
<div class="container"> <div class="header" onclick="exitApp"> <image class="back" src="common/ic_back.png"></image> <text class="title"> Air quality </text> </div> <swiper class="swiper" index="{{swiperPage}}" duration="500" onchange="swiperChange"> <! <stack class="swiper"> <! < span style="color:{{textColor1}}; >{{airData[0].airQuality}}</text> <! - the name of the city -- -- > < text class = "location - the text" > {{airData [0]. Location}} < / text > <! <progress class="circleProgress" style="color:{{textColor1}}; background-Color:{{bgColor1}};" type="arc" onclick="openDetail" percent="{{percent1}}"> </progress> <! - clouds pictures - > < image class = "image" SRC = "{{src1}}" > < / image > <! --AQI value --> <text class="pm25-value">{{airData[0]. DetailData}}</text> <text class=" PM25-name ">AQI</text> <! --> <div class="detail"> <div class="text-wrapper"> <text class="gas-name"> CO </text> <text class="gas-value"> 100 </text> </div> <div class="text-wrapper"> <text class="gas-name"> NO2 </text> <text class="gas-value"> 90 </text> </div> <div class="text-wrapper"> <text class="gas-name"> PM10 </text> <text Class ="gas-value"> 120 </text> </div> <div class="text-wrapper"> <text class="gas-name"> PM2.5 </text> <text class="gas-value"> 40 </text> </div> <div class="text-wrapper"> <text class="gas-name"> SO2 </text> <text Class ="gas-value"> 150 </text> </div> <input class=" BTN "type="button" onclick="openDetail" value=" history "></input> </div> <! <div class="footer"> <text class="update-time"> </text> <text class="info-source"> tianqi.com </text> </div> </stack> <! <stack class="swiper"> <text class="airquality" style="color: {{textColor2}};" >{{airData[1].airQuality}}</text> <text class="location-text">{{airData[1].location}}</text> <progress class="circle-progress" style="color: {{textColor2}}; background-Color: {{bgColor2}};" type="arc" percent="{{percent2}}"></progress> <image class="image" src="{{src2}}"></image> <text class="aqi-value">{{airData[1].detailData}}</text> <text class="aqi"> AQI </text> <div class="detail"> <div class="text-wrapper"> <text class="gas-name"> CO </text> <text class="gas-value"> 10 </text> </div> <div class="text-wrapper"> <text class="gas-name"> NO2 </text> <text class="gas-value"> 50 </text> </div> <div class="text-wrapper"> <text class="gas-name"> PM10 </text> <text class="gas-value"> 60 </text> </div> <div Class ="text-wrapper"> <text class="gas-name"> PM2.5 </text> <text class="gas-value"> 40 </text> </div> <div class="text-wrapper"> <text class="gas-name"> SO2 </text> <text class="gas-value"> 150 </text> </div> <input class="btn" </input> </div> <div class="footer"> <text class="update-time"> Tianqi.com </text> </div> </stack> </swiper> </div>Copy the code
3.7 Page position indicator
Add page position indicator: Since swiper currently does not support indicator Settings, developers need to implement this effect themselves. Add a child div to the root node and style it accordingly; Then add two child divs to the div, set the border-radius of the two divs, and dynamically change the background color of the corresponding div in the swiper swipe event to achieve this effect.
Modify index. HML and add the following code after swiper:
<div class="images"> <div class="circle-div" style="background-color: {{iconcheckedColor}};" ></div> <div class="circle-div" style="background-color: {{iconUncheckedColor}}; margin-left: 36px;" ></div> </div>Copy the code
3.8 Added text styles
Modified index. The CSS
.aqi-value {
text-align: center;
font-size: 65px;
color: #f0ffff;
width: 156px;
height: 92px;
top: 134px;
left: 210px;
}
.aqi {
text-align: center;
color: #a2c4a2;
width: 156px;
height: 45px;
top: 90px;
left: 210px;
}
.airquality {
top: 222px;
text-align: center;
width: 156px;
height: 45px;
left: 210px;
}
.image {
top: 285px;
left: 274px;
width: 32px;
height: 32px;
}
.location-text {
text-align: center;
color: #ffffff;
width: 250px;
height: 52px;
font-size: 40px;
left: 380px;
top: 16px;
}
.container {
flex-direction: column;
height: 480px;
width: 960px;
}
.circle-progress {
center-x: 128px;
center-y: 128px;
radius: 128px;
startAngle: 198;
totalAngle: 320;
strokeWidth: 24px;
width: 256px;
height: 256px;
left: 160px;
top: 58px;
}
.detail {
width: 256px;
height: 265px;
left: 544px;
top: 58px;
flex-direction: column;
}
.text-wrapper {
width: 256px;
height: 35px;
margin-top: 6px;
}
.gas-name {
width: 128px;
height: 35px;
text-align: left;
}
.gas-value {
width: 128px;
height: 35px;
text-align: right;
}
.btn {
width: 180px;
height: 50px;
margin-top: 6px;
margin-left: 38px;
background-color: #1a1a1a;
color: #1085CE;
}
.footer {
top: 326px;
width: 960px;
height: 28px;
}
.header {
width: 960px;
height: 72px;
}
.back {
width: 36px;
height: 36px;
margin-left: 39px;
margin-top: 23px;
}
.title {
width: 296px;
height: 40px;
margin-top: 20px;
margin-left: 21px;
color: #e6e6e6;
}
.swiper {
height: 385px;
width: 960px;
}
.images {
width: 60px;
height: 15px;
margin-left: 450px;
}
.update-time {
width: 480px;
height: 28px;
font-size: 20px;
color: #A9A9A9;
text-align: right;
}
.info-source {
width: 450px;
height: 28px;
font-size: 20px;
color: #A9A9A9;
text-align: left;
margin-left: 24px;
}
.circle-div {
width: 12px;
height: 12px;
border-radius: 6px;
}
Copy the code
3.9 Implementing page Logic
Modify index.js to bind page data data. OnInit displays different fonts and images based on different values. Realize page skipping openDetail and pass the current page index to the detail page. After swiperChange is triggered to change the indicated position.
Import router from'@system.router' import app from'@system. app' export default { TextColor1: "# 00FF00 ", textColor2: "# 00FF00 ", bgColor1: "#669966", bgColor2: "#669966", // Default is the first page swiperPage: 0, percent1: 10, percent2: 90, iconUncheckedColor: '#262626', iconcheckedColor: '#ffffff', iconcheckedBR: '6px', src1: "common/cloud_green.png", src2: "common/cloud_green.png", airData: [ { location: "HangZhou", airQuality: "Good", detailData: 10 }, { location: "ShangHai", airQuality: "Unhealth", detailData: 90}]}, onInit () { If (this.airData[0].detailData > 100){this.src1 = 'common/cloud_red.png'; this.textColor1 = '#ff0000'; this.bgColor1 = '#9d7462'; } else if(50 < this.airData[0].detailData && this.airData[0].detailData <= 100){ this.src1 = 'common/cloud_yellow.png'; this.textColor1 = '#ecf19a'; this.bgColor1 = '#9d9d62'; } if(this.airData[1].detailData > 100){ this.src2 = 'common/cloud_red.png'; this.textColor2 = '#ff0000'; this.bgColor2 = '#9d7462'; } else if(50 < this.airData[1].detailData && this.airData[1].detailData <= 100){ this.src2 = 'common/cloud_yellow.png'; this.textColor2 = '#ecf19a'; this.bgColor2 = '#9d9d62'; } if(this.selectedCityIndex){ this.swiperPage = this.selectedCityIndex; if(this.swiperPage == 0){ this.iconcheckedColor = '#ffffff'; this.iconUncheckedColor = '#262626'; }else{ this.iconcheckedColor = '#262626'; this.iconUncheckedColor = '#ffffff'; OpenDetail () {router.replace({uri: 'pages/detail/detail', params: {selectedCityIndex:this.swiperPage} }); }, // Exit exitApp(){console.log('start exit'); app.terminate(); console.log('end exit'); }, //swiper swiper callback event, save the index value of the current swiper, each swiper will save the index value in the swiperPage variable swiperChange (e) {this.swiperPage = e.index; if(e.index == 0){ this.iconcheckedColor = '#ffffff'; this.iconUncheckedColor = '#262626'; }else{ this.iconcheckedColor = '#262626'; this.iconUncheckedColor = '#ffffff'; }}}Copy the code
The preview looks like this:
4. Develop the details page
The details page presents weekly air quality index values in the form of charts. This page is composed of two parts: title bar and chart bar; In the chart bar, we use multiple divs instead of the Chart component to implement the chart function, considering the display effect.
4.1 Adding a Title Bar
Modify the entry/SRC/main/js/default/pages/detail/detail. HML
<div class="container"> <div class="header" onclick="backMain"> <image class="back" src="common/ic_back.png"></image> <list class="chart-list"> </list> </div>Copy the code
4.2 Adding a chart bar
Add city location to list-item-title and chart to list-item-chart
<list class="chart-list">
<list-item class="list-item-title">
<text class="location">{{location}}</text>
</list-item>
<list-item class="list-item-chart">
</list-item>
</list>
Copy the code
4.3 Adding a Chart
<div class="chart-wrapper" style="margin-left: 128px;" > <text class="gas-name">CO</text> <div class="chart"> <div class="chart-item" style="height: 78px; background-color: #00ff00;" ></div> <div class="chart-item" style="height: 52px; background-color: #00ff00;" ></div> <div class="chart-item" style="height: 155px; background-color: #ff0000;" ></div> <div class="chart-item" style="height: 134px; background-color: #ff0000;" ></div> <div class="chart-item" style="height: 98px; background-color: #FF7500;" ></div> <div class="chart-item" style="height: 88px; background-color: #FF7500;" ></div> <div class="chart-item" style="height: 144px; background-color: #ff0000;" ></div> </div> <div class="white-line"></div> <div class="week"></div> </div>Copy the code
4.4 Adding Styles
.location {
text-align: center;
color: #ffffff;
width: 960px;
height: 52px;
font-size: 40px;
}
.container {
height: 480px;
width: 960px;
flex-direction: column;
}
.header {
width: 960px;
height: 72px;
}
.back {
width: 36px;
height: 36px;
margin-left: 39px;
margin-top: 23px;
}
.title {
width: 296px;
height: 40px;
margin-top: 20px;
margin-left: 21px;
color: #e6e6e6;
}
.chart-list {
width: 960px;
height: 408px;
}
.list-item-title {
width: 960px;
height: 52px;
}
.list-item-chart {
width: 960px;
height: 280px;
}
.chart-wrapper {
width: 308px;
height: 256px;
flex-direction: column;
}
.gas-name {
width: 308px;
height: 35px;
text-align: left;
}
.chart {
width: 308px;
height: 155px;
margin-top: 10px;
justify-content: flex-start;
align-items: flex-end;
}
.chart-item {
width: 24px;
margin-left: 18px;
border-radius: 3px;
}
.white-line {
width: 308px;
height: 2px;
background-color: #ffffff;
margin-top: 22px;
}
.week {
width: 308px;
height: 17px;
margin-top: 6px;
border-color: #ffffff;
border-radius: 2px;
margin-top: 6px;
}
.day {
width: 26px;
height: 17px;
font-size: 10px;
margin-left: 16px;
text-align: center;
}
Copy the code
4.5 Redirect the page
Where onclick=”backMain” is the event to return to the home page, and display different location data according to the page index passed. The code in detail.js is implemented as follows:
import router from '@system.router' export default { data: { location: }, onInit() {if (this.selectedCityIndex === 0) {this.location = 'hangzhou '; } else {this.location = 'Shanghai '; } }, backMain() { router.replace({ uri: 'pages/index/index', params: { selectedCityIndex: this.selectedCityIndex } }); }}Copy the code
5. Simulator debugging
Choose Tools->HVD Manager to open the emulator in the cloud
Register a Huawei developer account and authorize login
You’ll see the list of emulators, which adds a lot of gear to the beta’s Phone, TV and Wearable offerings.
Unfortunately, there is no simulator that can be used for smartVision equipment. At the present stage, we can only burn and debug the device. Generally speaking, the progress of “Fuhongmeng” is relatively fast, and we are looking forward to a wave of updates.
6. Compile and package
If you want to develop a mobile App, you need to apply for a certificate and sign the App. So that they can be released to the app market and allowed to run on real phones.
IPCamera apps do not support signed mode for the time being, so you need to publish the app as an unsigned app installation package.
Menu Build->Buildo APP(s)/Hap(s)->Build Release Hap(s) to generate Hap file.
The output file for the build/outputs/hap/release/smartVision/entry – release – smartVision – unsigned. Hap, renamed MyUiApp. Hap ease of installation.
7. Install using the SDcard
7.1 Copying installation packages and Tools
Place the IDE compiled unsigned app installation package and installation tool (Z: openHarmony \ Out \ my_HI3516DV300 \dev_tools) in the sdcard and insert the SDcard into the development board slot.
7.2 Disabling Signature Verification
Signature verification is required for application installation by default. Run the following command to disable signature verification.
./sdcard/dev_tools/bin/bm set -s disable
Copy the code
7.3 Installing Applications
./sdcard/dev_tools/bin/bm install -p /sdcard/MyUiApp.hap
Copy the code
8. Install using NFS
It is very inconvenient to plug and unplug SDcard every time, here we install an NFS server, so that the hongmengsystem can directly access the directory of Win10, the subsequent installation and debugging will be a lot more convenient.
8.1 Installing the NFS Server
To install a haneWIN NFS server, double-click nfs1169.exe in the end disk.
8.2 Setting Directory Parameters
Edit the output table file to define the transport directory
Exports example # C: / ftP-range 192.168.1.1 192.168.1.10 # C: / public-public-readonly # C: / tools-readonly 192.168.1.4 D: \ PycharmProjects \ aiLearn \ Harmony \ TFTP - public - name: NFSCopy the code
8.3 Restarting the Service
Right-click administrator privileges and restart all services for the configuration to take effect.
8.4 Configuring the Firewall
The firewall allows TCP and UDP traffic on ports 111, 1058, and 2049 based on inbound rules.
8.5 Mount directory is displayed
The IP address of the main computer is 192.168.1.57, the alias of the NFS service is NFS, and the corresponding directory is D:\PycharmProjects\aiLearn\Harmony\ TFTP
Mkdir NFS mount 192.168.1.57:/ NFS/NFS NFSCopy the code
Mount it to hung Meng’s newly created/NFS directory and we can copy the installation package and installation tools
8.6 Installing Applications
cd nfs
./dev_tools/bin/bm set -s disable
./dev_tools/bin/bm install -p MyUiApp.hap
Copy the code
So many fosters have been done in front, the subsequent development as long as copy hap installation package, a direct command installation can be very convenient.
To run the program
Once installed, click MyUiApp on your desktop to see what the interface looks like.
Js UI framework is more friendly to developers, small procedures or fast application development experience, should be relatively smooth.
However, HarmonyOS Device’s support library is so thin that @system.request and @system.fetch are both unavailable for network access, which would be easier to develop on a “rich” Device.
Data download
Next up
This issue mainly introduces the interface development under the JS framework,
In the next article we will try to familiarize ourselves with more of the device’s capabilities,
And get through the connection between the frame user mode and the driver kernel mode,
Stay tuned for…