105 lines
4.5 KiB
C#
105 lines
4.5 KiB
C#
#if FIREBASE
|
|
using Android.App;
|
|
using Android.Content;
|
|
using AndroidX.Core.App;
|
|
using Firebase.Messaging;
|
|
|
|
namespace MijnBesluit.App;
|
|
|
|
/// <summary>
|
|
/// Vangt meldingen op die binnenkomen terwijl de app openstaat.
|
|
///
|
|
/// Android zet een melding alleen zelf in de balk als de app op de achtergrond staat. Staat hij
|
|
/// open, dan geeft Android hem door aan deze dienst en gebeurt er verder niets - tenzij we hem
|
|
/// hier zelf tonen. Dat was precies het geval waarin de proefmelding "verstuurd" heette en er
|
|
/// op de telefoon niets te zien was.
|
|
///
|
|
/// De tekst komt uit het data-deel van het bericht en niet uit het notification-deel. Beide
|
|
/// staan erin (zie FirebasePush), maar het data-deel is het stuk waar de naamgeving in de
|
|
/// Android-binding niet per versie verschilt.
|
|
/// </summary>
|
|
[Service(Exported = false)]
|
|
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
|
|
public class Meldingsdienst : FirebaseMessagingService
|
|
{
|
|
/// <summary>
|
|
/// Het kanaal waarop deze meldingen binnenkomen. Vanaf Android 8 hoort elke melding bij een
|
|
/// kanaal, en kan de gebruiker per kanaal zeggen hoe opdringerig het mag zijn. De naam staat
|
|
/// ook in AndroidManifest.xml, zodat meldingen die binnenkomen terwijl de app dicht is op
|
|
/// hetzelfde kanaal terechtkomen en niet onder "Overig".
|
|
/// </summary>
|
|
public const string Kanaal = "mijnbesluit-berichten";
|
|
|
|
/// <summary>
|
|
/// Maakt het kanaal aan als het er nog niet is. Mag zo vaak aangeroepen worden als je wilt;
|
|
/// Android werkt een bestaand kanaal dan alleen bij. Gebeurt bij het starten van de app, want
|
|
/// een melding die binnenkomt terwijl de app dicht is heeft het kanaal al nodig.
|
|
/// </summary>
|
|
public static void MaakKanaal(Context context)
|
|
{
|
|
if (!OperatingSystem.IsAndroidVersionAtLeast(26)) return;
|
|
|
|
var kanaal = new NotificationChannel(Kanaal, "Berichten", NotificationImportance.High)
|
|
{
|
|
Description = "Laat weten dat er iets voor je klaarstaat. Wat erin staat komt er nooit bij te staan."
|
|
};
|
|
|
|
var beheer = (NotificationManager?)context.GetSystemService(Context.NotificationService);
|
|
beheer?.CreateNotificationChannel(kanaal);
|
|
}
|
|
|
|
public override void OnMessageReceived(RemoteMessage bericht)
|
|
{
|
|
var gegevens = bericht.Data;
|
|
|
|
gegevens.TryGetValue("titel", out var titel);
|
|
gegevens.TryGetValue("tekst", out var tekst);
|
|
|
|
if (string.IsNullOrWhiteSpace(titel)) titel = "MijnBesluit";
|
|
if (string.IsNullOrWhiteSpace(tekst)) tekst = "Er staat iets voor je klaar.";
|
|
|
|
Toon(this, titel, tekst);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Firebase geeft een toestel af en toe een nieuw kenmerk. Het oude werkt dan niet meer.
|
|
/// De app meldt zich bij elke aanmelding opnieuw aan met het kenmerk van dat moment, dus dat
|
|
/// herstelt zichzelf zodra je weer inlogt. Zolang je ingelogd blijft kan er een melding
|
|
/// tussendoor vallen; dat is bewust niet hier opgelost, want hier is geen verbinding met de
|
|
/// server en geen sleutel om mee te praten.
|
|
/// </summary>
|
|
public override void OnNewToken(string kenmerk) => base.OnNewToken(kenmerk);
|
|
|
|
private static void Toon(Context context, string titel, string tekst)
|
|
{
|
|
MaakKanaal(context);
|
|
|
|
// Aantikken opent de app. SingleTop, zodat je niet een tweede keer hetzelfde scherm
|
|
// opent bovenop het scherm waar je al was.
|
|
var openen = new Intent(context, typeof(MainActivity));
|
|
openen.AddFlags(ActivityFlags.ClearTop | ActivityFlags.SingleTop);
|
|
|
|
var tik = PendingIntent.GetActivity(context, 0, openen,
|
|
PendingIntentFlags.UpdateCurrent | PendingIntentFlags.Immutable);
|
|
|
|
// ApplicationInfo.Icon en niet een eigen tekening: dat is een nummer dat Android zelf
|
|
// bijhoudt, dus hier hoeft geen tweede plaatje bijgehouden te worden dat kan ontbreken.
|
|
var melding = new NotificationCompat.Builder(context, Kanaal)
|
|
.SetContentTitle(titel)
|
|
.SetContentText(tekst)
|
|
.SetStyle(new NotificationCompat.BigTextStyle().BigText(tekst))
|
|
.SetSmallIcon(context.ApplicationInfo!.Icon)
|
|
.SetAutoCancel(true)
|
|
.SetPriority((int)NotificationPriority.High)
|
|
.SetContentIntent(tik)
|
|
.Build();
|
|
|
|
// Elk bericht een eigen nummer, anders vervangt de tweede melding de eerste.
|
|
NotificationManagerCompat.From(context).Notify(Volgnummer(), melding);
|
|
}
|
|
|
|
private static int _laatste;
|
|
private static int Volgnummer() => Interlocked.Increment(ref _laatste);
|
|
}
|
|
#endif
|