Notifications
Notifications locales et rappels
Affichez des notifications instantanées ou programmez des rappels qui se déclenchent même application fermée : sur l'appareil, sans serveur
1Ce que cela ajoute#
Votre application peut afficher des notifications Android depuis son propre code, Ă deux niveaux :
- Instantané (niveau 1) : une notification qui apparaît tout de suite, pendant que l'application est ouverte. Idéal pour « téléchargement terminé », « minuteur terminé », etc.
- Rappels programmés (niveau 2) : une notification qui se déclenche à une heure future même quand l'application est FERMÉE, et qui survit à un redémarrage. C'est ce dont ont besoin les applications de rappel, d'habitudes, d'alarme et de médicaments.
Ces fonctions sont 100 % sur l'appareil et hors ligne : pas de serveur, pas de compte OneSignal. (Les notifications push OneSignal sont une fonction distincte pour les messages que VOUS envoyez depuis un serveur.)
2Activez-le dans l'assistant de compilation#
À l'étape 4 (Accès), cochez :
- đź”” Notifications : permet Ă l'application de publier des notifications (ajoute POST_NOTIFICATIONS).
- ⏰ Rappels : ajoute des notifications programmées qui se déclenchent quand l'application est fermée (ajoute l'alarme exacte et la reprogrammation au démarrage). Cocher Rappels active automatiquement Notifications.
Laissez les deux désactivés pour les applications qui n'ont pas besoin de notifications : rien de plus n'est ajouté à votre APK.
3Appelez le pont depuis votre code web#
AppMint expose un pont JavaScript à window.WebToApk. Vérifiez toujours sa présence d'abord : il n'existe que dans l'application installée, votre site continue donc de fonctionner dans un navigateur.
const b = window.WebToApk || null;
// Ask once (Android 13+):
b?.requestNotificationPermission();
// Tier 1 — instant (app open):
b?.showNotification('Saved', 'Your note was saved', '', 'note');
// Tier 2 — scheduled reminder in 1 hour:
b?.scheduleNotification(
'water-1',
'Drink water',
'Time for a glass of water',
String(Date.now() + 60*60*1000),
'daily' // none | minutely | hourly | daily | weekly
);
b?.cancelNotification('water-1');
b?.cancelAllNotifications();
const pending = JSON.parse(b?.getScheduledNotifications() || '[]');4Laissez l'IA le câbler pour vous#
Dans AI App Studio, décrivez simplement ce que vous voulez, par exemple « un rappel pour boire de l'eau toutes les 2 heures » ou « un suivi de médicaments qui me rappelle à 8 h tous les jours ». Quand votre demande mentionne des rappels, des alarmes ou des notifications, AppMint explique automatiquement ce pont à l'IA pour que l'application générée l'utilise correctement (avec une solution de repli élégante quand il n'est pas disponible).
5Votre propre son à la place de celui d'Android par défaut#
Placez un fichier audio dans votre bundle web (mp3, wav, ogg, m4a, flac ou opus) et indiquez son chemin comme son. Cela fonctionne de la même façon pour une notification instantanée et pour un rappel qui se déclenche des jours plus tard, application fermée.
Le fichier est copié au bon endroit lors de la programmation, donc un mauvais nom de fichier renvoie false immédiatement au lieu de devenir le son par défaut à 7 h.
Une règle Android à connaître : le son d'un canal de notification est fixé à la création du canal, donc AppMint crée un canal distinct par son. Changer un son réinitialise donc les propres réglages de ce canal dans l'écran de notifications d'Android : c'est inévitable, et c'est le comportement honnête.
const b = window.WebToApk || null;
// Instant, with your sound:
b?.notify(JSON.stringify({
title: 'Order confirmed',
body: 'Arriving Tuesday',
sound: '/audio/chime.mp3' // a file in YOUR bundle
}));
// Check a sound before you save it in a settings screen:
const ok = b?.prepareNotificationSound('/audio/chime.mp3');
// 'silent' for no sound at all; leave it out for the Android default.6Rappels avec son, images et boutons#
scheduleNotificationEx() accepte tout ce que notify() accepte, plus le moment du déclenchement. Utilisez-le à la place de l'ancien scheduleNotification() à cinq arguments dès que vous voulez plus qu'un titre et un texte.
const b = window.WebToApk || null;
b?.scheduleNotificationEx('dose-1', JSON.stringify({
at: Date.now() + 60*60*1000, // epoch millis
repeat: 'daily', // none|minutely|hourly|daily|weekly
title: 'Time for your dose',
body: 'Vitamin D — 1 tablet',
sound: '/audio/chime.mp3',
actions: [{ id: 'taken', label: 'Taken' }]
}));
// Returns false if the sound file does not exist — check it.7Ouvrir l'application elle-même à une heure précise#
Ajoutez openApp: true et le rappel devient une alerte plein écran : sur un téléphone verrouillé, l'application s'ouvre par-dessus l'écran de verrouillage ; sur un téléphone déverrouillé, elle apparaît sous forme de bannière.
C'est tout ce qu'Android autorise. Une application ne peut pas se lancer silencieusement en arrière-plan (bloqué depuis Android 10), donc toute page qui promet « l'application s'ouvre à 7 h » doit passer par là . Sur Android 14+, l'utilisateur accorde l'alerte application par application ; vérifiez canOpenAppAtTime() et envoyez-le vers l'écran des paramètres si la réponse est « denied ».
Quand l'application s'ouvre ainsi, votre page reçoit un événement appmint:reminder, ce qui lui permet d'exécuter le travail qu'elle ne pouvait pas faire tant qu'elle était fermée.
const b = window.WebToApk || null;
if (b?.canOpenAppAtTime() === 'denied') b?.requestOpenAppPermission();
b?.scheduleNotificationEx('standup', JSON.stringify({
at: tomorrowAt9am, repeat: 'daily',
title: 'Stand-up', body: 'Daily sync starts now',
sound: '/audio/alarm.mp3',
openApp: true
}));
window.addEventListener('appmint:reminder', e => {
// e.detail = { id: 'standup', overLockScreen: true }
showReminderScreen(e.detail.id);
});8Fiabilité sur de vrais appareils#
Les rappels programmés sont aussi fiables qu'Android le permet :
- Sur Android 12+, une heure exacte exige SCHEDULE_EXACT_ALARM. S'il est désactivé pour votre application, le rappel est armé dans une fenêtre de 10 minutes (plus tard pendant que le téléphone dort), et l'application l'explique une fois à l'utilisateur. Interrogez getAlarmPrecision() (réponse « exact » ou « inexact ») et appelez requestExactAlarms() pour envoyer l'utilisateur vers le réglage. Une application de réveil ou de calendrier peut cocher « Mon application est un réveil ou un calendrier » dans l'assistant : les alarmes exactes sont alors toujours actives (Google Play exige la déclaration d'alarme exacte dans Play Console).
- Certains téléphones (Xiaomi, Samsung, Oppo, etc.) retardent ou arrêtent les alarmes en arrière-plan pour économiser la batterie. L'application l'explique une fois (avec le chemin des limites d'utilisation en arrière-plan de Samsung) et ouvre la liste d'optimisation de la batterie.
- Les rappels sont réarmés automatiquement après un redémarrage ou une mise à jour de l'application.
9Récupérer les utilisateurs qui ont désactivé les notifications#
Beaucoup de personnes appuient sur « Ne pas autoriser » à l'invite de notification d'Android 13, ou l'ignorent, et Android n'affiche cette invite qu'un nombre limité de fois. Ensuite, seuls les paramètres de notification de l'application permettent de les réactiver.
AppMint.enableNotifications() fait ce qu'il faut à partir d'un bouton sur lequel l'utilisateur a appuyé : l'invite d'autorisation tant qu'Android peut encore l'afficher, sinon les paramètres de notification de l'application, et il vous indique le nouvel état au retour de l'utilisateur. getNotificationState() répond « granted », « prompt » (on peut encore demander), « blocked » (seuls les Paramètres peuvent régler cela) ou « unavailable » (la compilation n'a pas de notifications). Affichez votre bannière uniquement pour « prompt » et « blocked », et ne demandez jamais au lancement.
Un bouton de notification push ou de message intégré avec le lien appmint://notifications/enable fait la même chose sans aucun code dans la page.
const A = window.AppMint;
if (A?.enableNotifications) {
const state = await A.getNotificationState();
// 'granted' | 'prompt' | 'blocked' | 'unavailable'
banner.hidden = !(state === 'prompt' || state === 'blocked');
turnOnButton.onclick = async () => {
const r = await A.enableNotifications();
// r = { state, changed, openedSettings }
banner.hidden = r.state === 'granted';
};
}
// Just the settings screen:
A?.openNotificationSettings?.();