Flutter & Mobil İle İleri Düzey Yerel Bildirim Zamanlayıcı Nasıl Yapılır?

Flutter & Mobil İle İleri Düzey Yerel Bildirim Zamanlayıcı Nasıl Yapılır?
Flutter & Mobil İle İleri Düzey Yerel Bildirim Zamanlayıcı Nasıl Yapılır?

Ön Hazırlık ve Gereksinimler

Projeye başlamadan önce geliştirme ortamınızın güncel olduğundan emin olmalısınız. 2026 yılı itibarıyla Flutter 3.x+ sürümlerini kullanmanız, kütüphane uyumluluğu ve performans açısından kritiktir. İhtiyacımız olan temel paket flutter_local_notifications kütüphanesidir.

Projenizin pubspec.yaml dosyasına gerekli bağımlılıkları ekleyerek işe başlayın:

dependencies:
  flutter:
    sdk: flutter
  flutter_local_notifications: ^18.0.0
  timezone: ^0.9.4

Bu paketler, bildirimlerin yerel zaman dilimlerine göre doğru şekilde tetiklenmesini sağlar. Özellikle timezone paketi, bildirimlerin sunucu saati yerine cihazın yerel saatine göre planlanması için zorunludur.

Bildirim Servisinin Yapılandırılması

Bildirimleri yönetmek için merkezi bir sınıf oluşturmak, kodun sürdürülebilirliğini artırır. İlk adımda, bildirim eklentisini başlatmalı ve gerekli izinleri yapılandırmalıyız. Android tarafında AndroidManifest.xml dosyasına gerekli izinleri eklemeyi unutmayın.

import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:timezone/data/latest_all.dart' as tz;

class NotificationService {
  final FlutterLocalNotificationsPlugin _plugin = FlutterLocalNotificationsPlugin();

  Future init() async {
    const AndroidInitializationSettings androidSettings = 
        AndroidInitializationSettings('@mipmap/ic_launcher');
    const InitializationSettings settings = InitializationSettings(android: androidSettings);
    await _plugin.initialize(settings);
    tz.initializeTimeZones();
  }
}

Bu kod bloğu, uygulamanızın bildirim sistemini başlatır. @mipmap/ic_launcher parametresi, bildirimde görünecek olan ikonunuzu temsil eder.

İleri Düzey Zamanlama Stratejileri

Basit tek seferlik bildirimlerin ötesine geçmek için zonedSchedule metodunu kullanırız. Bu metot, belirli bir tarih ve saatte, hatta tekrarlayan aralıklarla bildirim göndermenize olanak tanır. İleri düzey senaryolarda, bildirimlerin kullanıcıyı rahatsız etmemesi için "bildirim kanalları" (Notification Channels) kullanmak önemlidir.

import 'package:timezone/timezone.dart' as tz;

Future scheduleNotification(int id, String title, String body, DateTime date) async {
  await _plugin.zonedSchedule(
    id,
    title,
    body,
    tz.TZDateTime.from(date, tz.local),
    const NotificationDetails(
      android: AndroidNotificationDetails(
        'gorev_kanali', 'Görev Hatırlatıcı',
        importance: Importance.max,
        priority: Priority.high,
      ),
    ),
    uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
    androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
  );
}

Burada kullanılan androidScheduleMode.exactAllowWhileIdle parametresi, cihaz güç tasarrufu modunda olsa bile bildirimin tam zamanında iletilmesini sağlar.

Bildirim Yöntemleri Karşılaştırma Tablosu

Yöntem Avantajı Dezavantajı
Tek Seferlik (Schedule) Basit ve hızlı kurulum Esneklik düşük
Tekrarlayan (Daily/Weekly) Otomatik periyot yönetimi Özelleştirme kısıtlı
Zoned Schedule (İleri) Tam kontrol ve kesin zamanlama Karmaşık konfigürasyon

Bildirim İzinleri ve Güvenlik Uyarıları

Android 13 ve üzeri sürümlerde, bildirim göndermek için çalışma zamanı izni almanız zorunludur. Kullanıcıdan izin almadan bildirim göndermeye çalışmak, uygulamanızın çökmesine veya bildirimlerin sistem tarafından engellenmesine neden olur.

import 'package:permission_handler/permission_handler.dart';

Future requestNotificationPermission() async {
  if (await Permission.notification.isDenied) {
    await Permission.notification.request();
  }
}

Kritik Güvenlik Uyarısı: Bildirim içeriklerinde asla hassas kullanıcı verilerini (şifre, TC kimlik no, kredi kartı bilgisi) açık metin olarak göndermeyin. Bildirimler sistem tarafından okunabilir olduğundan, veri sızıntılarına yol açabilir. Sadece bildirim ID'sini gönderip, veriyi uygulama içinden çekmek en güvenli yöntemdir.

Bildirimleri Yönetme ve İptal Etme

Zamanlanmış bir bildirimi güncellemek veya iptal etmek, kullanıcı deneyimi açısından kritiktir. Örneğin, kullanıcı bir görevi tamamladığında, o göreve ait hatırlatıcının iptal edilmesi gerekir.

Future cancelNotification(int id) async {
  await _plugin.cancel(id);
}

Future cancelAllNotifications() async {
  await _plugin.cancelAll();
}

Bu metotlar, uygulama içinde kullanıcı aksiyonlarına göre bildirimleri temizlemenizi sağlar. cancelAll() metodu, uygulamanın önbelleğini temizlemek veya kullanıcı ayarlarını sıfırlamak için kullanılabilir.

Sıkça Sorulan Sorular

Bildirimlerim neden bazen geç geliyor?

Android'in "Doze Mode" (uyku modu) özelliği, pil ömrünü korumak için arka plan görevlerini kısıtlar. AndroidScheduleMode.exactAllowWhileIdle kullanarak bu kısıtlamayı aşabilirsiniz.

İOS tarafında bildirimler neden görünmüyor?

İOS için DarwinInitializationSettings yapılandırmasını yapmalı ve Apple Developer hesabınızdan "Push Notifications" yetkisini aktif etmelisiniz.

Bir bildirim ID'sini nasıl dinamik yönetebilirim?

Veritabanınızdaki (SQLite veya Hive) benzersiz kayıt ID'lerini bildirim ID'si olarak kullanın. Böylece her bildirimi eşsiz bir şekilde güncelleyebilirsiniz.

Bildirim tıklandığında uygulamanın belirli bir sayfaya gitmesini nasıl sağlarım?

onDidReceiveNotificationResponse callback fonksiyonunu kullanarak bildirim tıklandığında gelen payload bilgisini okuyabilir ve Navigator ile yönlendirme yapabilirsiniz.

Bildirimler uygulama kapalıyken çalışır mı?

Evet, yerel bildirimler işletim sistemi seviyesinde planlandığı için uygulamanız tamamen kapalı olsa bile tetiklenir.

Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamında bildirimlerin zamanlama doğruluğu, cihazın donanım üreticisi (OEM) kısıtlamalarına bağlı olarak değişiklik gösterebilir.

Bildirimlerde Performans Optimizasyonu ve Bellek Yönetimi

İleri düzey bildirim sistemlerinde, özellikle periyodik bildirimlerin yoğun olduğu uygulamalarda bellek yönetimi kritik bir rol oynar. Her bildirim zamanlayıcısı, arka planda bir kaynak tüketir. Eğer uygulamanızda yüzlerce dinamik bildirim oluşturuyorsanız, bu bildirimlerin ID yönetimini bir veritabanı (örneğin sqflite veya hive) üzerinden takip etmek, bellek sızıntılarını önlemek için en sağlıklı yöntemdir.

Performansı artırmak için şu stratejileri uygulayabilirsiniz:

  • Toplu İptal İşlemleri: Kullanıcı ayarları değiştirdiğinde veya oturumu kapattığında, cancelAll() yerine belirli bir kategoriye ait ID aralıklarını temizleyin.
  • Zaman Damgası Kontrolü: Bildirimleri planlamadan önce, geçmiş bir tarihe ait olup olmadıklarını kontrol ederek gereksiz işlem yükünü azaltın.
  • İzolasyon: Bildirim tetiklendiğinde çalışan kod bloklarını (callback), uygulamanın ana UI thread'ini yormayacak şekilde optimize edin.

Bildirim Hata Ayıklama (Debugging) ve Test Süreçleri

Bildirimlerin cihaz üzerinde tetiklenip tetiklenmediğini anlamak bazen zor olabilir. Özellikle emülatörler, gerçek cihazlardaki "Doze Mode" (pil tasarruf modu) kısıtlamalarını tam yansıtmaz. Test sürecinde şu adımları izleyerek hata ayıklama yapabilirsiniz:

  1. Log Kaydı: Bildirim planlandığı anda log ekranına ID, zaman ve içerik bilgilerini yazdırın.
  2. Anlık Test: Zamanlayıcıyı test etmek için tz.TZDateTime.now().add(const Duration(seconds: 5)) gibi kısa süreli tetikleyiciler kullanın.
  3. ADB Komutları: Android cihazlarda bildirimlerin durumunu kontrol etmek için terminal üzerinden şu komutu kullanabilirsiniz:
adb shell dumpsys notification

Bu komut, cihazda aktif olan tüm bildirim kanallarını ve bekleyen (pending) bildirimleri listeler. Eğer bildiriminiz bu listede görünmüyorsa, zamanlayıcıda bir mantık hatası veya izin sorunu yaşıyor olabilirsiniz.

Örnek Senaryo: İlaç Hatırlatıcı Uygulaması

Bir ilaç hatırlatıcı uygulamasında, kullanıcının ilacını alıp almadığını takip etmek için bildirimlere "Aksiyon Butonları" eklemek, kullanıcı deneyimini doğrudan etkiler. Aşağıdaki kod bloğu, bildirim üzerine "İçtim" butonu eklemek için gerekli yapılandırmayı gösterir:

const DarwinNotificationDetails iosDetails = DarwinNotificationDetails(
  categoryIdentifier: 'ilac_hatirlatici_kategori',
);

const AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
  'kanal_id',
  'İlaç Hatırlatıcı',
  actions: [
    AndroidNotificationAction('id_ictim', 'İlacımı İçtim', showsUserInterface: false),
  ],
);

const NotificationDetails platformDetails = NotificationDetails(
  android: androidDetails,
  iOS: iosDetails,
);

await flutterLocalNotificationsPlugin.show(
  0,
  'İlaç Zamanı!',
  'Lütfen ilacınızı almayı unutmayın.',
  platformDetails,
);

Bu yapı sayesinde, kullanıcı bildirim panelinden uygulamaya girmeden "İlacımı İçtim" butonuna basabilir ve siz de onDidReceiveNotificationResponse callback'i üzerinden bu aksiyonu yakalayarak veritabanınızda ilgili ilacı "alındı" olarak işaretleyebilirsiniz.

Sonuç

Flutter ile ileri düzey bildirim zamanlama, uygulamanızın profesyonellik seviyesini bir üst noktaya taşır. Bu rehberde, flutter_local_notifications paketinin temel kullanımından, zaman dilimi yönetimine ve bildirim izinlerinin güvenli şekilde alınmasına kadar kritik adımları inceledik. Bir sonraki adım olarak, bildirimlerinize "Action Buttons" (hızlı aksiyon butonları) ekleyerek, kullanıcıların uygulamayı açmadan bildirim üzerinden işlem yapmasını sağlamayı deneyebilirsiniz.

Bu yazıya tepkinizi paylaşın:
Zeynep Kaya

Yaşam kalitesini artıran hızlı ve etkili yöntemler üzerine içerik geliştiriyorum. Detaylara önem veren, çözüm odaklı rehberlerin öncüsüyüm.

Yorumlar (0)

Yorum Yaz