Menjalankan tugas latar belakang dan mengirim push notification: WorkManager & foreground services di Android, BGTask di iOS, FCM & APNs sebagai jalur pengiriman, serta pola deep link dari notifikasi untuk Fitku

Aplikasi yang baik bukan hanya merespons — ia juga bekerja saat tidak dibuka. Di episode 14 ini kita belajar background tasks & push notifications: mengirim pengingat workout, menyinkronkan data di malam hari, dan menampilkan notifikasi dari server. Ini fitur yang sangat memengaruhi retensi pengguna, tapi juga salah satu area paling rumit karena kedua platform membatasi latar belakang dengan ketat.
Mengapa rumit? Karena OS membenci aplikasi yang menghabiskan baterai diam-diam. Android dan iOS punya kebijakan berbeda, dan melanggar batasannya berujung pada aplikasi dibunuh OS atau ditolak review store.
Push notification dikirim oleh server ke device, lewat layanan resmi platform:
Payload notifikasi membawa data + token device:
{
"to": "device_token",
"notification": {
"title": "Waktunya workout!",
"body": "30 menit lari pagi terjadwal."
},
"data": {
"route": "workout/42",
"type": "reminder"
}
}Field data dipakai aplikasi untuk navigasi (deep link dari episode 12) — pengguna mengetuk notifikasi dan langsung dibuka ke layar yang tepat.
class FitkuMessagingService : FirebaseMessagingService() {
override fun onMessageReceived(message: RemoteMessage) {
message.data["route"]?.let { route ->
// tampilkan notifikasi; saat di-tap → navigasi ke route
showNotification(title, body, route)
}
}
}Android 8+ wajib memakai notification channels — pengguna bisa memilih mengatur jenis notifikasi:
val channel = NotificationChannel(
"workout_reminders",
"Pengingat Workout",
NotificationManager.IMPORTANCE_HIGH
).apply { description = "Pengingat jadwal workout harian" }
notificationManager.createNotificationChannel(channel)WorkManager adalah API standar untuk pekerjaan deferred & guaranteed — sinkronisasi, upload, cleanup. Ia bertahan dari restart dan memilih waktu yang efisien:
class SyncWork : Worker() {
override fun doWork(): Result {
return try {
syncPendingWorkouts()
Result.success()
} catch (e: RetryableException) {
Result.retry()
}
}
}
// Jadwalkan periodik (min 15 menit)
val request = PeriodicWorkRequestBuilder<SyncWork>(6, TimeUnit.HOURS)
.setConstraints(Constraints.Builder()
.setRequiredNetworkType(NetworkType.CONNECTED)
.build())
.build()
WorkManager.getInstance(context).enqueueUniquePeriodicWork(
"sync_workouts", ExistingPeriodicWorkPolicy.UPDATE, request
)Untuk tugas yang harus terus jalan dan terlihat (misal melacak lari GPS), gunakan foreground service dengan notifikasi persisten — berperilaku seperti "sedang aktif".
Warning
Android membatasi foreground service dengan izin & persyaratan tertentu (misal FOREGROUND_SERVICE_LOCATION untuk GPS). Jangan menyalahgunakan: service yang tidak sah akan dicabut OS. Sebagian besar kebutuhan sync cukup ditangani WorkManager.
iOS jauh lebih ketat. Pilihan resmi:
class AppRefreshScheduler {
static func schedule() {
let request = BGAppRefreshTaskRequest(identifier: "fitku.refresh")
request.earliestBeginDate = Date(timeIntervalSinceNow: 3600) // 1 jam lagi
try? BGTaskScheduler.shared.submit(request)
}
}
func handleRefresh(task: BGAppRefreshTask) {
task.expirationHandler = { /* batasi kerja saat hampir kadaluarsa */ }
Task {
await syncPendingWorkouts()
task.setTaskCompleted(success: true)
}
}Aturan praktis iOS: lakukan sesedikit mungkin dalam waktu singkat. iOS memberi waktu terbatas sebelum app di-suspend.
import * as Notifications from "expo-notifications";
export async function registerForPush() {
const token = await Notifications.getExpoPushTokenAsync();
await saveDeviceToken(token.data);
}
export async function sendReminderLocal() {
await Notifications.scheduleNotificationAsync({
content: { title: "Waktunya workout!", body: "30 menit lari pagi." },
trigger: { type: Notifications.SchedulableTriggerInputTypes.DAILY, hour: 6, minute: 0 },
});
}Untuk background sync di Expo, gunakan expo-background-task atau EAS; untuk Flutter gunakan firebase_messaging + workmanager package.
Tip
Log semua fase notifikasi: kirim server → sampai FCM/APNs → tampil → di-tap. Ketika "notifikasi tidak muncul", 80% kasus karena payload salah, channel belum dibuat, atau device token kedaluwarsa. Instrumentasi menyelamatkan hari.
Pada episode 14 ini, kalian telah menguasai latar belakang & notifikasi:
expo-notifications, firebase_messaging, workmanager.Di episode 15 selanjutnya kita ukur kualitas aplikasi: Performance & Profiling — rendering jank, memory, battery, dan tools profiling untuk menemukan bottleneck di Fitku. Sampai jumpa!