# Maui Push Notifications

> >

- **Type:** Skill
- **Install:** `agentstack add skill-davidortinau-maui-skills-maui-push-notifications`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [davidortinau](https://agentstack.voostack.com/s/davidortinau)
- **Installs:** 0
- **Category:** [Agent Skills](https://agentstack.voostack.com/c/agent-skills)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [davidortinau](https://github.com/davidortinau)
- **Source:** https://github.com/davidortinau/maui-skills/tree/main/plugins/maui-skills/skills/maui-push-notifications

## Install

```sh
agentstack add skill-davidortinau-maui-skills-maui-push-notifications
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

# Push Notifications — Gotchas & Best Practices

## Troubleshooting Table

| Issue | Cause | Fix |
|-------|-------|-----|
| Token changes every debug run (Android) | Debug builds regenerate Firebase tokens | Always re-register in `OnNewToken` |
| `HttpClient` requests fail silently | `BaseAddress` missing trailing `/` | Ensure endpoint ends with `/` |
| iOS push won't arrive on simulator | Simulators don't support APNS | Use a **physical iOS device** |
| No notifications on Android 13+ | `POST_NOTIFICATIONS` required (API 33+) | Call `RequestPermissions` in `OnCreate` |
| Notification channel missing (API 26+) | Android requires explicit channel creation | Create channel before sending |
| `SendNotificationAsync` throws for >20 tags | Azure NH tag expression limit | Batch tags in groups of 20 |
| `422` on device registration | Platform string mismatch | Use `"fcmv1"` (not `"gcm"`) and `"apns"` |
| Token empty at `RegisterAsync` | Race condition on cold start | Guard with `IsNullOrWhiteSpace` check |

## Critical Gotchas

### ⚠️ BaseAddress trailing slash

`HttpClient.BaseAddress` **must** end with `/`. Without it, relative URI resolution silently breaks.

```csharp
// ❌ Relative URIs resolve incorrectly
_http = new HttpClient { BaseAddress = new Uri("https://example.com") };

// ✅ Trailing slash required
_http = new HttpClient { BaseAddress = new Uri("https://example.com/") };
```

### ⚠️ Android: Always re-register on token refresh

Firebase tokens regenerate frequently in debug builds. If you skip `OnNewToken`, the backend holds a stale token and pushes silently fail.

```csharp
// ❌ Only registering once at startup
// (token may change later without re-registration)

// ✅ Always re-register in OnNewToken
public override void OnNewToken(string token)
{
    var svc = IPlatformApplication.Current?.Services.GetService();
    if (svc is null) return;
    svc.Token = token;
    _ = svc.RegisterAsync();
}
```

### ⚠️ Android 13+ requires POST_NOTIFICATIONS permission

Without explicitly requesting `POST_NOTIFICATIONS` on API 33+, notifications are silently dropped.

### ⚠️ Azure NH tag expression limit: 20 tags

`SendNotificationAsync` throws if a tag expression references more than 20 tags. Batch into chunks:

```csharp
// ✅ Batch tags to stay under the limit
var batches = request.Tags.Chunk(20);
foreach (var batch in batches)
{
    var tagExpr = string.Join(" || ", batch);
    await _hub.SendFcmV1NativeNotificationAsync(payload, tagExpr, ct);
}
```

### ⚠️ Use "fcmv1" not "gcm"

The legacy `"gcm"` platform string causes `422` errors on device registration. Always use `"fcmv1"` for Android and `"apns"` for iOS.

### ⚠️ iOS simulators cannot receive push notifications

APNS only works on physical iOS devices. Simulators silently ignore push registrations.

## Platform Checklist

### Android
- [ ] `google-services.json` in `Platforms/Android/` with `` in `.csproj`
- [ ] `Xamarin.Firebase.Messaging` NuGet package added (Android-only condition)
- [ ] `POST_NOTIFICATIONS` permission requested on API 33+
- [ ] Notification channel created before first notification (API 26+)
- [ ] `OnNewToken` always calls `RegisterAsync`
- [ ] `FirebaseMessagingService` registered in manifest with `MESSAGING_EVENT` intent filter

### iOS
- [ ] Push Notifications capability enabled in Apple Developer portal
- [ ] APNs key (`.p8`) uploaded to Azure Notification Hub
- [ ] `Entitlements.plist` with `aps-environment` set to `development` or `production`
- [ ] `CodesignEntitlements` set in `.csproj`
- [ ] `RegisterForRemoteNotifications` called on main thread after authorization grant
- [ ] Device token converted to lowercase hex string (no dashes)

### Backend
- [ ] Azure Notification Hub configured with FCM V1 JSON and APNS key
- [ ] `BaseAddress` ends with trailing `/`
- [ ] Tag expressions batched in groups of ≤20
- [ ] Platform strings: `"fcmv1"` and `"apns"` (not legacy values)

## Architecture Overview

```
MAUI app → ASP.NET Core backend → Azure Notification Hub → FCM / APNS → device
```

See `references/push-notifications-api.md` for full implementation templates.

## Source & license

This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [davidortinau](https://github.com/davidortinau)
- **Source:** [davidortinau/maui-skills](https://github.com/davidortinau/maui-skills)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** no
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/skill-davidortinau-maui-skills-maui-push-notifications
- Seller: https://agentstack.voostack.com/s/davidortinau
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
