鸿蒙5应用消息推送:AGC Push通知集成详解

一、AGC Push服务介绍与准备工作

  1. AGC Push服务概述
    AGC Push是华为提供的消息推送服务,支持多种消息类型:

通知栏消息
透传消息
富媒体消息
定时消息
2. 开通Push服务
登录AppGallery Connect
进入你的项目
选择"增长" > "推送服务"
点击"立即开通"按钮
3. 配置HarmonyOS项目
在entry/build.gradle中添加依赖:

dependencies {
// AGC核心库
implementation 'com.huawei.agconnect:agconnect-core-harmony:1.6.5.300'
// Push服务库
implementation 'com.huawei.agconnect:agconnect-push-harmony:1.6.5.300'
}
二、Push服务初始化与配置

  1. 初始化AGC Push服务
    在EntryAbility.ets中进行初始化:

import agconnect from '@hw-agconnect/core';
import push from '@hw-agconnect/push';

@Entry
@Component
struct EntryAbility {
onWindowStageCreate(windowStage: Window.WindowStage) {
// 初始化AGC
agconnect.instance().init();

    // 初始化Push服务
    push.instance().init();
    
    // 设置默认通知处理
    push.instance().on('pushMessageReceived', (data) => {
        console.log('收到推送消息:', JSON.stringify(data));
        // 这里可以添加自定义处理逻辑
    });
}

}
2. 获取Push Token
创建PushManager.ets工具类:

import push from '@hw-agconnect/push';

export class PushManager {
private static instance: PushManager | null = null;

private constructor() {}

public static getInstance(): PushManager {
    if (!PushManager.instance) {
        PushManager.instance = new PushManager();
    }
    return PushManager.instance;
}

// 获取设备Push Token
async getPushToken(): Promise<string> {
    try {
        const token = await push.instance().getToken();
        console.log('Push Token:', token);
        return token;
    } catch (error) {
        console.error('获取Push Token失败:', error);
        throw error;
    }
}

// 删除Push Token
async deleteToken(): Promise<void> {
    try {
        await push.instance().deleteToken();
        console.log('Push Token已删除');
    } catch (error) {
        console.error('删除Push Token失败:', error);
        throw error;
    }
}

}
三、实现消息接收与处理

  1. 配置消息接收监听
    在EntryAbility.ets中扩展消息处理:

onWindowStageCreate(windowStage: Window.WindowStage) {
// ...其他初始化代码...

// 监听通知点击事件
push.instance().on('notificationClicked', (data) => {
    console.log('通知被点击:', JSON.stringify(data));
    this.handleNotificationClick(data);
});

// 监听透传消息
push.instance().on('dataMessageReceived', (data) => {
    console.log('收到透传消息:', JSON.stringify(data));
    this.handleDataMessage(data);
});

}

private handleNotificationClick(data: any) {
// 解析通知中的自定义参数
const extras = data.notification?.extras || {};

// 根据参数跳转到不同页面
if (extras.page) {
    router.pushUrl({
        url: extras.page,
        params: extras
    });
}

}

private handleDataMessage(data: any) {
// 处理透传消息,可以更新UI或执行后台任务
// 注意:透传消息不会自动显示通知
// 需要手动调用通知API显示
this.showLocalNotification(data);
}

private showLocalNotification(data: any) {
try {
const notificationRequest: NotificationManager.NotificationRequest = {
content: {
contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
normal: {
title: data.title || '新消息',
text: data.text || '您收到一条新消息',
additionalText: data.additionalText || ''
}
},
id: Date.now(),
isOngoing: false,
tapDismissed: true,
extras: data.extras || {}
};

    NotificationManager.publish(notificationRequest);
} catch (error) {
    console.error('显示本地通知失败:', error);
}

}
四、实现消息发送功能

  1. 服务端发送消息示例(Node.js)
    const agconnect = require('@hw-agconnect/server');

// 初始化AGC
agconnect.instance().init({
clientId: 'YOUR_CLIENT_ID',
clientSecret: 'YOUR_CLIENT_SECRET',
projectId: 'YOUR_PROJECT_ID'
});

// 发送通知消息
async function sendNotificationMessage(tokens, title, body, extras = {}) {
try {
const pushMessaging = agconnect.push().messaging();

    const message = {
        notification: {
            title: title,
            body: body
        },
        android: {
            notification: {
                click_action: {
                    type: 1 // 打开应用
                },
                extras: extras
            }
        },
        tokens: tokens // 设备token数组
    };
    
    const response = await pushMessaging.send(message);
    console.log('消息发送成功:', response);
    return response;
} catch (error) {
    console.error('消息发送失败:', error);
    throw error;
}

}

// 发送透传消息
async function sendDataMessage(tokens, data) {
try {
const pushMessaging = agconnect.push().messaging();

    const message = {
        data: data,
        tokens: tokens
    };
    
    const response = await pushMessaging.send(message);
    console.log('透传消息发送成功:', response);
    return response;
} catch (error) {
    console.error('透传消息发送失败:', error);
    throw error;
}

}
2. 鸿蒙端实现消息发送UI
@Entry
@Component
struct PushTestPage {
@State token: string = '';
@State messageTitle: string = '';
@State messageBody: string = '';
@State result: string = '';

private pushManager = PushManager.getInstance();

build() {
    Column({ space: 20 }) {
        Text('Push通知测试')
            .fontSize(24)
            .fontWeight(FontWeight.Bold)
        
        Button('获取Push Token')
            .width(200)
            .height(50)
            .onClick(async () => {
                try {
                    this.token = await this.pushManager.getPushToken();
                    this.result = `Token: ${this.token}`;
                } catch (error) {
                    this.result = `获取Token失败: ${error.message}`;
                }
            })
        
        TextInput({ text: this.messageTitle })
            .placeholder('输入消息标题')
            .width('90%')
            .onChange((value: string) => {
                this.messageTitle = value;
            })
        
        TextInput({ text: this.messageBody })
            .placeholder('输入消息内容')
            .width('90%')
            .onChange((value: string) => {
                this.messageBody = value;
            })
        
        Button('发送测试通知')
            .width(200)
            .height(50)
            .backgroundColor(Color.Green)
            .onClick(async () => {
                if (!this.token) {
                    this.result = '请先获取Token';
                    return;
                }
                
                try {
                    // 这里应该调用后端API发送消息
                    // 以下是模拟发送的代码
                    push.instance().on('pushMessageReceived', {
                        notification: {
                            title: this.messageTitle,
                            body: this.messageBody,
                            extras: {
                                test: 'true',
                                time: new Date().toISOString()
                            }
                        }
                    });
                    
                    this.result = '测试通知已触发';
                } catch (error) {
                    this.result = `发送失败: ${error.message}`;
                }
            })
        
        Text(this.result)
            .fontSize(16)
            .width('90%')
            .multilineTextAlign(TextAlign.Start)
        
        Text(this.token ? `当前Token: ${this.token}` : '未获取Token')
            .fontSize(14)
            .width('90%')
            .textOverflow({ overflow: TextOverflow.Ellipsis })
    }
    .width('100%')
    .height('100%')
    .padding(20)
}

}
五、高级推送功能实现

  1. 主题订阅与取消
    // 在PushManager.ets中添加方法
    async subscribeToTopic(topic: string): Promise {
    try {
    await push.instance().subscribe(topic);
    console.log(已订阅主题: ${topic});
    } catch (error) {
    console.error(订阅主题${topic}失败:, error);
    throw error;
    }
    }

async unsubscribeFromTopic(topic: string): Promise {
try {
await push.instance().unsubscribe(topic);
console.log(已取消订阅主题: ${topic});
} catch (error) {
console.error(取消订阅主题${topic}失败:, error);
throw error;
}
}
2. 本地通知管理
// 在PushManager.ets中添加本地通知方法
async scheduleLocalNotification(
id: number,
title: string,
body: string,
delaySeconds: number,
extras?: Object
): Promise {
try {
const trigger: NotificationManager.NotificationTrigger = {
type: NotificationManager.TriggerType.TIMER,
timer: {
value: delaySeconds * 1000 // 毫秒
}
};

    const notificationRequest: NotificationManager.NotificationRequest = {
        content: {
            contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
            normal: {
                title: title,
                text: body,
                additionalText: ''
            }
        },
        id: id,
        isOngoing: false,
        tapDismissed: true,
        extras: extras || {},
        trigger: trigger
    };
    
    await NotificationManager.publish(notificationRequest);
    console.log(`本地通知已计划,ID: ${id}`);
} catch (error) {
    console.error('计划本地通知失败:', error);
    throw error;
}

}

async cancelLocalNotification(id: number): Promise {
try {
await NotificationManager.cancel(id);
console.log(已取消通知,ID: ${id});
} catch (error) {
console.error('取消通知失败:', error);
throw error;
}
}
六、消息统计分析

  1. 配置消息点击跟踪
    在EntryAbility.ets中:

private handleNotificationClick(data: any) {
// 记录消息点击事件
push.instance().reportNotificationClicked(data.msgId);

// ...原有的点击处理逻辑...

}
2. 在AGC控制台查看分析数据
进入"推送服务" > "统计分析"
可以查看:
消息送达率
点击率
用户设备分布
时间趋势分析
七、常见问题与解决方案

  1. 收不到推送消息
    ​​排查步骤:​​

确认设备已联网
检查Token是否成功获取
验证AGC控制台消息发送状态
检查应用通知权限是否开启
​​代码检查:​​

// 检查通知权限
async checkNotificationPermission(): Promise {
try {
const result = await NotificationManager.isNotificationEnabled();
console.log('通知权限状态:', result);
return result;
} catch (error) {
console.error('检查通知权限失败:', error);
return false;
}
}

// 打开通知设置页面
async openNotificationSettings() {
try {
await NotificationManager.requestEnableNotification();
} catch (error) {
console.error('打开通知设置失败:', error);
}
}
2. Token失效问题
​​处理方案:​​

// 在PushManager.ets中添加Token监听
setupTokenListeners() {
// 监听Token变化
push.instance().on('tokenUpdated', (newToken) => {
console.log('Token已更新:', newToken);
// 这里应该将新Token发送到你的服务器
});

// 监听Token失效
push.instance().on('tokenInvalid', () => {
    console.log('Token已失效');
    // 重新获取Token
    this.getPushToken();
});

}
3. 后台接收限制
​​解决方案:​​

添加后台任务权限
实现后台服务处理消息
在module.json5中添加权限:

{
"module": {
"abilities": [
{
"backgroundModes": [
"notification",
"dataTransfer"
]
}
],
"requestPermissions": [
{
"name": "ohos.permission.KEEP_BACKGROUND_RUNNING"
}
]
}
}
八、完整示例:新闻应用推送实现

  1. 新闻推送服务类
    // NewsPushService.ets
    import { PushManager } from './PushManager';

export class NewsPushService {
private static instance: NewsPushService | null = null;
private pushManager = PushManager.getInstance();

private constructor() {
    this.setupNewsPushListeners();
}

public static getInstance(): NewsPushService {
    if (!NewsPushService.instance) {
        NewsPushService.instance = new NewsPushService();
    }
    return NewsPushService.instance;
}

private setupNewsPushListeners() {
    // 监听新闻推送
    push.instance().on('pushMessageReceived', (data) => {
        if (data.notification?.extras?.type === 'news') {
            this.handleNewsPush(data);
        }
    });
}

private handleNewsPush(data: any) {
    const extras = data.notification?.extras || {};
    const newsId = extras.newsId;
    const category = extras.category || 'general';
    
    // 存储未读新闻
    this.saveUnreadNews(newsId, category);
    
    // 显示本地通知
    this.showNewsNotification(
        data.notification.title,
        data.notification.body,
        extras
    );
}

private async saveUnreadNews(newsId: string, category: string) {
    // 这里可以实现将未读新闻保存到本地数据库
    console.log(`保存未读新闻: ${newsId}, 分类: ${category}`);
}

private showNewsNotification(title: string, body: string, extras: any) {
    try {
        const notificationRequest = {
            content: {
                contentType: NotificationManager.ContentType.NOTIFICATION_CONTENT_BASIC_TEXT,
                normal: {
                    title: title,
                    text: body,
                    additionalText: '点击查看详情'
                }
            },
            id: parseInt(extras.newsId),
            isOngoing: false,
            tapDismissed: true,
            extras: extras
        };
        
        NotificationManager.publish(notificationRequest);
    } catch (error) {
        console.error('显示新闻通知失败:', error);
    }
}

// 订阅新闻分类
async subscribeToNewsCategory(category: string) {
    try {
        await this.pushManager.subscribeToTopic(`news_${category}`);
        console.log(`已订阅新闻分类: ${category}`);
    } catch (error) {
        console.error(`订阅新闻分类${category}失败:`, error);
        throw error;
    }
}

// 取消订阅新闻分类
async unsubscribeFromNewsCategory(category: string) {
    try {
        await this.pushManager.unsubscribeFromTopic(`news_${category}`);
        console.log(`已取消订阅新闻分类: ${category}`);
    } catch (error) {
        console.error(`取消订阅新闻分类${category}失败:`, error);
        throw error;
    }
}

}
2. 新闻页面集成推送
@Entry
@Component
struct NewsDetailPage {
@State newsItem: NewsItem = { id: '0', title: '', content: '' };
@State isSubscribed: boolean = false;

private newsPushService = NewsPushService.getInstance();

build() {
    Column() {
        Text(this.newsItem.title)
            .fontSize(24)
            .fontWeight(FontWeight.Bold)
        
        Text(this.newsItem.content)
            .fontSize(16)
            .margin({ top: 20 })
        
        Button(this.isSubscribed ? '取消订阅此类新闻' : '订阅此类新闻')
            .width(200)
            .height(50)
            .margin({ top: 30 })
            .onClick(async () => {
                if (this.isSubscribed) {
                    await this.newsPushService.unsubscribeFromNewsCategory(this.newsItem.category);
                } else {
                    await this.newsPushService.subscribeToNewsCategory(this.newsItem.category);
                }
                this.isSubscribed = !this.isSubscribed;
            })
    }
    .padding(20)
    .width('100%')
    .height('100%')
}

onPageShow() {
    // 从路由参数获取新闻项
    const params = router.getParams();
    if (params && params.newsItem) {
        this.newsItem = params.newsItem;
        
        // 检查是否已订阅
        this.checkSubscriptionStatus();
    }
}

async checkSubscriptionStatus() {
    // 这里应该实现检查用户是否已订阅此类新闻
    // 简化示例,假设使用本地存储
    this.isSubscribed = localStorage.get(`subscribed_${this.newsItem.category}`) === 'true';
}

}
总结
通过本文的详细讲解,你已经掌握了在HarmonyOS 5应用中集成AGC Push服务的完整流程:

​​环境配置​​:正确初始化Push服务和配置项目
​​Token管理​​:获取和管理设备Push Token
​​消息处理​​:实现通知和透传消息的接收与处理
​​高级功能​​:主题订阅、本地通知和统计分析
​​实战案例​​:新闻应用的完整推送实现
实际开发中,你还可以进一步探索:

推送消息的A/B测试
基于用户行为的精准推送
推送消息的个性化定制
与其他AGC服务(如Analytics)的集成

posted @ 2025-06-28 22:34  暗雨YA  阅读(156)  评论(0)    收藏  举报