Files
MijnBesluit/docs/Meldingen.md
T
2026-09-27 14:21:31 +00:00

149 lines
7.4 KiB
Markdown

# Meldingen op de telefoon
Als er een bericht voor iemand wordt bezorgd, hoort zijn telefoon dat te laten weten - ook als
de app dicht is. Daarvoor is Firebase Cloud Messaging van Google nodig; een andere weg is er op
Android niet.
De applicatie is er klaar voor. Wat er nog moet gebeuren is een Firebase-project aanmaken en
twee bestanden op de juiste plek zetten. Aan de code hoeft niets te veranderen: het csproj gaat
vanzelf aan zodra het eerste bestand er staat.
## Wat er al werkt
| Onderdeel | Waar |
|---|---|
| Toestellen bijhouden | tabel `toestellen`, `MeldingService` |
| Aanmelden vanuit de app | bij elk inloggen en elke hervatte sessie |
| Afmelden bij uitloggen | zodat de volgende gebruiker op die telefoon niet jouw meldingen krijgt |
| Versturen bij bezorging | `MessageService.DeliverAsync` |
| Praten met Google | `FirebasePush`, met een zelfgeschreven ondertekening |
| Opruimen van dode kenmerken | een toestel dat Google niet meer kent wordt meteen afgemeld |
Zonder servicesleutel gebeurt er niets en werkt alles gewoon door - er gaan alleen geen
meldingen uit.
**Wat er bewust níét in een melding staat:** de inhoud. Een melding verschijnt op een scherm dat
ook zichtbaar is als de telefoon op tafel ligt. Er staat alleen dat er iets klaarstaat en van
wie. Daar is een controle voor in de zelftest.
## Stap 1: het Firebase-project
1. Ga naar console.firebase.google.com en maak een project, bijvoorbeeld **MijnBesluit**.
Google Analytics kun je overslaan.
2. Voeg een **Android-app** toe met pakketnaam `nl.mijnbesluit.app` - precies zoals hij in
`MijnBesluit.App.csproj` bij `ApplicationId` staat.
3. Download `google-services.json` en zet hem in `src\MijnBesluit.App\Platforms\Android\`.
Een Play Console-account is hier niet voor nodig; Firebase is gratis en staat los van de
Play Store.
## Stap 2: niets
Dit stond hier vroeger als een handmatige aanpassing van het csproj. Dat is nu niet meer nodig:
in `MijnBesluit.App.csproj` staat een blok dat zichzelf aanzet zodra `google-services.json` er
staat. Het haalt dan het package `Xamarin.Firebase.Messaging` erbij, koppelt het json-bestand,
en zet de schakelaar `FIREBASE` aan die bij de `#if` in `Toestelmeldingen.cs` hoort.
Staat het bestand er niet, dan gebeurt er niets en bouwt het project gewoon. Dat is met opzet:
er is nu geen stap die je een keer kunt overslaan, en het project blijft te bouwen op een machine
waar dat bestand niet staat.
Het versienummer in dat blok (`125.1.1.1`, bij `net10.0-android`) moet passen bij de
werkbelasting op je machine. Klaagt de build over versies, kijk dan in NuGet welke bij jouw
.NET-versie hoort en pas alleen dat nummer aan.
In hetzelfde blok staan vijf AndroidX-packages met een versienummer erbij. Die horen niet bij
Firebase zelf, maar lossen een botsing op: Firebase vraagt om oudere `.Ktx`-packages, terwijl
MAUI de bijbehorende basispackages al nieuwer binnenhaalt. Sinds Fragment 1.9.0 zitten de
Kotlin-uitbreidingen in het hoofdpackage, dus kwam dezelfde klasse twee keer binnen en brak de
build bij het dexen (`Type androidx.fragment.app.FragmentManagerKt is defined multiple times`).
Komen de NU1608-waarschuwingen ooit terug, dan heeft een nieuwere MAUI de basispackages weer
opgehoogd: zoek in NuGet de bijpassende `.Ktx`-versie op en hoog die nummers mee op. Weghalen
lost het niet op, dan komt de dubbele klasse terug.
Na het wijzigen van die versies: gooi `src\MijnBesluit.App\obj` en `bin` weg voordat je opnieuw
bouwt. In `obj` staan de uitgepakte Java-bibliotheken van de vorige build, en die worden niet
altijd opgeruimd.
## Stap 3: de servicesleutel op de server
1. In Firebase: **Projectinstellingen > Serviceaccounts > Nieuwe persoonlijke sleutel genereren**.
Er wordt een json-bestand gedownload.
2. Zet dat op de server als `C:\MijnBesluitData\keys\firebase.json`.
3. Zet in `C:\MijnBesluitData\appsettings.secrets.json`:
```json
"Push": {
"ServiceAccountFile": "C:\\MijnBesluitData\\keys\\firebase.json"
}
```
4. `Restart-Service MijnBesluitSocket`.
**Dat bestand is een sleutel tot je Firebase-project.** Bewaar het net zo zorgvuldig als
`masterkey.json` en zet het nooit in de publicatiemap - die wordt bij elke publicatie
overschreven, en erger: dan staat hij in het zip-bestand dat je rondstuurt.
In het logboek van de service staat bij het opstarten of het gelukt is:
```
Meldingen staan aan voor Firebase-project mijnbesluit-...
```
## Stap 4: controleren
1. App opnieuw installeren en inloggen. Android vraagt nu toestemming voor meldingen - die
vraag komt van `Permissions.PostNotifications`, verplicht sinds Android 13.
2. **Ga naar Mijn profiel en druk op "Stuur me een proefmelding".** Dat kan ook op de website,
bij Mijn profiel onder *Meldingen op je telefoon*.
Die knop loopt de hele keten langs en zegt waar het op vastloopt:
| Wat er staat | Wat eraan mankeert |
|---|---|
| "Op de server staat geen servicesleutel voor Firebase" | stap 3 is niet gedaan, of het pad klopt niet |
| "Er is geen toestel aangemeld" | de app heeft geen kenmerk; zie *Als er niets komt* hieronder |
| "Verstuurd naar je toestel" en je ziet niets | meldingen staan op de telefoon zelf uit |
| "Google nam de melding niet aan" | het kenmerk is verlopen; opnieuw inloggen in de app |
| Je ziet de melding | klaar |
Hij gaat alleen naar je eigen toestellen. Iemand anders een melding kunnen sturen zou een manier
zijn om mensen lastig te vallen; daar is een controle voor in de zelftest.
Wil je het echte pad ook een keer zien: zet vanaf de website een bericht voor jezelf klaar met
bezorging **meteen**. De achtergrondtaak van de SocketServer bezorgt het binnen een kwartier, en
dan hoort de melding vanzelf te verschijnen.
## Als er niets komt
* **Geen regel in `toestellen`** - de app krijgt geen kenmerk. Meestal ontbreekt
`google-services.json` in de APK die op het toestel staat (is hij ná het bouwen toegevoegd,
bouw dan opnieuw), of heeft de gebruiker de toestemmingsvraag weggeklikt.
```sql
SELECT id, user_id, platform, naam, laatst_gezien FROM toestellen;
```
* **Wel een regel, geen melding** - kijk in het logboek van de service. Staat er "Google gaf
geen toegangstoken", dan klopt de servicesleutel niet. Staat er "Melding niet afgeleverd",
dan zegt Google waarom.
* **"Verstuurd naar je toestel", maar niets te zien terwijl de app openstaat** - Android zet een
melding alleen zelf in de balk als de app op de achtergrond staat. Staat de app open, dan geeft
Android hem door aan `Meldingsdienst` in `Platforms\Android`, en die toont hem. Ontbreekt die
klasse, of is hij niet als dienst aangemeld, dan verdwijnt de melding geruisloos. Daarom gaan
titel en tekst twee keer mee in het bericht: in het `notification`-deel voor Android zelf, en
in het `data`-deel voor de app. Zie `FirebasePush.StuurAsync`.
* **Werkte eerst, nu niet meer** - het kenmerk van Firebase verandert af en toe vanzelf,
bijvoorbeeld na het terugzetten van een back-up. De app meldt zich daarom bij elke start
opnieuw aan; werkt dat niet, dan komt de app niet langs het inloggen.
## Wat hier nog niet in zit
* **iOS.** Daar loopt het via APNs, met een sleutel uit het Apple Developer Program (€99 per
jaar). Firebase kan dat doorgeven, dus de serverkant blijft hetzelfde.
* **Meldingen bij andere gebeurtenissen.** Nu alleen bij een bezorgd bericht. Een overlijdens-
melding of een uitnodiging zou net zo goed een melding kunnen zijn; de plek om dat aan te
roepen is `MeldingService.StuurAsync`.
* **Instellen per gebruiker.** Wie geen meldingen wil, kan ze nu alleen op het toestel zelf
uitzetten.