capacitor-push-notifications by cap-go/capgo-skills
npx skills add https://github.com/cap-go/capgo-skills --skill capacitor-push-notifications使用 Firebase 和 APNs 为 iOS 和 Android 实现推送通知。
bun add @capacitor/push-notifications
bunx cap sync
import { PushNotifications } from '@capacitor/push-notifications';
async function initPushNotifications() {
// 请求权限
const permission = await PushNotifications.requestPermissions();
if (permission.receive === 'granted') {
// 注册推送
await PushNotifications.register();
}
// 获取 FCM 令牌
PushNotifications.addListener('registration', (token) => {
console.log('推送令牌:', token.value);
// 将令牌发送到您的服务器
sendTokenToServer(token.value);
});
// 处理注册错误
PushNotifications.addListener('registrationError', (error) => {
console.error('注册错误:', error);
});
// 处理接收到的通知(前台)
PushNotifications.addListener('pushNotificationReceived', (notification) => {
console.log('收到通知:', notification);
// 显示应用内通知
showInAppNotification(notification);
});
// 处理通知点击
PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
console.log('通知操作:', action);
// 根据通知数据导航
handleNotificationTap(action.notification);
});
}
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
下载 google-services.json 到 android/app/
// android/build.gradle
buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.4.0'
}
}
// android/app/build.gradle
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation platform('com.google.firebase:firebase-bom:32.7.0')
implementation 'com.google.firebase:firebase-messaging'
}
下载 GoogleService-Info.plist 到 ios/App/App/
# ios/App/Podfile
pod 'Firebase/Messaging'
// ios/App/App/AppDelegate.swift
import Firebase
import FirebaseMessaging
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
return true
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Messaging.messaging().apnsToken = deviceToken
}
}
在 Xcode 中:
import admin from 'firebase-admin';
// 初始化
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
// 发送到单个设备
async function sendToDevice(token: string) {
await admin.messaging().send({
token,
notification: {
title: '你好!',
body: '您有一条新消息',
},
data: {
type: 'message',
messageId: '123',
},
android: {
priority: 'high',
notification: {
channelId: 'messages',
icon: 'ic_notification',
color: '#4285f4',
},
},
apns: {
payload: {
aps: {
badge: 1,
sound: 'default',
},
},
},
});
}
// 发送到主题
async function sendToTopic(topic: string) {
await admin.messaging().send({
topic,
notification: {
title: '突发新闻',
body: '发生了重要的事情',
},
});
}
// 发送到多个设备
async function sendToMultiple(tokens: string[]) {
await admin.messaging().sendEachForMulticast({
tokens,
notification: {
title: '更新',
body: '有新功能可用',
},
});
}
curl -X POST \
'https://fcm.googleapis.com/v1/projects/YOUR_PROJECT/messages:send' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"message": {
"token": "DEVICE_TOKEN",
"notification": {
"title": "Hello",
"body": "World"
}
}
}'
import { PushNotifications } from '@capacitor/push-notifications';
// 创建渠道
await PushNotifications.createChannel({
id: 'messages',
name: '消息',
description: '消息通知',
importance: 5, // 最高重要性
visibility: 1, // 公开
sound: 'notification.wav',
vibration: true,
lights: true,
lightColor: '#FF0000',
});
// 删除渠道
await PushNotifications.deleteChannel({ id: 'old-channel' });
// 列出渠道
const channels = await PushNotifications.listChannels();
// 订阅主题
await PushNotifications.addListener('registration', async () => {
// 根据用户偏好订阅主题
const messaging = getMessaging();
await subscribeToTopic(messaging, 'news');
await subscribeToTopic(messaging, 'promotions');
});
// ios/App/NotificationService/NotificationService.swift
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
guard let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent else {
contentHandler(request.content)
return
}
// 添加图片
if let imageUrl = request.content.userInfo["image"] as? String,
let url = URL(string: imageUrl) {
downloadImage(url: url) { attachment in
if let attachment = attachment {
mutableContent.attachments = [attachment]
}
contentHandler(mutableContent)
}
} else {
contentHandler(mutableContent)
}
}
}
// 处理操作按钮
PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
switch (action.actionId) {
case 'reply':
// 处理回复操作
const input = action.inputValue;
sendReply(input);
break;
case 'dismiss':
// 处理关闭
break;
default:
// 处理点击
navigateToContent(action.notification.data);
}
});
// 服务器端:发送纯数据消息
{
"to": "DEVICE_TOKEN",
"data": {
"type": "sync",
"action": "refresh"
}
// 没有 "notification" 键 = 纯数据
}
// android/app/src/main/java/.../FirebaseService.kt
class FirebaseService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
// 在后台处理数据消息
message.data["type"]?.let { type ->
when (type) {
"sync" -> performBackgroundSync()
"update" -> checkForUpdates()
}
}
}
}
import { LocalNotifications } from '@capacitor/local-notifications';
// 在前台时显示本地通知
PushNotifications.addListener('pushNotificationReceived', async (notification) => {
await LocalNotifications.schedule({
notifications: [
{
id: Date.now(),
title: notification.title || '',
body: notification.body || '',
extra: notification.data,
},
],
});
});
async function requestNotificationPermission() {
const { receive } = await PushNotifications.checkPermissions();
if (receive === 'prompt') {
// 先显示解释
const shouldRequest = await showPermissionExplanation();
if (shouldRequest) {
const result = await PushNotifications.requestPermissions();
return result.receive === 'granted';
}
return false;
}
if (receive === 'denied') {
// 引导用户前往设置
showSettingsPrompt();
return false;
}
return receive === 'granted';
}
// 处理令牌刷新
PushNotifications.addListener('registration', async (token) => {
const oldToken = await getStoredToken();
if (oldToken !== token.value) {
// 令牌已更改,更新服务器
await updateServerToken(oldToken, token.value);
await storeToken(token.value);
}
});
PushNotifications.addListener('registrationError', (error) => {
console.error('推送注册失败:', error);
// 记录到分析工具
analytics.logEvent('push_registration_failed', {
error: error.error,
});
// 使用退避策略重试
scheduleRetry();
});
| 问题 | 解决方案 |
|---|---|
| 没有令牌 | 检查权限、网络 |
| 仅前台接收 | 实现后台处理器 |
| 延迟送达 | 使用高优先级、纯数据 |
| 没有声音 | 配置通知渠道 |
| 徽章未更新 | 在 payload 中设置徽章 |
每周安装次数
69
仓库
GitHub Stars
18
首次出现
Feb 6, 2026
安全审计
安装于
gemini-cli68
opencode66
github-copilot64
codex64
kimi-cli62
amp62
Implement push notifications for iOS and Android using Firebase and APNs.
bun add @capacitor/push-notifications
bunx cap sync
import { PushNotifications } from '@capacitor/push-notifications';
async function initPushNotifications() {
// Request permission
const permission = await PushNotifications.requestPermissions();
if (permission.receive === 'granted') {
// Register for push
await PushNotifications.register();
}
// Get FCM token
PushNotifications.addListener('registration', (token) => {
console.log('Push token:', token.value);
// Send token to your server
sendTokenToServer(token.value);
});
// Handle registration error
PushNotifications.addListener('registrationError', (error) => {
console.error('Registration error:', error);
});
// Handle incoming notification (foreground)
PushNotifications.addListener('pushNotificationReceived', (notification) => {
console.log('Notification received:', notification);
// Show in-app notification
showInAppNotification(notification);
});
// Handle notification tap
PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
console.log('Notification action:', action);
// Navigate based on notification data
handleNotificationTap(action.notification);
});
}
Download google-services.json to android/app/
// android/build.gradle
buildscript {
dependencies {
classpath 'com.google.gms:google-services:4.4.0'
}
}
// android/app/build.gradle
apply plugin: 'com.google.gms.google-services'
dependencies {
implementation platform('com.google.firebase:firebase-bom:32.7.0')
implementation 'com.google.firebase:firebase-messaging'
}
Download GoogleService-Info.plist to ios/App/App/
# ios/App/Podfile
pod 'Firebase/Messaging'
// ios/App/App/AppDelegate.swift
import Firebase
import FirebaseMessaging
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
FirebaseApp.configure()
return true
}
func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data
) {
Messaging.messaging().apnsToken = deviceToken
}
}
In Xcode:
import admin from 'firebase-admin';
// Initialize
admin.initializeApp({
credential: admin.credential.cert(serviceAccount),
});
// Send to single device
async function sendToDevice(token: string) {
await admin.messaging().send({
token,
notification: {
title: 'Hello!',
body: 'You have a new message',
},
data: {
type: 'message',
messageId: '123',
},
android: {
priority: 'high',
notification: {
channelId: 'messages',
icon: 'ic_notification',
color: '#4285f4',
},
},
apns: {
payload: {
aps: {
badge: 1,
sound: 'default',
},
},
},
});
}
// Send to topic
async function sendToTopic(topic: string) {
await admin.messaging().send({
topic,
notification: {
title: 'Breaking News',
body: 'Something important happened',
},
});
}
// Send to multiple devices
async function sendToMultiple(tokens: string[]) {
await admin.messaging().sendEachForMulticast({
tokens,
notification: {
title: 'Update',
body: 'New features available',
},
});
}
curl -X POST \
'https://fcm.googleapis.com/v1/projects/YOUR_PROJECT/messages:send' \
-H 'Authorization: Bearer ACCESS_TOKEN' \
-H 'Content-Type: application/json' \
-d '{
"message": {
"token": "DEVICE_TOKEN",
"notification": {
"title": "Hello",
"body": "World"
}
}
}'
import { PushNotifications } from '@capacitor/push-notifications';
// Create channel
await PushNotifications.createChannel({
id: 'messages',
name: 'Messages',
description: 'Message notifications',
importance: 5, // Max importance
visibility: 1, // Public
sound: 'notification.wav',
vibration: true,
lights: true,
lightColor: '#FF0000',
});
// Delete channel
await PushNotifications.deleteChannel({ id: 'old-channel' });
// List channels
const channels = await PushNotifications.listChannels();
// Subscribe to topic
await PushNotifications.addListener('registration', async () => {
// Subscribe to topics based on user preferences
const messaging = getMessaging();
await subscribeToTopic(messaging, 'news');
await subscribeToTopic(messaging, 'promotions');
});
// ios/App/NotificationService/NotificationService.swift
import UserNotifications
class NotificationService: UNNotificationServiceExtension {
override func didReceive(
_ request: UNNotificationRequest,
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
) {
guard let mutableContent = request.content.mutableCopy() as? UNMutableNotificationContent else {
contentHandler(request.content)
return
}
// Add image
if let imageUrl = request.content.userInfo["image"] as? String,
let url = URL(string: imageUrl) {
downloadImage(url: url) { attachment in
if let attachment = attachment {
mutableContent.attachments = [attachment]
}
contentHandler(mutableContent)
}
} else {
contentHandler(mutableContent)
}
}
}
// Handle action buttons
PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
switch (action.actionId) {
case 'reply':
// Handle reply action
const input = action.inputValue;
sendReply(input);
break;
case 'dismiss':
// Handle dismiss
break;
default:
// Handle tap
navigateToContent(action.notification.data);
}
});
// Server-side: Send data-only message
{
"to": "DEVICE_TOKEN",
"data": {
"type": "sync",
"action": "refresh"
}
// No "notification" key = data-only
}
// android/app/src/main/java/.../FirebaseService.kt
class FirebaseService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
// Handle data message in background
message.data["type"]?.let { type ->
when (type) {
"sync" -> performBackgroundSync()
"update" -> checkForUpdates()
}
}
}
}
import { LocalNotifications } from '@capacitor/local-notifications';
// Show local notification when in foreground
PushNotifications.addListener('pushNotificationReceived', async (notification) => {
await LocalNotifications.schedule({
notifications: [
{
id: Date.now(),
title: notification.title || '',
body: notification.body || '',
extra: notification.data,
},
],
});
});
async function requestNotificationPermission() {
const { receive } = await PushNotifications.checkPermissions();
if (receive === 'prompt') {
// Show explanation first
const shouldRequest = await showPermissionExplanation();
if (shouldRequest) {
const result = await PushNotifications.requestPermissions();
return result.receive === 'granted';
}
return false;
}
if (receive === 'denied') {
// Guide user to settings
showSettingsPrompt();
return false;
}
return receive === 'granted';
}
// Handle token refresh
PushNotifications.addListener('registration', async (token) => {
const oldToken = await getStoredToken();
if (oldToken !== token.value) {
// Token changed, update server
await updateServerToken(oldToken, token.value);
await storeToken(token.value);
}
});
PushNotifications.addListener('registrationError', (error) => {
console.error('Push registration failed:', error);
// Log to analytics
analytics.logEvent('push_registration_failed', {
error: error.error,
});
// Retry with backoff
scheduleRetry();
});
| Issue | Solution |
|---|---|
| No token | Check permissions, network |
| Foreground only | Implement background handler |
| Delayed delivery | Use high priority, data-only |
| No sound | Configure notification channel |
| Badge not updating | Set badge in payload |
Weekly Installs
69
Repository
GitHub Stars
18
First Seen
Feb 6, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
gemini-cli68
opencode66
github-copilot64
codex64
kimi-cli62
amp62
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
118,000 周安装
AI产品开发实战指南:LLM生产部署、提示词优化与安全防护最佳实践
465 周安装
性能剖析指南:Lighthouse审计、核心网页指标优化与运行时性能分析
462 周安装
skill-creator:AI CLI技能自动化创建工具,遵循Anthropic最佳实践,支持Copilot/Claude/Codex
463 周安装
gog - Google Workspace CLI 命令行工具:高效管理Gmail和Calendar
459 周安装
iOS 17+ SwiftUI MapKit 与 CoreLocation 开发指南:地图、定位、地理围栏
461 周安装
RAG工程师技能详解:检索增强生成系统架构与最佳实践
466 周安装