鸿蒙5 汽车行业类实践
本文档汽车类HarmonyOS应用的架构设计实践,提供汽车类应用常见的汽车类资讯、购车、商城以及充电服务等功能,帮助开发者快速构建一款汽车类应用。Stage开发模型+声明式UI开发范式。按照应用设备形态,规划一个手机设备Entry类型HAP包。本实践性能优先,应用程序包大小可控,且无单独加载模块场景,业务模块包类型采用HAR包。应用布局说明实践应用框架代码运行图,开发者可以基于框架代码替换相关资源
📢 重磅福利!参与活动赢好礼,8月1日-12月31日等你来!
点击链接,加入班级: 华为开发者学堂
简介
本文档汽车类HarmonyOS应用的架构设计实践,提供汽车类应用常见的汽车类资讯、购车、商城以及充电服务等功能,帮助开发者快速构建一款汽车类应用。
Stage开发模型+声明式UI开发范式。
按照应用设备形态,规划一个手机设备Entry类型HAP包。
本实践性能优先,应用程序包大小可控,且无单独加载模块场景,业务模块包类型采用HAR包。
应用布局
说明
实践应用框架代码运行图,开发者可以基于框架代码替换相关资源文件,以保证应用良好的使用体验。
应用首页采用各类APP常见页面导航布局
首页底部导航包含“探索”,“购车”,“商城”,“服务”,“我的”五个功能入口,分别对应五个功能模块(模块划分详见本实践软件视图)。
探索页面上部是热门汽车介绍Banner轮播图,中间是汽车资讯列表瀑布流。
购车页面提供车辆详细信息以及预约试驾等能力。
首页->服务->最优站点,基于位置提供最佳充电位置服务。
应用架构设计
模块划分
根据行业应用的功能,按照高内聚,低耦合的原则,常见汽车类应用功能以及职责划分模块如下,开发者在实际设计过程中,可以根据模块的复杂程度实际情况再进一步细分:
表1 模块划分
模块名称
功能点
探索
行业资讯
购车
产品详情,购车指南
商城
商品搜索,商品详情,商品购买
服务
充电服务,服务门店
我的
我的车辆,我的订单,我的积分,我的家充
通用
资源,国际化,导航
软件视图设计
应用分层模块类型划分指导,参见分层模块化实践。
产品定制层:本实践只涉及手机端,设计为一个HAP,包含页面框架、导航、手机独有资源等。
基础特性层:“探索”、“购车” 等功能模块设计为HAR包,被上层引用。
公共能力层:本实践将“应用路由”、“基础工具”、“DFX”等基础公共模块打包为Har包被上层业务组件引用,其中路由管理划分到公共组件。
逻辑视图设计
根据本应用功能的模块以及依赖,分解对基础服务以及三方的依赖,逻辑视图如下:
逻辑视图
公共关键技术方案
介绍行业应用通用的公共关键技术,详见 公共关键技术方案。
行业关键技术方案
扫码充电技术方案
功能设计
扫码充电是汽车类行业的基础能力。应用充电服务,提供最优站点列表以及路径规划。常见页面路径:首页->服务->扫码充电,功能入口如下图所示:
图3 扫码充电功能入口
设计
使用Scan Kit(统一扫码服务)实现扫码能力,本示例代码使用默认界面扫码能力。
表2 方案对比参考
能力
限制条件
scanBarcode (默认界面扫码)
系统体验一致的扫码体验,系统预授权,暂不支持悬浮屏、分屏场景;相册扫码只支持单码识别。
customScan (自定义界面扫码)
适用对扫码有定制需求的开发,需要授权使用相机权限;需要开发者自行实现扫码的人机交互界面。
代码参考
代码详情参见扫码充电代码实现。
最优站点技术方案
功能设计
最优站点提供最优站点列表以及路径规划。常见页面路径:首页->服务->最优站点,功能页面如下图所示:
图4 最优充电站点功能页面
点击放大
方案设计
使用HarmonyOS Map Kit(地图服务)能力,应用无需集成SDK,不影响包大小,开发者不用考虑SDK升级。
使用Map Kit地图服务,首先要在AppGallery Connect配置使用相关API,参考指导配置AppGallery Connect。
代码参考
申请ohos.permission.LOCATION和ohos.permission.APPROXIMATELY_LOCATION权限,您需要在module.json5配置文件中声明所需要的权限,具体可参考声明权限。
代码详情参见最优站点代码实现。
行业创新设计
说明
结合鸿蒙生态,针对行业的创新场景设计,开发者可以参考行业创新设计方案,实现创新场景代码。
导航体验提升设计
场景说明
最优站点页面,点击站点导航图标拉起导航类应用,导航应用单独一个界面。通用方案:使用隐式want能力,启动设备内地图应用,多个应用时会弹框显示多个应用图标,用户选择。如果本机没有安装地图导航应用,会有类似“请安装地图应用”提示,用户需要先下载导航应用,操作繁琐,体验差。
创新设计
利用元服务免安装能力,导航元服务(相应元服务已上架)内嵌展示在应用内。在用户没有安装导航应用情况下,也能正常打开地图导航功能,实现导航能力。
图5 元服务内嵌效果示意图
点击放大
应用框架代码
说明
本篇代码非应用的全量代码,只包括应用的部分框架代码。
框架代码中登录验证,只是UI能力,手机号输入满11位,任意密码可登录,开发者自行补齐相关鉴权认证。
代码运行环境
软件要求
DevEco Studio版本:DevEco Studio 5.0.1 Release及以上。
HarmonyOS SDK版本:HarmonyOS 5.0.1 Release SDK及以上。
硬件要求
设备类型:华为手机。
HarmonyOS系统:HarmonyOS 5.0.1 Release及以上。
环境搭建
安装DevEco Studio,详情请参考使用指南。
历史工程迁移
开发者使用HarmonyOS NEXT Developer Beta1(5.0.3.300)以上版本导入代码,使用一体化的历史工程迁移能力,帮助开发者快速完成工程转换。
代码结构解读
本篇代码非应用的全量代码,只包括脱敏后的应用框架代码,开发者可以通过链接下载全量的框架代码。
整个框架代码结构分为5个HAR包,所有的HAR在同一个IDE工程中维护开发。
图6 Entry集成的HAR列表
5个HAR分别为buyingCar,explore,mine,service,shoppingMall。
├── common/src/main/ets // 公共模块
│ ├── components
│ │ ├── NavItem.ets // nav组件
│ │ ├── PageHeaderComp.ets // 二级页面头部组件
│ │ └── ShopItem.ets // shop组件
│ ├── constants
│ │ ├── CommonConstants.ets // 公共样式
│ │ ├── NavConstants.ets // nav样式
│ │ └── TabConstants.ets // tab样式
│ ├── model
│ │ ├── BuyingCarModel.ets // 购车数据模型
│ │ ├── CommodityModel.ets // 商城数据模型
│ │ ├── ExploreModel.ets // 探索数据模型
│ │ ├── LazyDataSource.ets // 懒加载数据
│ │ ├── NavModel.ets // nav数据模型
│ │ └── ShopModel.ets // shop数据模型
│ └── utils
│ ├── LoggerUtil.ets
│ ├── PermissionsUtil.ets // 权限管理工具类
│ └── PreferencesUtil.ets // 数据存储工具类
├── entry/src/main/ets // 主页面
│ ├── constants
│ │ └── TabConstants.ets // tab样式
│ ├── entryability
│ │ └── EntryAbility.ets // 程序入口
│ └── pages
│ ├── LoginPage.ets // 登录页
│ ├── NavigationPage.ets // Navigation根页面
│ ├── PrivacyPolicyPage.ets // 隐私政策页面
│ ├── SplashScreenPage.ets // 闪屏页
│ ├── SplashScreenPage2.ets // 闪屏页2
│ └── TabPage.ets // tab页
├── features
│ ├── buyingcar/src/main/ets // 购车
│ │ ├── components
│ │ │ ├── LearnMoreItemComp.ets // 了解更多item组件
│ │ │ ├── MarqueeImageComp.ets // 走马灯图片
│ │ │ ├── SwiperItemComp.ets // 购车swiperItem组件
│ │ │ └── VehicleModelActivities.ets // 车型item组件
│ │ └── pages
│ │ ├── BuyingCarDetailPage.ets
│ │ └── BuyingCarPage.ets // 购车tab页
│ ├── explore/src/main/ets // 探索
│ │ ├── components
│ │ │ ├── ActivityComp.ets // 活动swiper页
│ │ │ ├── ActivityItemComp.ets // 活动item组件
│ │ │ ├── RealTimeInfoComp.ets // 咨询swiper页
│ │ │ └── RecommendationComp.ets // 推荐swiper页
│ │ ├── constants
│ │ │ └── RecommendationConstants.ets // 探索tab页
│ │ └── pages
│ │ └── ExplorePage.ets
│ ├── mine/src/main/ets // 我的
│ │ ├── components
│ │ │ └── MajorList.ets // 单个组件
│ │ ├── constants
│ │ │ ├── HeaderConstants.ets // 头部样式
│ │ │ └── MajorConstants.ets // major样式
│ │ ├── model
│ │ │ └── MajorModel.ets // major模型
│ │ └── pages
│ │ ├── MinePage.ets // 我的tab页
│ │ └── SettingsPage.ets // 设置页面
│ ├── service/src/main/ets // 服务
│ │ ├── components
│ │ │ └── SheetTransition.ets // sheet模态框
│ │ ├── constants
│ │ │ └── ServiceConstants.ets // 服务样式
│ │ ├── model
│ │ │ └── StationModel.ets // station模型
│ │ ├── pages
│ │ │ ├── MyCharge.ets // 我的充电页
│ │ │ ├── OptimalStation.ets // 最优站点页
│ │ │ └── ServicePage.ets // 服务tab页
│ └── shoppingMall/src/main/ets // 商城
│ ├── components
│ │ └── CommodityItemComp.ets // 商城列表item组件
│ ├── constants
│ │ └── ShoppingMallConstants.ets // 商城样式
│ └── pages
│ ├── CommodityDetailPage.ets // 商城详情
│ └── ShoppingMallPage.ets // 商城tab页
└── entry/src/main/resources // 资源文件目录
扫码充电代码实现
使用Scan Kit(统一扫码服务)实现扫码能力。本示例采用默认的扫码能力,调用scanBarcode (默认界面扫码)接口能力,具备相机预授权,集成简单,适用于通用扫码场景。
// features\service\src\main\ets\pages\ServicePage.ets
Row() {
ForEach(this.mapShopList, (item: shopInfo, index: number) => {
Row() {
ShopItem({ itemData: item })
}.onClick(() => {
if (item.title === '扫码充电') {
// 定义扫码参数options
let options: scanBarcode.ScanOptions = {
scanTypes: [scanCore.ScanType.ALL], // 设置扫码类型,默认扫码ALL(全部码类型)
enableMultiMode: true, // 是否开启多码识别,默认false。
enableAlbum: true // 是否开启相册,默认true, 此参数只控制默认界面扫码能力中的相册扫码且只支持单码识别。
};
try {
scanBarcode.startScanForResult(getContext(this), options).then((result: scanBarcode.ScanResult) => {
// 收到扫码结果后返回
Logger.info('Promise scan result: %{public}s', JSON.stringify(result));
// 处理扫码结果
this.showScanResult(result);
}).catch((error: BusinessError) => {
Logger.error('Promise error: %{public}s', JSON.stringify(error));
});
} catch (error) {
Logger.error('failReason: %{public}s', JSON.stringify(error));
}
}
if (item.title === '最优站点') {
this.pageInfos.pushPath({ name: 'OptimalStation' });
} else if (item.title === '我的充电') {
this.pageInfos.pushPath({ name: 'MyCharge' });
}
})
if (index !== this.mapShopList.length - 1) {
Line().LineStyle();
}
})
}
.width(CommonConstants.COLUMN_WIDTH)
.justifyContent(FlexAlign.SpaceEvenly)
开发者也可调用customScan (自定义界面扫码)接口能力,自定义实现扫码界面,需要申请相机权限,需要在配置文件module.json5里添加:ohos.permission.CAMERA,参见应用权限列表。适用于对扫码界面有个性化定制的场景。
最优站点代码实现
使用HarmonyOS Map Kit(地图服务)能力。
配置相关权限entry\src\main\module.json5
"
requestPermissions": [
{
"name": "ohos.permission.LOCATION",
"reason": "$string:EntryAbility_desc",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
},
{
"name": "ohos.permission.APPROXIMATELY_LOCATION",
"reason": "$string:EntryAbility_desc",
"usedScene": {
"abilities": [
"EntryAbility"
],
"when": "always"
}
}
]
使用MapComponent地图组件在页面中放置地图。MapComponentController是地图组件的主要功能入口类,用来操作地图,与地图有关的所有方法从此处接入。它所承载的工作包括:地图类型切换(如标准地图、空地图)、改变地图状态(中心点坐标和缩放级别)、添加点标记(Marker)、绘制几何图形(MapPolyline、MapPolygon、MapCircle)、各类事件监听等。
// features\service\src\main\ets\pages\OptimalStation.ets
@Entry
@Component
export struct OptimalStation {
@StorageProp('avoidArea') topHeight: number = 0;
private mapOption?: mapCommon.MapOptions;
@State addressName: string = '';
private callback?: AsyncCallback<map.MapComponentController>;
private mapController?: map.MapComponentController;
// 地图初始化经纬度,可自定义。
private latLng: mapCommon.LatLng = {
latitude: 31.97413747571286,
longitude: 118.77314161376894
}
@State addressString: string = '';
@Consume('pageInfos') pageInfos: NavPathStack;
build() {
NavDestination(){
Stack({ alignContent: Alignment.Bottom }) {
MapComponent({ mapOptions: this.mapOption, mapCallback: this.callback }).width('100%').height('100%');
// ...
Row() {
// 半模态框
SheetTransition({
StationList: Station.getStationList(),
addressName: this.addressName
})
}.margin({ bottom: 220 })
}
}
.hideTitleBar(true)
.onReady(()=>{
// 地图初始化参数,设置地图中心点坐标及层级
this.mapOption = {
position: {
target: this.latLng,
zoom: 14
},
zoomControlsEnabled: false,
myLocationControlsEnabled: true
};
// 地图初始化的回调
this.callback = async (err, mapController) => {
if (!err) {
// 获取地图的控制器类,用来操作地图
this.mapController = mapController;
// 启用我的位置图层
this.mapController?.setMyLocationEnabled(true);
this.mapController.on("mapLoad", () => {
});
// 监听“我的位置”按钮点击事件
this.mapController.on("myLocationButtonClick", () => {
this.getMyLocation();
});
// 初始化我的位置
this.getMyLocation();
}
};
})
}
}
由于框架示例代码访问API受限,目前最优站点列表数据来源是本地数据,数据文件位置:features>service src/main/ets/model/StationModel.ets
开发者可以基于此示例代码,使用地点搜索能力,查找相关POI,根据响应替换本地数据,在此基础上,根据响应使用地图绘制能力,在地图上设置图标,效果更佳。
代码下载链接
汽车类示例代码.zip
更多推荐


所有评论(0)