Setup push notification dengan `@capacitor/push-notifications`: registrasi token FCM/APNs, payload handling, dan tap-to-navigate. Serta notifikasi lokal terjadwal dengan aksi tombol dan test push end-to-end.

Setelah di episode 7 kita menguasai Geolocation dan Preferences, pada episode ini kita masuk ke salah satu fitur mobile paling powerful: push notification dan notifikasi lokal. Notifikasi adalah cara paling efektif untuk menarik user kembali ke aplikasi — dan di mobile, notifikasi jauh lebih efektif daripada email atau in-app banner.
Mengapa push notification penting? Karena aplikasi mobile yang tidak punya notifikasi cenderung dilupakan user. Push notification memungkinkan kalian mengirim pesan real-time ke perangkat user bahkan saat aplikasi tidak aktif.
Dua layanan push notification utama:
Capacitor menggunakan @capacitor/push-notifications yang menjembatani kedua layanan ini.
npm install @capacitor/push-notifications
npx cap syncappId kalian.google-services.json dan taruh di android/app/.android/build.gradle dan android/app/build.gradle.import { PushNotifications } from '@capacitor/push-notifications';
async function registerPush() {
// Minta permission
const permission = await PushNotifications.requestPermissions();
if (permission.receive !== 'granted') {
console.log('Push notification permission denied');
return;
}
// Register untuk push
await PushNotifications.register();
// Dapatkan token
PushNotifications.addListener('registration', (token) => {
console.log('Push token:', token.value);
// Kirim token ke server kalian
sendTokenToServer(token.value);
});
// Handle error
PushNotifications.addListener('registrationError', (err) => {
console.error('Registration error:', err.error);
});
}import { PushNotifications } from '@capacitor/push-notifications';
// Saat notifikasi diterima (app di foreground)
PushNotifications.addListener('pushNotificationReceived', (notification) => {
console.log('Notification received:', notification.title, notification.body);
// Tampilkan in-app banner atau update badge
});
// Saat user tap notifikasi
PushNotifications.addListener('pushNotificationActionPerformed', (action) => {
const data = action.notification.data;
console.log('Notification tapped:', data);
// Navigasi ke konten spesifik
if (data.articleId) {
window.location.href = `/article/${data.articleId}`;
}
});npm install @capacitor/local-notifications
npx cap syncimport { LocalNotifications } from '@capacitor/local-notifications';
async function scheduleNotification() {
await LocalNotifications.requestPermissions();
await LocalNotifications.schedule({
notifications: [
{
title: 'Waktunya minum air!',
body: 'Jangan lupa hidrasi setiap 2 jam.',
id: 1,
schedule: { at: new Date(Date.now() + 7200000) }, // 2 jam lagi
actionTypeId: 'HYDRATION_REMINDER',
extra: { reminderType: 'hydration' },
},
],
});
}import { LocalNotifications } from '@capacitor/local-notifications';
async function scheduleDailyReminder() {
await LocalNotifications.schedule({
notifications: [
{
title: 'Reminder Harian',
body: 'Buka app untuk cek progress hari ini.',
id: 100,
schedule: {
every: { weekday: 1, weekday: 2, weekday: 3, weekday: 4, weekday: 5 },
at: new Date(new Date().setHours(9, 0, 0, 0)), // 09:00 setiap hari kerja
},
},
],
});
}import { LocalNotifications } from '@capacitor/local-notifications';
await LocalNotifications.registerActionTypes({
types: [
{
id: 'TASK_REMINDER',
actions: [
{ id: 'complete', title: 'Selesaikan', foreground: true },
{ id: 'snooze', title: 'Tunda 15 menit', foreground: false },
],
},
],
});
// Kirim notifikasi dengan aksi
await LocalNotifications.schedule({
notifications: [
{
title: 'Task belum selesai',
body: 'Kerjakan "Review PR" sebelum deadline.',
id: 200,
actionTypeId: 'TASK_REMINDER',
schedule: { at: new Date(Date.now() + 3600000) },
},
],
});Untuk testing push notification:
PushNotifications.addListener('registration').Warning
Push notification tidak bisa diuji di iOS Simulator. Gunakan perangkat fisik atau TestFlight untuk testing iOS. Android emulator mendukung push notification.
Pada episode 8 ini, kalian telah memahami:
Di episode 9 selanjutnya, kita akan membahas Deep Links, Universal Links, dan App State — custom scheme vs App Links vs Universal Links, lifecycle events, dan cara membuka konten spesifik dari link eksternal. Sampai jumpa!