HarmonyOS 鸿蒙Next中使用高德天气 SDK 实现实时天气与预报查询
HarmonyOS 鸿蒙Next中使用高德天气 SDK 实现实时天气与预报查询 在开发旅行类应用时,需要为用户提供目的地天气信息:
- 查询指定城市的实时天气(温度、天气现象、风向、风力、湿度)
- 查询城市的未来几天天气预报(白天/夜间温度、天气)
- 根据天气现象显示对应的天气图标
- 异步查询,不阻塞 UI 线程
3 回复
1. 配置高德地图 SDK
在 oh-package.json5 中添加依赖:
{
"dependencies": {
"@amap/amap_lbs_search": "^1.0.0"
}
}
注意: 使用高德天气 API 需要在高德开放平台申请 Key,并在项目中正确配置。
2. 创建天气服务类
// services/WeatherService.ets
import {
WeatherSearch,
WeatherSearchQuery,
LocalWeatherLive,
LocalWeatherLiveResult,
LocalWeatherForecast,
LocalWeatherForecastResult,
OnWeatherSearchListener,
AMapException
} from '@amap/amap_lbs_search'
import { common } from '@kit.AbilityKit'
/**
* 天气服务类
* 封装高德 SDK 天气查询 API
*/
export class WeatherService {
private context: common.UIAbilityContext
constructor(context: common.UIAbilityContext) {
this.context = context
}
}
3. 实现实时天气查询
/**
* 查询实时天气
* @param cityName 城市名称(支持城市名称或 adcode,如 "北京" 或 "110000")
* @returns 实时天气数据
*/
async searchLiveWeather(cityName: string): Promise<LocalWeatherLive | null> {
return new Promise<LocalWeatherLive | null>((resolve) => {
try {
// 创建天气查询监听器
const weatherSearchListener: OnWeatherSearchListener = {
onWeatherLiveSearched: (
weatherLiveResult: LocalWeatherLiveResult | undefined,
errorCode: number
): void => {
if (errorCode === AMapException.CODE_AMAP_SUCCESS) {
if (weatherLiveResult && weatherLiveResult.getLiveResult()) {
console.info(`[WeatherService] ✅ 实时天气查询成功: ${cityName}`)
resolve(weatherLiveResult.getLiveResult())
} else {
console.warn(`[WeatherService] ⚠️ 实时天气查询无数据: ${cityName}`)
resolve(null)
}
} else {
console.error(`[WeatherService] ❌ 实时天气查询失败,错误码: ${errorCode}`)
resolve(null)
}
},
onWeatherForecastSearched: (
weatherForecastResult: LocalWeatherForecastResult | undefined,
errorCode: number
): void => {
// 不处理预报天气回调
}
}
// 创建查询参数
// WEATHER_TYPE_LIVE = 1:实时天气
const query = new WeatherSearchQuery(cityName, WeatherSearchQuery.WEATHER_TYPE_LIVE)
// 创建天气搜索对象
const weatherSearch = new WeatherSearch(this.context)
weatherSearch.setOnWeatherSearchListener(weatherSearchListener)
weatherSearch.setQuery(query)
// 异步搜索
weatherSearch.searchWeatherAsyn()
console.info(`[WeatherService] 🔍 开始查询实时天气: ${cityName}`)
} catch (error) {
console.error(`[WeatherService] ❌ 实时天气查询异常:`, error)
resolve(null)
}
})
}
4. 实现天气预报查询
/**
* 查询预报天气(未来几天)
* @param cityName 城市名称(支持城市名称或 adcode)
* @returns 预报天气数据
*/
async searchForecastWeather(cityName: string): Promise<LocalWeatherForecast | null> {
return new Promise<LocalWeatherForecast | null>((resolve) => {
try {
// 创建天气查询监听器
const weatherSearchListener: OnWeatherSearchListener = {
onWeatherLiveSearched: (
weatherLiveResult: LocalWeatherLiveResult | undefined,
errorCode: number
): void => {
// 不处理实时天气回调
},
onWeatherForecastSearched: (
weatherForecastResult: LocalWeatherForecastResult | undefined,
errorCode: number
): void => {
if (errorCode === AMapException.CODE_AMAP_SUCCESS) {
if (weatherForecastResult &&
weatherForecastResult.getForecastResult() &&
weatherForecastResult.getForecastResult().getWeatherForecast() &&
weatherForecastResult.getForecastResult().getWeatherForecast().length > 0) {
console.info(`[WeatherService] ✅ 预报天气查询成功: ${cityName}`)
resolve(weatherForecastResult.getForecastResult())
} else {
console.warn(`[WeatherService] ⚠️ 预报天气查询无数据: ${cityName}`)
resolve(null)
}
} else {
console.error(`[WeatherService] ❌ 预报天气查询失败,错误码: ${errorCode}`)
resolve(null)
}
}
}
// 创建查询参数
// WEATHER_TYPE_FORECAST = 2:预报天气
const query = new WeatherSearchQuery(cityName, WeatherSearchQuery.WEATHER_TYPE_FORECAST)
// 创建天气搜索对象
const weatherSearch = new WeatherSearch(this.context)
weatherSearch.setOnWeatherSearchListener(weatherSearchListener)
weatherSearch.setQuery(query)
// 异步搜索
weatherSearch.searchWeatherAsyn()
console.info(`[WeatherService] 🔍 开始查询预报天气: ${cityName}`)
} catch (error) {
console.error(`[WeatherService] ❌ 预报天气查询异常:`, error)
resolve(null)
}
})
}
5. 创建天气图标映射工具
// models/WeatherModels.ets
/**
* 天气图标映射类
* 将天气现象字符串映射为对应的图标资源
*/
export class WeatherIconMapper {
/**
* 根据天气现象返回对应的图标路径
* @param weather 天气现象字符串(如"晴"、"多云"、"小雨")
* @returns SVG 图标路径
*/
static getIconPath(weather: string): string {
const iconMap: Record<string, string> = {
// 晴天类
'晴': 'icons/weather/sunny.svg',
'少云': 'icons/weather/sunny.svg',
'热': 'icons/weather/sunny.svg',
// 多云类
'晴间多云': 'icons/weather/cloudy.svg',
'多云': 'icons/weather/cloudy.svg',
'有风': 'icons/weather/cloudy.svg',
'微风': 'icons/weather/cloudy.svg',
// 阴天类
'阴': 'icons/weather/overcast.svg',
'冷': 'icons/weather/overcast.svg',
// 雨天类
'小雨': 'icons/weather/rain.svg',
'中雨': 'icons/weather/rain.svg',
'大雨': 'icons/weather/rain.svg',
'暴雨': 'icons/weather/rain.svg',
'大暴雨': 'icons/weather/rain.svg',
'特大暴雨': 'icons/weather/rain.svg',
'毛毛雨': 'icons/weather/rain.svg',
'雨': 'icons/weather/rain.svg',
// 阵雨类
'阵雨': 'icons/weather/shower.svg',
'雷阵雨': 'icons/weather/shower.svg',
'雷阵雨并伴有冰雹': 'icons/weather/shower.svg',
// 雪天类
'小雪': 'icons/weather/snow.svg',
'中雪': 'icons/weather/snow.svg',
'大雪': 'icons/weather/snow.svg',
'暴雪': 'icons/weather/snow.svg',
'雨夹雪': 'icons/weather/snow.svg',
'阵雪': 'icons/weather/snow.svg',
// 雾霾类
'雾': 'icons/weather/fog.svg',
'浓雾': 'icons/weather/fog.svg',
'霾': 'icons/weather/fog.svg',
'中度霾': 'icons/weather/fog.svg',
'重度霾': 'icons/weather/fog.svg',
'沙尘暴': 'icons/weather/fog.svg',
'浮尘': 'icons/weather/fog.svg',
'扬沙': 'icons/weather/fog.svg',
// 默认
'未知': 'icons/weather/default.svg'
}
return iconMap[weather] || 'icons/weather/default.svg'
}
/**
* 获取天气对应的主题色
* @param weather 天气现象字符串
* @returns 颜色值
*/
static getWeatherColor(weather: string): string {
if (weather.includes('晴')) {
return '#FFA500' // 橙色 - 晴天
} else if (weather.includes('云')) {
return '#87CEEB' // 天蓝色 - 多云
} else if (weather.includes('雨')) {
return '#4682B4' // 钢蓝色 - 雨天
} else if (weather.includes('雪')) {
return '#B0E0E6' // 粉蓝色 - 雪天
} else if (weather.includes('雾') || weather.includes('霾')) {
return '#808080' // 灰色 - 雾霾
} else {
return '#A9846A' // 默认驼色
}
}
}
6. 在页面中使用天气服务
// pages/WeatherDetailPage.ets
import { WeatherService } from '../services/WeatherService'
import { WeatherIconMapper } from '../models/WeatherModels'
import {
LocalWeatherLive,
LocalWeatherForecast,
LocalDayWeatherForecast
} from '@amap/amap_lbs_search'
import { ArrayList } from '@kit.ArkTS'
import { common } from '@kit.AbilityKit'
@Entry
@Component
struct WeatherDetailPage {
private context: Context = this.getUIContext().getHostContext() as Context
@State cityName: string = '北京'
@State weatherLive: LocalWeatherLive | null = null
@State weatherForecast: LocalWeatherForecast | null = null
@State forecastList: ArrayList<LocalDayWeatherForecast> = new ArrayList()
@State isLoading: boolean = true
aboutToAppear(): void {
this.loadWeatherData()
}
/**
* 加载天气数据(实时 + 预报)
*/
private async loadWeatherData(): Promise<void> {
this.isLoading = true
try {
const weatherService = new WeatherService(this.context as common.UIAbilityContext)
// 并行获取实时天气和预报天气
const livePromise = weatherService.searchLiveWeather(this.cityName)
const forecastPromise = weatherService.searchForecastWeather(this.cityName)
this.weatherLive = await livePromise
this.weatherForecast = await forecastPromise
if (this.weatherForecast) {
this.forecastList = this.weatherForecast.getWeatherForecast()
}
console.info(`[WeatherDetailPage] ✅ 天气数据加载成功`)
} catch (error) {
console.error(`[WeatherDetailPage] ❌ 天气数据加载失败:`, error)
} finally {
this.isLoading = false
}
}
build() {
Column() {
// 加载状态
if (this.isLoading) {
LoadingProgress().width(48).height(48)
Text('加载天气数据...').fontSize(14).margin({ top: 12 })
} else {
// 实时天气卡片
if (this.weatherLive) {
this.LiveWeatherCard()
}
// 天气预报列表
if (this.forecastList.length > 0) {
this.ForecastList()
}
}
}
.width('100%')
.height('100%')
.padding(16)
}
@Builder
LiveWeatherCard() {
Column({ space: 8 }) {
// 城市名称
Text(this.cityName)
.fontSize(18)
.fontWeight(FontWeight.Medium)
Row({ space: 24 }) {
// 天气图标
Image($rawfile(WeatherIconMapper.getIconPath(this.weatherLive!.getWeather() || '晴')))
.width(64)
.height(64)
Column({ space: 4 }) {
// 温度
Text(`${this.weatherLive!.getTemperature() || '--'}°`)
.fontSize(48)
.fontWeight(FontWeight.Bold)
// 天气现象
Text(this.weatherLive!.getWeather() || '--')
.fontSize(16)
.fontColor('#666666')
}
}
// 详细信息
Row({ space: 16 }) {
Text(`风向:${this.weatherLive!.getWindDirection() || '--'}`)
Text(`风力:${this.weatherLive!.getWindPower() || '--'}级`)
Text(`湿度:${this.weatherLive!.getHumidity() || '--'}%`)
}
.fontSize(14)
.fontColor('#999999')
}
.width('100%')
.padding(20)
.backgroundColor('#FFFFFF')
.borderRadius(12)
.shadow({ radius: 4, color: '#00000010' })
}
@Builder
ForecastList() {
Column({ space: 8 }) {
Text('未来天气预报')
.fontSize(16)
.fontWeight(FontWeight.Medium)
.margin({ top: 16, bottom: 8 })
ForEach(this.forecastList.convertToArray(), (item: LocalDayWeatherForecast) => {
Row() {
// 日期
Column() {
Text(item.getDate() || '--')
.fontSize(14)
Text(this.getWeekName(item.getWeek()))
.fontSize(12)
.fontColor('#999999')
}
.width(80)
// 白天天气
Row({ space: 4 }) {
Image($rawfile(WeatherIconMapper.getIconPath(item.getDayWeather() || '晴')))
.width(24)
.height(24)
Text(item.getDayWeather() || '--')
.fontSize(14)
}
.layoutWeight(1)
// 温度范围
Text(`${item.getNightTemp() || '--'}° ~ ${item.getDayTemp() || '--'}°`)
.fontSize(14)
.fontColor('#666666')
}
.width('100%')
.padding(12)
.backgroundColor('#FFFFFF')
.borderRadius(8)
})
}
}
private getWeekName(week: string | undefined): string {
const weekMap: Record<string, string> = {
'1': '周一', '2': '周二', '3': '周三', '4': '周四',
'5': '周五', '6': '周六', '7': '周日'
}
return weekMap[week || ''] || ''
}
}
返回数据说明
实时天气 LocalWeatherLive
| 方法 | 返回值 | 说明 |
|---|---|---|
getCity() |
string | 城市名称 |
getWeather() |
string | 天气现象(晴、多云、小雨等) |
getTemperature() |
string | 当前温度(摄氏度) |
getWindDirection() |
string | 风向(东、西南等) |
getWindPower() |
string | 风力等级(1-12级) |
getHumidity() |
string | 相对湿度(百分比) |
getReportTime() |
string | 数据发布时间 |
天气预报 LocalDayWeatherForecast
| 方法 | 返回值 | 说明 |
|---|---|---|
getDate() |
string | 日期(YYYY-MM-DD) |
getWeek() |
string | 星期(1-7) |
getDayWeather() |
string | 白天天气现象 |
getNightWeather() |
string | 夜间天气现象 |
getDayTemp() |
string | 白天温度 |
getNightTemp() |
string | 夜间温度 |
getDayWind() |
string | 白天风向 |
getNightWind() |
string | 夜间风向 |
效果
控制台日志:
[WeatherService] 🔍 开始查询实时天气: 北京
[WeatherService] 🔍 开始查询预报天气: 北京
[WeatherService] ✅ 实时天气查询成功: 北京
[WeatherService] ✅ 预报天气查询成功: 北京
[WeatherDetailPage] ✅ 天气数据加载成功
数据示例:
| 字段 | 值 |
|---|---|
| 城市 | 北京 |
| 天气 | 晴 |
| 温度 | 25° |
| 风向 | 东北风 |
| 风力 | 3级 |
| 湿度 | 45% |
常见错误码
| 错误码 | 说明 | 解决方案 |
|---|---|---|
| 1001 | 参数错误 | 检查城市名称是否正确 |
| 1002 | 网络错误 | 检查网络连接 |
| 1003 | 服务不可用 | 稍后重试 |
| 1008 | Key 无效 | 检查高德 Key 配置 |
关键点总结
| 步骤 | 说明 |
|---|---|
| 1. 创建查询参数 | WeatherSearchQuery(城市, 类型) |
| 2. 设置监听器 | OnWeatherSearchListener 处理回调 |
| 3. 异步查询 | searchWeatherAsyn() 非阻塞 |
| 4. 处理结果 | 判断 errorCode 是否成功 |
| 5. 图标映射 | 天气现象 → 图标资源路径 |
查询类型对比
| 类型 | 常量值 | 返回数据 | 使用场景 |
|---|---|---|---|
| 实时天气 | WEATHER_TYPE_LIVE = 1 |
当前天气详情 | 首页天气展示 |
| 预报天气 | WEATHER_TYPE_FORECAST |
更多关于HarmonyOS 鸿蒙Next中使用高德天气 SDK 实现实时天气与预报查询的实战系列教程也可以访问 https://www.itying.com/category-93-b0.html
在HarmonyOS Next中集成高德天气SDK
步骤概述
1. 申请API Key
首先需要在高德开放平台申请API Key。
2. 创建项目
通过DevEco Studio创建项目。
3. 配置网络权限
在module.json5配置文件中添加网络权限。
4. 使用天气API
- 使用高德天气API接口,例如实时天气和预报查询。
- 通过ArkTS的HTTP模块发起请求。
- 解析返回的JSON数据。
5. 注意事项
- SDK需适配HarmonyOS Next的API版本。
- 确保兼容性。
在HarmonyOS Next中集成高德天气SDK实现天气查询,可以按照以下步骤进行:
1. 环境准备
- 在AppGallery Connect中创建项目,并开启高德地图服务。
- 下载高德天气SDK的HarmonyOS版本,将
.har包放入工程的entry/libs目录。 - 在
module.json5中添加权限:
{
"module": {
"requestPermissions": [
{
"name": "ohos.permission.INTERNET"
}
]
}
}
2. 初始化SDK
在EntryAbility的onCreate中初始化:
import weather from '@ohos/weather';
export default class EntryAbility extends Ability {
onCreate(want: Want, launchParam: AbilityConstant.LaunchParam): void {
weather.init({
apiKey: '你的高德开放平台Key'
});
}
}
3. 实时天气查询
使用异步任务避免阻塞UI:
import { weather } from '@ohos/weather';
import { BusinessError } from '@ohos.base';
async function getRealtimeWeather(city: string): Promise<void> {
try {
const result = await weather.getRealtimeWeather({
city: city,
extensions: 'base' // 返回基础信息
});
// 解析数据
const temperature = result.temperature; // 温度
const weatherDesc = result.weather; // 天气现象
const windDirection = result.winddirection; // 风向
const windPower = result.windpower; // 风力
const humidity = result.humidity; // 湿度
// 更新UI(需在主线程)
getContext().uiTaskCenter.executeTask(() => {
// 更新UI组件
});
} catch (error) {
const err: BusinessError = error as BusinessError;
console.error(`查询失败: ${err.code} ${err.message}`);
}
}
4. 天气预报查询
async function getWeatherForecast(city: string, days: number): Promise<void> {
try {
const result = await weather.getWeatherForecast({
city: city,
extensions: 'all', // 返回预报信息
days: days
});
// 处理预报数据
result.forecasts.forEach((forecast: any) => {
const date = forecast.date; // 日期
const dayTemp = forecast.daytemp; // 白天温度
const nightTemp = forecast.nighttemp; // 夜间温度
const dayWeather = forecast.dayweather; // 白天天气
const nightWeather = forecast.nightweather; // 夜间天气
});
} catch (error) {
// 错误处理
}
}
5. 天气图标显示
建议方案:
- 下载高德天气图标包(或自定义图标)
- 根据返回的天气代码映射图标:
const weatherIcons: Map<string, string> = new Map([
['晴', 'sunny.png'],
['多云', 'cloudy.png'],
['雨', 'rain.png'],
// ...其他映射
]);
function getWeatherIcon(weatherDesc: string): Resource {
const iconName = weatherIcons.get(weatherDesc) || 'default.png';
return $r(`app.media.${iconName}`);
}
6. 异步处理最佳实践
- 使用
TaskPool或Worker处理复杂计算 - UI更新通过
uiTaskCenter.executeTask()回到主线程 - 添加加载状态和错误重试机制
关键注意事项
- 确保网络权限正确配置
- 高德Key需要在真机测试
- 注意API调用频率限制
- 错误处理要完善,特别是网络异常情况
通过以上实现,可以完成天气查询功能,且不会阻塞UI线程。

