168 lines
6.6 KiB
Markdown
168 lines
6.6 KiB
Markdown
# Catatan Lengkap Implementasi Notifikasi (TelurKu)
|
|
|
|
Dokumen ini menjelaskan kenapa sistem notifikasi saat ini berjalan lancar, bagaimana konsep kerjanya, batasannya saat app di-minimize/ditutup, dan apa saja yang perlu dibuat jika ingin dipakai ulang di aplikasi berikutnya.
|
|
|
|
## 1) Ringkasan Kenapa Notifikasi Bisa Berjalan Lancar
|
|
|
|
Sistem notifikasi berjalan baik karena ada kombinasi yang benar antara:
|
|
|
|
1. Inisialisasi service notifikasi sejak awal app startup.
|
|
2. Channel Android sudah dibuat dengan importance tinggi.
|
|
3. Permission notifikasi dan exact alarm diminta secara eksplisit.
|
|
4. Scheduling memakai timezone-aware API (zoned schedule).
|
|
5. Ada fallback jika exact alarm tidak diizinkan (tetap kirim inexact).
|
|
6. Receiver Android untuk scheduled notification + boot completed sudah terpasang.
|
|
7. ID notifikasi harian dibuat stabil dari scheduleKey sehingga update/cancel konsisten.
|
|
|
|
## 2) Arsitektur Notifikasi Saat Ini (di Project Ini)
|
|
|
|
### 2.1 Service Utama
|
|
|
|
- Service utama: [lib/services/notification_service.dart](lib/services/notification_service.dart)
|
|
- Fungsi penting:
|
|
- initialize: setup timezone, init plugin, channel, permissions
|
|
- showInstantNotification: kirim notifikasi langsung
|
|
- scheduleNotification: jadwalkan notifikasi sekali jalan
|
|
- scheduleDailyNotificationAtTime: jadwal harian (repeat per jam yang sama)
|
|
- cancelScheduledNotification/cancelAll/pendingNotifications
|
|
|
|
### 2.2 Titik Inisialisasi App
|
|
|
|
- Inisialisasi dipanggil di startup app non-web: [lib/main.dart](lib/main.dart)
|
|
- Bagian bootstrap juga:
|
|
- memuat data awal,
|
|
- sinkron jadwal aktif,
|
|
- menjadwalkan ulang notifikasi harian,
|
|
- cancel jadwal yang tidak aktif lagi.
|
|
|
|
### 2.3 Trigger Notifikasi dari Data Realtime
|
|
|
|
- Realtime listener panen: [lib/providers/panen_provider.dart](lib/providers/panen_provider.dart)
|
|
- Saat ada record baru Firebase Realtime DB, app membuat notifikasi ringkasan panen (pagi/sore).
|
|
|
|
### 2.4 Trigger Otomatis Berdasarkan Jam Panen
|
|
|
|
- Runtime scheduler 30 detik: [lib/services/panen_runtime_scheduler_service.dart](lib/services/panen_runtime_scheduler_service.dart)
|
|
- Service auto capture panen: [lib/services/panen_auto_capture_service.dart](lib/services/panen_auto_capture_service.dart)
|
|
- Setelah capture, sistem kirim notifikasi summary per jenis panen.
|
|
|
|
### 2.5 Konfigurasi Android yang Wajib
|
|
|
|
- Manifest: [android/app/src/main/AndroidManifest.xml](android/app/src/main/AndroidManifest.xml)
|
|
- Sudah ada:
|
|
- receiver scheduled notification
|
|
- receiver boot completed
|
|
- POST_NOTIFICATIONS
|
|
- SCHEDULE_EXACT_ALARM dan USE_EXACT_ALARM
|
|
- RECEIVE_BOOT_COMPLETED
|
|
|
|
## 3) Perilaku Notifikasi Berdasarkan Kondisi App
|
|
|
|
### 3.1 App Foreground
|
|
|
|
- Notifikasi langsung (instant) akan muncul sesuai konfigurasi plugin/channel.
|
|
|
|
### 3.2 App Minimize / Background
|
|
|
|
- Notifikasi terjadwal tetap bisa tampil jika sudah dijadwalkan sebelumnya.
|
|
- Ini karena alarm dikelola oleh OS, bukan loop UI Flutter.
|
|
|
|
### 3.3 App Ditutup User (swipe away / terminate proses)
|
|
|
|
- Notifikasi lokal terjadwal yang sudah terdaftar umumnya tetap bisa tampil.
|
|
- Tetapi proses Flutter berhenti, artinya:
|
|
- listener realtime Firebase berhenti,
|
|
- runtime scheduler internal berhenti,
|
|
- logic yang butuh eksekusi Dart real-time tidak jalan lagi.
|
|
|
|
### 3.4 App Baru Dinyalakan Ulang / Device Reboot
|
|
|
|
- Dengan boot receiver, jadwal plugin bisa dipulihkan (tergantung platform/plugin).
|
|
- Tetap bagus jika app melakukan resync jadwal saat startup (sudah dilakukan di bootstrap).
|
|
|
|
## 4) Hal Penting: Notifikasi Lokal vs Push Notification
|
|
|
|
### Notifikasi lokal
|
|
|
|
Cocok untuk:
|
|
- reminder berbasis waktu yang sudah diketahui,
|
|
- alarm harian,
|
|
- notifikasi yang bisa dijadwalkan dari dalam app.
|
|
|
|
Keterbatasan:
|
|
- tidak ideal untuk event server real-time saat app benar-benar mati total.
|
|
|
|
### Push notification (FCM/APNs)
|
|
|
|
Diperlukan jika kamu ingin:
|
|
- kirim notif dari server kapan pun,
|
|
- user tetap menerima event baru meskipun app tidak aktif.
|
|
|
|
Kesimpulan praktis:
|
|
- Reminder waktu tetap: lokal notification.
|
|
- Event dari backend/sensor saat app tidak aktif: push notification.
|
|
|
|
## 5) Konsep Implementasi Ulang ke App Berikutnya
|
|
|
|
Urutan implementasi yang direkomendasikan:
|
|
|
|
1. Pasang package:
|
|
- flutter_local_notifications
|
|
- timezone
|
|
- flutter_timezone
|
|
2. Buat service singleton notifikasi (pola seperti NotificationService).
|
|
3. Pada initialize:
|
|
- init timezone,
|
|
- init plugin,
|
|
- create channel Android,
|
|
- request permission notif + exact alarm.
|
|
4. Buat API wrapper:
|
|
- showInstantNotification
|
|
- scheduleOneShot
|
|
- scheduleDaily
|
|
- cancelByKey
|
|
- pending list
|
|
5. Gunakan stable notification ID berbasis key agar update/cancel tidak salah sasaran.
|
|
6. Simpan source of truth jadwal (DB lokal/remote), lalu resync di startup app.
|
|
7. Tambahkan debug screen untuk:
|
|
- test instant notif,
|
|
- test jadwal 30 detik,
|
|
- lihat pending schedule,
|
|
- test exact alarm permission.
|
|
8. Tambahkan Android receivers + permission yang diperlukan.
|
|
9. Uji di beberapa kondisi device (lihat checklist pengujian di bawah).
|
|
10. Jika butuh event server saat app mati, tambahkan FCM backend.
|
|
|
|
## 6) Checklist Pengujian yang Wajib
|
|
|
|
1. Foreground test: instant notif muncul.
|
|
2. Background test: jadwal 30 detik tetap muncul saat app diminimize.
|
|
3. Terminated test: jadwal tetap muncul setelah app diswipe (untuk jadwal yang sudah tercatat).
|
|
4. Reboot test: setelah restart HP, jadwal masih ada atau berhasil resync saat app dibuka.
|
|
5. Exact alarm off test: pastikan fallback inexact tetap bekerja.
|
|
6. Permission denied test: app tidak crash, tampilkan instruksi jelas ke user.
|
|
7. OEM aggressive battery test (Xiaomi/Oppo/Vivo, dsb): validasi behavior nyata.
|
|
|
|
## 7) Batasan Nyata di Android Modern
|
|
|
|
1. Doze/battery optimization bisa menunda notifikasi non-exact.
|
|
2. Exact alarm butuh izin user di banyak device/versi Android.
|
|
3. Sebagian vendor membatasi background process dengan agresif.
|
|
4. Karena itu, selalu sediakan fallback, status pending, dan edukasi user.
|
|
|
|
## 8) Rekomendasi Praktis untuk Produksi
|
|
|
|
1. Pisahkan notifikasi menjadi:
|
|
- reminder terjadwal (lokal),
|
|
- event backend (push).
|
|
2. Simpan mapping scheduleKey -> bisnis ID secara konsisten.
|
|
3. Hindari log print berlebih pada mode produksi.
|
|
4. Tambahkan telemetry sederhana (berapa jadwal aktif, terakhir sync kapan).
|
|
5. Siapkan halaman troubleshooting notifikasi untuk user.
|
|
|
|
## 9) Kesimpulan
|
|
|
|
Notifikasi di project ini sudah berada di jalur yang benar untuk use-case reminder dan summary lokal. Kunci stabilitasnya ada di setup channel + permission + timezone + scheduler yang disinkronkan ulang saat startup.
|
|
|
|
Untuk kebutuhan notifikasi real-time ketika app benar-benar mati dan event datang dari server, kamu harus menambahkan arsitektur push notification (FCM/APNs) di sisi backend.
|