在鸿蒙HarmonyOS 5中使用CodeGenie实现一个获取实时新闻推送小程序
·
应用概述
这个实时新闻推送应用将提供多种新闻类别的实时更新,支持个性化订阅、新闻收藏和推送通知功能。
开发步骤
1. 创建项目
- 打开CodeGenie IDE
- 选择"File" > "New" > "HarmonyOS Project"
- 输入项目名称"NewsFlash"
- 选择API版本为HarmonyOS 5
- 点击"Finish"
2. 配置权限
在config.json中添加必要权限:
{
"module": {
"reqPermissions": [
{
"name": "ohos.permission.INTERNET"
},
{
"name": "ohos.permission.RECEIVER_STARTUP_COMPLETED"
},
{
"name": "ohos.permission.NOTIFICATION_CONTROLLER"
},
{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
}
]
}
}
3. 设计数据模型
在resources/base/profile目录下创建news_data.json:
{
"categories": [
{"id": 1, "name": "头条", "subscribed": true},
{"id": 2, "name": "科技", "subscribed": false},
{"id": 3, "name": "财经", "subscribed": false},
{"id": 4, "name": "体育", "subscribed": true},
{"id": 5, "name": "娱乐", "subscribed": false}
],
"news": [
{
"id": 1,
"title": "鸿蒙系统5.0正式发布",
"content": "华为今日正式发布鸿蒙HarmonyOS 5.0系统,带来多项创新功能...",
"category": "科技",
"time": "2023-08-10 09:30",
"source": "华为新闻",
"image": "media/harmonyos5.jpg",
"isBreaking": true
}
]
}
4. 创建主界面布局
在resources/base/layout目录下创建main_page.xml:
<TabView
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:width="match_parent"
ohos:height="match_parent">
<TabBar
ohos:width="match_parent"
ohos:height="50vp"
ohos:orientation="horizontal">
<TextTab>推荐</TextTab>
<TextTab>订阅</TextTab>
<TextTab>收藏</TextTab>
</TabBar>
<TabContent>
<!-- 推荐新闻列表 -->
<RefreshContainer ohos:id="$+id:refresh_container">
<ListContainer ohos:id="$+id:news_list"/>
</RefreshContainer>
</TabContent>
<TabContent>
<!-- 订阅管理 -->
<ListContainer ohos:id="$+id:subscription_list"/>
</TabContent>
<TabContent>
<!-- 收藏新闻 -->
<ListContainer ohos:id="$+id:favorites_list"/>
</TabContent>
</TabView>
5. 实现主界面逻辑
在src/main/ets/MainAbility目录下创建MainPage.ets:
import newsData from '../../resources/base/profile/news_data.json';
import { NewsItem, NewsCategory } from '../common/model';
@Entry
@Component
struct MainPage {
@State newsList: Array<NewsItem> = newsData.news
@State categories: Array<NewsCategory> = newsData.categories
@State favorites: Array<NewsItem> = []
@State activeTab: number = 0
@State refreshing: boolean = false
// 模拟从网络获取最新新闻
fetchLatestNews() {
this.refreshing = true
// 实际开发中替换为真实的API调用
setTimeout(() => {
this.newsList = [...this.generateMockNews(), ...this.newsList]
this.refreshing = false
}, 1500)
}
// 生成模拟新闻数据
generateMockNews(): Array<NewsItem> {
const mockTitles = [
"我国成功发射新一代通信卫星",
"人工智能大会在上海开幕",
"新能源汽车销量创新高",
"世界杯预选赛亚洲区开战"
]
return mockTitles.map((title, index) => ({
id: Date.now() + index,
title,
content: `${title}相关内容...`,
category: ["科技", "科技", "财经", "体育"][index],
time: new Date().toLocaleString(),
source: ["新华社", "央视新闻", "财经日报", "体育在线"][index],
image: "",
isBreaking: index % 3 === 0
}))
}
build() {
Tabs({ barPosition: BarPosition.Start }) {
TabContent() {
Refresh({ refreshing: this.refreshing }) {
List() {
ForEach(this.newsList, (item: NewsItem) => {
ListItem() {
NewsCard({ news: item })
}
})
}
.width('100%')
.divider({ strokeWidth: 1, color: '#f0f0f0' })
}
.onRefresh(() => {
this.fetchLatestNews()
})
}.tabBar('推荐')
TabContent() {
List() {
ForEach(this.categories, (category: NewsCategory) => {
ListItem() {
Row() {
Text(category.name)
.fontSize(18)
.layoutWeight(1)
Toggle({ type: ToggleType.Checkbox, isOn: category.subscribed })
.onChange((isOn: boolean) => {
category.subscribed = isOn
})
}
.width('100%')
.padding(15)
}
})
}
}.tabBar('订阅')
TabContent() {
if (this.favorites.length === 0) {
Column() {
Image($r('app.media.empty_favorites'))
.width(150)
.height(150)
.margin({ bottom: 20 })
Text('暂无收藏内容')
.fontSize(16)
.fontColor(Color.Gray)
}
.width('100%')
.height('100%')
.justifyContent(FlexAlign.Center)
} else {
List() {
ForEach(this.favorites, (item: NewsItem) => {
ListItem() {
NewsCard({ news: item })
}
})
}
}
}.tabBar('收藏')
}
.barWidth('100%')
.barHeight(50)
.onChange((index: number) => {
this.activeTab = index
})
}
}
@Component
struct NewsCard {
@Prop news: NewsItem
@State isFavorite: boolean = false
build() {
Column() {
if (this.news.isBreaking) {
Row() {
Image($r('app.media.breaking'))
.width(20)
.height(20)
.margin({ right: 5 })
Text('快讯')
.fontSize(14)
.fontColor(Color.Red)
}
.width('100%')
.margin({ bottom: 5 })
}
Row() {
Column() {
Text(this.news.title)
.fontSize(18)
.fontWeight(FontWeight.Bold)
.margin({ bottom: 5 })
Text(`${this.news.source} · ${this.news.time}`)
.fontSize(12)
.fontColor(Color.Gray)
}
.layoutWeight(1)
Icon(this.isFavorite ? $r('app.media.favorite_filled') : $r('app.media.favorite'))
.width(24)
.height(24)
.onClick(() => {
this.isFavorite = !this.isFavorite
// 这里应更新收藏列表
})
}
if (this.news.image) {
Image(this.news.image)
.width('100%')
.height(150)
.margin({ top: 10 })
.objectFit(ImageFit.Cover)
}
Text(this.news.content.length > 60 ?
this.news.content.substring(0, 60) + '...' :
this.news.content)
.fontSize(14)
.margin({ top: 10 })
}
.width('100%')
.padding(15)
.onClick(() => {
router.push({
url: 'pages/NewsDetail',
params: { newsId: this.news.id }
})
})
}
}
6. 创建新闻详情页
在resources/base/layout目录下创建news_detail.xml:
<ScrollView
xmlns:ohos="http://schemas.huawei.com/res/ohos"
ohos:width="match_parent"
ohos:height="match_parent">
<DirectionalLayout
ohos:width="match_parent"
ohos:height="match_content"
ohos:orientation="vertical"
ohos:padding="20vp">
<Text
ohos:id="$+id:title"
ohos:width="match_parent"
ohos:height="wrap_content"
ohos:text_size="20fp"
ohos:text_alignment="center"
ohos:margin="10vp"/>
<Text
ohos:id="$+id:meta"
ohos:width="match_parent"
ohos:height="wrap_content"
ohos:text_size="14fp"
ohos:text_alignment="center"
ohos:margin="5vp"/>
<Image
ohos:id="$+id:image"
ohos:width="match_parent"
ohos:height="200vp"
ohos:margin="10vp"
ohos:visibility="visible"/>
<Text
ohos:id="$+id:content"
ohos:width="match_parent"
ohos:height="wrap_content"
ohos:text_size="16fp"
ohos:margin="10vp"/>
<Button
ohos:id="$+id:share_btn"
ohos:width="match_parent"
ohos:height="50vp"
ohos:text="分享新闻"
ohos:margin="10vp"/>
</DirectionalLayout>
</ScrollView>
7. 实现详情页逻辑
创建NewsDetail.ets:
import newsData from '../../resources/base/profile/news_data.json';
import { NewsItem } from '../common/model';
@Entry
@Component
struct NewsDetail {
@State news: NewsItem = newsData.news[0]
@State isFavorite: boolean = false
onInit() {
const params = router.getParams() as Record<string, number>
if (params && params.newsId) {
const foundNews = newsData.news.find(item => item.id === params.newsId)
if (foundNews) {
this.news = foundNews
}
}
}
build() {
Column() {
Text(this.news.title)
.fontSize(20)
.fontWeight(FontWeight.Bold)
.textAlign(TextAlign.Center)
.margin(10)
Text(`${this.news.source} · ${this.news.time}`)
.fontSize(14)
.fontColor(Color.Gray)
.textAlign(TextAlign.Center)
.margin({ bottom: 15 })
if (this.news.image) {
Image(this.news.image)
.width('100%')
.height(200)
.objectFit(ImageFit.Cover)
.margin({ bottom: 15 })
}
Text(this.news.content)
.fontSize(16)
.margin({ bottom: 20 })
Row() {
Button('分享')
.width('45%')
.height(45)
.onClick(() => {
this.shareNews()
})
Button(this.isFavorite ? '已收藏' : '收藏')
.width('45%')
.height(45)
.margin({ left: '10%' })
.backgroundColor(this.isFavorite ? '#f0f0f0' : '#1890ff')
.onClick(() => {
this.isFavorite = !this.isFavorite
// 这里应更新收藏列表
})
}
.width('100%')
.margin({ top: 10 })
}
.width('100%')
.padding(15)
}
shareNews() {
// 实现分享功能
prompt.showToast({
message: '分享功能已触发',
duration: 2000
})
}
}
8. 添加类型定义
在src/main/ets/common目录下创建model.ets:
export interface NewsItem {
id: number;
title: string;
content: string;
category: string;
time: string;
source: string;
image: string;
isBreaking: boolean;
}
export interface NewsCategory {
id: number;
name: string;
subscribed: boolean;
}
9. 实现推送服务
创建src/main/ets/services/PushService.ets:
import { NewsItem } from '../common/model';
import notification from '@ohos.notification';
export class PushService {
static subscribeToCategory(categoryId: number) {
// 实际开发中这里应该调用推送服务的订阅API
console.log(`已订阅分类ID: ${categoryId}`)
}
static unsubscribeFromCategory(categoryId: number) {
// 实际开发中这里应该调用推送服务的取消订阅API
console.log(`已取消订阅分类ID: ${categoryId}`)
}
static showNotification(news: NewsItem) {
notification.publish({
id: news.id,
content: {
title: news.title,
text: news.content.length > 50 ? news.content.substring(0, 50) + '...' : news.content
},
tapAction: {
want: {
bundleName: 'com.example.newsflash',
abilityName: 'MainAbility',
uri: `news://detail?id=${news.id}`
}
}
}).then(() => {
console.log('通知发送成功')
}).catch(err => {
console.error('通知发送失败:', err)
})
}
static checkForBreakingNews() {
// 定时检查突发新闻
setInterval(() => {
// 实际开发中这里应该调用API检查最新新闻
const mockBreakingNews = {
id: Date.now(),
title: "突发: " + ["地震快报", "重大政策", "国际事件", "股市异动"][Math.floor(Math.random() * 4)],
content: "点击查看详情...",
category: "头条",
time: new Date().toLocaleString(),
source: "新闻快讯",
image: "",
isBreaking: true
}
this.showNotification(mockBreakingNews)
}, 3600000) // 每小时检查一次
}
}
10. 添加路由配置
在src/main/resources/base/profile/main_pages.json中添加:
{
"src": [
"pages/MainPage",
"pages/NewsDetail"
]
}
功能扩展建议
- 集成新闻API:连接真实的新闻API如NewsAPI、腾讯新闻API等
- 离线阅读:实现新闻缓存功能,支持离线阅读
- 夜间模式:添加暗色主题支持
- 字体调整:允许用户调整新闻阅读字体大小
- 评论功能:添加新闻评论和互动功能
- 视频新闻:支持视频新闻播放
- 本地新闻:基于位置服务的本地新闻推送
- AI摘要:使用AI生成新闻摘要
测试与发布
- 在CodeGenie中使用预览器测试应用界面
- 测试推送通知功能
- 测试网络请求和错误处理
- 在真机设备上测试所有功能
- 使用HUAWEI AppGallery Connect进行应用签名和发布
这个实时新闻推送小程序将帮助用户随时获取最新资讯,通过鸿蒙系统的分布式能力,用户可以在手机、平板、智能手表等多种设备上接收和阅读新闻。
更多推荐


所有评论(0)