#2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区-51CTO.COM

#2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇 原创 精华

bluishfish
发布于 2021-1-19 15:01
浏览
8收藏

前言

上一篇,我们在鸿蒙上写了一个HDF驱动并操作了一下LED硬件,这一篇我们来尝试一下构建一个有简单界面的App,体验一下鸿蒙的前端开发流程。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

环境准备

1. 安装DevEco Studio

解压相应的压缩包(文末附下载链接),这里以win10为例,双击`deveco-studio-2.0.12.201.exe`

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区指定安装目录

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区设置可选快捷方式和环境变量

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区一路下一步即可。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区同意用户协议后,就能正常启动了。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

2. 更新sdk

在菜单 `Setting->HarmonyOS SDK->SDK Platforms`中,选择`Js`和`Java`,安装新版的`SDK`。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区同样在`SDK Tools`中,选中新版的`Previewer`

 

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区点击Apply更新

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

新建项目

点击菜单`File->New Project...`,选择智慧屏`Smart Vision`,创建一个空模板应用。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

填入项目名称`MyUiAPP`,点击完成就能创建一个工程了。

 

遇到 `gradle`下载太慢或版本差异的,可以直接在以下网址用工具下载 

https://services.gradle.org/distributions/

 

目录结构

我们先分析一下目录结构,做`Android`开发的会倍感亲切。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

1. APP

`HarmonyOS`的应用软件包以`APP Pack(Application Package)`形式发布,它是由一个或多个`HAP(HarmonyOS Ability Package)`以及描述每个`HAP`属性的`pack.info`组成。`HAP`是`Ability`的部署包,`HarmonyOS`应用代码围绕`Ability`组件展开。

一个`HAP`是由代码、资源、第三方库及应用配置文件组成的模块包,可分为`entry`和`feature`两种模块类型。

- **entry**:应用的主模块。一个APP中,对于同一设备类型必须有且只有一个`entry`类型的`HAP`,可独立安装运行。
- **feature**:应用的动态特性模块。一个`APP`可以包含一个或多个`feature`类型的`HAP`,也可以不含。只有包含`Ability`的`HAP`才能够独立运行。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

2. Ability

Ability是应用所具备的能力的抽象,一个应用可以包含一个或多个`Ability`。`Ability`分为两种类型:`FA(Feature Ability)`和`PA(Particle Ability)`。`FA/PA`是应用的基本组成单元,能够实现特定的业务功能。`FA`有`UI`界面,而`PA`无`UI`界面。

3. 资源文件

应用的资源文件(字符串、图片、音频等)统一存放于`resources`目录下,便于开发者使用和维护。`resources`目录包括两大类目录,一类为`base`目录与限定词目录,另一类为`rawfile`目录。

4. 配置文件

配置文件` (config.json) `是应用的`Ability`信息,用于声明应用的`Ability`,以及应用所需权限等信息。

- 应用的全局配置信息,包含应用的包名、生产厂商、版本号等基本信息。
- 应用在具体设备上的配置信息,包含应用的备份恢复、网络安全等能力。
- `HAP`包的配置信息,包含每个`Ability`必须定义的基本属性(如包名、类名、类型以及`Ability`提供的能力),以及应用访问系统或其他应用受保护部分所需的权限等。

5. JS UI 框架

`JS UI`框架是一种跨设备的高性能`UI`开发框架,支持声明式编程和跨设备多态`UI`。

- 声明式编程

  `JS UI`框架采用类`HTML`和`CSS`声明式编程语言作为页面布局和页面样式的开发语言,页面业务逻辑则支持`ECMAScript`规范的`JavaScript`语言。`JS UI`框架提供的声明式编程,可以让开发者避免编写`UI`状态切换的代码,视图配置信息更加直观。

- 跨设备

  开发框架架构上支持`UI`跨设备显示能力,运行时自动映射到不同设备类型,开发者无感知,降低开发者多设备适配成本。

- 高性能

  开发框架包含了许多核心的控件,如列表、图片和各类容器组件等,针对声明式语法进行了渲染流程的优化。

`JS UI`框架包括应用层`(Application)`、前端框架层`(Framework)`、引擎层`(Engine)`和平台适配层`(Porting Layer)`。

 

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

# 空气质量监测 UI

## 1. 创建首页面

空气质量监测App包含两个界面`(Page)`,工程创建完成后会生成一个名为`index`的`Page`,可以作为首页。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

## 2. 创建详情页

在`pages`目录按右键,弹出的菜单中选择`New->JS Page`。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区输入页面名称`detail`,

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区详情页创建完成后应用工程目录如下图所示,每个`Page`包括三个文件:布局文件`hml`、样式文件`css`、业务逻辑代码`js`。

 

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

## 3. 开发首页

应用首页主要展示城市的空气质量概况。首页总共有两屏(可以根据需求设置多屏),每屏显示一个城市的空气质量信息:主要包括AQI指数、城市名称、污染物指数、更新时间和信息来源等数据。

### 3.1 创建根节点

修改`entry/src/main/js/default/pages/index/index.hml`,加入根节点`div`:

<div class="container">
</div>

### 3.2 创建样式

修改`entry/src/main/js/default/pages/index/index.css`

.container {    
    flex-direction: column;
    height: 480px;
    width: 960px;
}

3.3 添加标题栏
标题栏包括一个退出按钮和一个标题,两个控件是横向排列

<div class="container">    
    <div class="header" onclick="exitApp">        
        <image class="back" src="common/ic_back.png"></image>        
        <text class="title">            
            空气质量        
         </text>    
    </div>
</div>

注意,这里要先导入common/ic_back.png图标资源。

 

3.4 添加标题栏样式
修改entry/src/main/js/default/pages/detail/detail.css,添加以下代码,设置组件的高度、边距、颜色等属性。

.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;
}

 

### 3.5 添加退出事件

`onclick="exitApp"` 设置了`div`组件的`click`事件,当在标题栏上触发点击事件时,就会执行函数`exitApp`,该函数位于`index.js`文件中,代码如下:

exitApp() {  
    console.log('start exit');  
    app.terminate();  
    console.log('end exit');
}

`app.terminate()`函数实现了程序退出功能;在使用该函数前,需要引入`app`模块,在`index.js`文件的最上方写如下代码:

 

import app from '@system.app'

 

在 Previewer 窗口中,可以预览界面效果

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

### 3.6 滑动组件

实现城市空气质量信息的多屏左右滑动,需要使用`“swiper”`组件。

在根节点中添加一个子节点`swiper`, 修改`index.hml`

<swiper class="swiper" index="{{swiperPage}}" duration="500" onchange="swiperChange">

</swiper>

添加样式,修改`index.css`

.swiper {
    height: 385px;
    width: 960px;
}

绑定`swiperPage`变量,`swiperChange`事件,修改`index.js`

//引入router模块,用户页面跳转
import router from'@system.router'
import app from '@system.app'
 
export default {
    //定义参数
    data: {
      //默认是第一页
      swiperPage: 0 
    },
    onInit () {
    },
    exitApp(){  
        console.log('start exit');  
        app.terminate();  
        console.log('end exit');
    },
    //swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中
    swiperChange (e) {
        this.swiperPage = e.index;
    }
}

 

在`swiper`中添加两个子组件`stack`(绝对布局),每个`stack`组件内分别添加`text、image、progress`等组件来显示对应的信息。

 

<div class="container">
    <div class="header" onclick="exitApp">
        <image class="back" src="common/ic_back.png"></image>
        <text class="title">
            空气质量
        </text>
    </div>
    <swiper class="swiper" index="{{swiperPage}}" duration="500" onchange="swiperChange">
        <!--第一屏-->
        <stack class="swiper">
            <!--空气质量-->
            <text class="airquality" style="color:{{textColor1}};">{{airData[0].airQuality}}</text>
            <!--城市名称-->
            <text class="location-text">{{airData[0].location}}</text>
            <!--进度条-->
            <progress
                class="circleProgress"
                style="color:{{textColor1}};background-Color:{{bgColor1}};"
                type="arc"
                onclick="openDetail"
                percent="{{percent1}}">
            </progress>
            <!--云朵图片-->
            <image class="image" src="{{src1}}"></image>
            <!--AQI数值-->
            <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="历史记录"></input>
            </div>
            <!--更新时间和网站等信息-->
            <div class="footer">
                <text class="update-time">
                    更新时间: 10:38
                </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" type="button" onclick="openDetail" value="历史记录"></input>
            </div>
            <div class="footer">
                <text class="update-time">
                    更新时间: 10:38
                </text>
                <text class="info-source">
                    信息来源: tianqi.com
                </text>
            </div>
        </stack>
    </swiper>
</div>

### 3.7 页面位置指示器

添加页面位置指示器:由于当前`swiper`不支持设置`indicator`,需要开发者自己来实现该效果。在根节点中添加一个子组件`div`,并设置相应样式;然后在该`div`中添加两个子组件`div`,设置两个`div`的`border-radius`,并在`swiper`滑动事件中动态改变对应`div`的背景色来实现该效果。

修改`index.hml`,在`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>

 

### 3.8 新增文字样式

修改 `index.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;
}

 

### 3.9 实现页面逻辑

修改`index.js`,绑定页面数据`data`。初始化时,根据不同的数值显示不同的字体和图片`onInit`。实现页面跳转`openDetail`,将当前页面索引传递给`detail`页面。滑动触发后`swiperChange`改变指示位置。

//引入router模块,用户页面跳转
import router from'@system.router'
import app from '@system.app'

export default {
//定义参数
    data: {
        //页面绑定数据
        textColor1: "#00ff00",
        textColor2: "#00ff00",
        bgColor1: "#669966",
        bgColor2: "#669966",
        //默认是第一页
        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}
        });
    },
    //退出应用
    exitApp(){
        console.log('start exit');
        app.terminate();
        console.log('end exit');
    },
    //swiper滑动回调事件,保存当前swiper的index值,每次滑动都会将index值保存在swiperPage变量中
    swiperChange (e) {
        this.swiperPage = e.index;
        if(e.index == 0){
            this.iconcheckedColor = '#ffffff';
            this.iconUncheckedColor = '#262626';
        }else{
            this.iconcheckedColor = '#262626';
            this.iconUncheckedColor = '#ffffff';
        }
    }
}

预览效果如下:

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

## 4. 开发详情页

详情页以图表的形式展示一周内空气质量指标值。本页面由两部分组成:标题栏和图表栏;在图表栏,考虑显示效果,我们使用多个`div`替代`chart`组件来实现图表功能。

### 4.1 添加标题栏

修改 `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>
        <text class="title">
            历史记录
        </text>
    </div>
    <list class="chart-list">
    </list>
</div>

### 4.2 添加图表栏

添加城市位置到`list-item-title`,图表到`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>

4.3 添加图表

<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>

4.4 添加样式

.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;
}

 

### 4.5 实现页面跳转

其中`onclick="backMain"`为返回主页事件,根据传递的页面索引,显示不同的位置数据,`detail.js`中的代码实现如下:

 

import router from '@system.router'

export default {
    data: {
        location: ''
    },
    onInit() {
        if (this.selectedCityIndex === 0) {
            this.location = '杭州';
        } else {
            this.location = '上海';
        }
    },
    backMain() {
        router.replace({
            uri: 'pages/index/index',
            params: {
                selectedCityIndex: this.selectedCityIndex
            }
        });
    }
}

 

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区5. 模拟器调试
菜单Tools->HVD Manager,可以打开云端的模拟器

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区注册华为开发者账号,授权登录后

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区就能看到模拟器列表了,相比`beta`版只有`Phone`、`TV`和`Wearable`三种,增加了不少的设备。

 

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

可惜还没有可用于`smartVision`设备的模拟器,现阶段我们还只能烧录到设备中调试,总体上"富鸿蒙"的进度比较快,期待一波更新。

 

## 6. 编译打包

若开发手机端的`App`,则需要申请证书,对应用程序进行签名。这样才能发布到应用市场,才被允许安装到真机上运行。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

`IPCamera`应用**暂时不支持签名模式**,所以需要将应用发布为未签名的应用安装包。

菜单`Build->Buildo APP(s)/Hap(s)->Build Release Hap(s)`,生成`Hap`文件。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区输出文件为 `build/outputs/hap/release/smartVision/entry-release-smartVision-unsigned.hap`,改名为`MyUiApp.hap`便于安装。

 

## 7. 通过sdcard安装

### 7.1 复制安装包和工具

将IDE编译的未签名应用安装包和安装工具(`Z:\openharmony\out\my_hi3516dv300\dev_tools`)放在`sdcard`中,将`sdcard`插入开发板卡槽。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

### 7.2 禁用签名校验

应用安装默认要校验签名,需要执行以下命令,关闭签名校验。

./sdcard/dev_tools/bin/bm set -s disable

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区7.3 安装应用

./sdcard/dev_tools/bin/bm install -p /sdcard/MyUiApp.hap 

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

## 8. 通过NFS安装

每次插拔`sdcard`还是蛮不方便的,这里我们安装一个`NFS`服务器,让鸿蒙系统能直接访问`Win10`的目录,后续安装调试就会方便很多。

### 8.1 安装NFS服务器

我们先安装一个`haneWIN NFS服务器`, 双击文末网盘里的`nfs1169.exe`,一路下一步即可。

 

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区8.2 配置目录参数
编辑输出表文件,定义传输目录

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

# 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:nfs

 

### 8.3 重启服务

右键管理员权限,重启所有服务,让配置生效。

 

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

### 8.4 设置防火墙

防火墙设置`111、1058、2049`这些端口的`TCP`和`UDP`,入站规则放行。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

### 8.5 鸿蒙上挂载目录

主电脑的`ip`地址为`192.168.1.57`,`NFS`服务的别名为`nfs`,对应的目录为`D:\PycharmProjects\aiLearn\Harmony\tftp`

mkdir nfs
mount 192.168.1.57:/nfs /nfs nfs

挂载到鸿蒙的刚新建的 `/nfs`目录下,我们可以复制安装包和安装工具

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区8.6 安装应用

cd nfs
./dev_tools/bin/bm set -s disable
./dev_tools/bin/bm install -p MyUiApp.hap

前面做了这么多的铺垫,后续开发只要复制`hap`安装包,直接一条命令安装即可,非常方便。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

# 运行程序

安装完成后,点击桌面上的`MyUiApp`就能看见界面效果了。

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

 

`Js UI框架`对开发者还是比较友好的,有小程序或快应用的开发经验,上手应该都比较顺滑。

不过`HarmonyOS Device`的支持库精简的非常严重,例如网络访问的`@system.request`和`@system.fetch`都不可用,这些功能在“富鸿蒙”的设备上开发就会比较方便。

 

# 资料下载

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

# 下一篇预告

>  本期主要介绍了一下JS框架下的界面开发,
>  下一篇我们将尝试熟悉更多的设备能力,
>  并打通从框架用户态到驱动内核态之间的联系,
>  敬请期待...

 

 #2020征文-开发板# 用鸿蒙开发AI应用(六)UI篇-鸿蒙开发者社区

 

©著作权归作者所有,如需转载,请注明出处,否则将追究法律责任
已于2021-1-19 15:01:44修改
6
收藏 8
回复
举报
4条回复
按时间正序
/
按时间倒序
开发者训练营官方
开发者训练营官方

读大佬的帖子有点神清气爽的感觉!!

1
回复
2021-1-19 15:06:31
雪糕酱
雪糕酱

感谢分享~

回复
2021-1-19 15:09:30
啧啧啧GKD
啧啧啧GKD

看下拉条就知道你不简单

回复
2021-1-19 15:20:00
鲜橙加冰
鲜橙加冰

哎哟,不错哦。

回复
2021-1-19 15:35:42
回复
    相关推荐