Blog FQSoft

Just Simple Code Documentation

Flutter

Flutter Local Notification Android

Faiq Himmah 18 January 2024
[ Gambar Post ]

Setup Android

File : android/app/build.gradle

android {
  defaultConfig {
    multiDexEnabled true
    .......
  }

  compileOptions {
    // Flag to enable support for the new language APIs
    coreLibraryDesugaringEnabled true
    // Sets Java compatibility to Java 8
    sourceCompatibility JavaVersion.VERSION_1_8
    targetCompatibility JavaVersion.VERSION_1_8
  }
}

dependencies {
  coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.2'
}

File: android/build.gradle

buildscript {
   ...

    dependencies {
        classpath 'com.android.tools.build:gradle:7.3.1'
        ...
    }

File: AndroidManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android">
  <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
  <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
  <uses-permission android:name="android.permission.USE_EXACT_ALARM" />
  <application>
    android:label="local_notif"
    ..........
    
    <receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationReceiver" />
    <receiver android:exported="false" android:name="com.dexterous.flutterlocalnotifications.ScheduledNotificationBootReceiver">
      <intent-filter>
          <action android:name="android.intent.action.BOOT_COMPLETED"/>
          <action android:name="android.intent.action.MY_PACKAGE_REPLACED"/>
          <action android:name="android.intent.action.QUICKBOOT_POWERON" />
          <action android:name="com.htc.intent.action.QUICKBOOT_POWERON"/>
      </intent-filter>
    </receiver>
    
    <activity>
      .........................
    </activity>
  </application>
</manifest>

Sumber : https://pub.dev/packages/flutter_local_notifications#-android-setup

Setup Class & Simple Test

Disini saya membuat class MyNotif dengan constructor dibawah ini

class MyNotif{
    final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
    AndroidNotificationDetails? androidPlatformChannelSpecifics;
  
    MyNotif(){
      var initSettingAndroid = const AndroidInitializationSettings('@mipmap/launcher_icon');
      var initSettings = InitializationSettings(android: initSettingAndroid);
      androidPlatformChannelSpecifics = const AndroidNotificationDetails(
          'wiridku_channel_653', // Change this to a unique ID
          'Local Notif Wiridku',
          icon: "@mipmap/launcher_icon",
          importance: Importance.high,
          priority: Priority.high,
      );
      tz.initializeTimeZones();
      tz.setLocalLocation(tz.getLocation("Asia/Jakarta"));
      flutterLocalNotificationsPlugin.initialize(initSettings,
        onDidReceiveNotificationResponse: (payload) async{
          if(MyApp.navigatorKey.currentContext!=null){
            print("Open Notif");
            Wirid w = await WiridService().getWiridById(payload.payload);
            Navigator.push(MyApp.navigatorKey.currentContext!, 
              MaterialPageRoute(builder: (context) => FlipPage(wiridObj: w,))
            );
          }else{
            print("context Null");
          }
          
        }
      );
    }
  ....................................
  }

Agar proses navigasi bisa berjalan dimana saat notifikasi di klik bisa diarahkan ke halaman tujuan. maka pada file main.dart tambahkan kode dibawah ini yang ditandai dengan double slash

class MyApp extends StatelessWidget {
  static final navigatorKey = GlobalKey<NavigatorState>(); 
  const MyApp({super.key}); //<- TAMBAHKAN KODE INI
  
  @override
  Widget build(BuildContext context){
    return MaterialApp(
      title: 'Wiridku',
      navigatorKey: MyApp.navigatorKey, //<- TAMBAHKAN KODE INI
      theme: ThemeData(
        ....................................
      ),
      home: MyHomePage(title: 'Wiridku'),
    );
  }
     

}

Buat method untuk request permission notifikasi

Future<bool> getNotifPermission() async{
    bool? isPermission = await flutterLocalNotificationsPlugin.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()?.requestNotificationsPermission();
    return isPermission??false;
  }

Sebagai permulaan kita akan buat simple notification untuk memastikan setup sudah dilakukakan denga benar.

Future<int> showSimpleNotif() async{
    if(await getNotifPermission()==true){
      // init();
      await FlutterLocalNotificationsPlugin().show(
          0,
          'Hello, Flutter!',
          'This is your first local notification.',
          NotificationDetails(android: androidPlatformChannelSpecifics)
        );
    }
    return 1;
  }

Selanjutnya menbuat simple notification berbasis jadwal

Future<int> showSimpleSchedule() async{
    if(await getNotifPermission()==true){
      await flutterLocalNotificationsPlugin.zonedSchedule(
        0,
        'Hello, Flutter! Schedule',
        'Scheduled Body',
        tz.TZDateTime.now(tz.local).add(const Duration(seconds: 5)),
        NotificationDetails(android: androidPlatformChannelSpecifics),
        androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
        uiLocalNotificationDateInterpretation:
            UILocalNotificationDateInterpretation.absoluteTime);
    }
    return 1;
  }

Setup Notifikasi Berbasis Jadwal Rutin

Buat dua method seeperti dibawah ini. nantinya kedua function ini akan digunakan pada notifikasi daily, weekly dan monthly

tz.TZDateTime _nextInstanceOfHour(int hour,int minute) {
    final tz.TZDateTime now = tz.TZDateTime.now(tz.local);
    tz.TZDateTime scheduledDate = tz.TZDateTime(tz.local, now.year, now.month, now.day, hour, minute);
    if (scheduledDate.isBefore(now)) {
      scheduledDate = scheduledDate.add(const Duration(days: 1));
    }
    return scheduledDate;
  }

  tz.TZDateTime _nextInstanceOfDayHour(int day,int hour,int minute) {
    tz.TZDateTime scheduledDate = _nextInstanceOfHour(hour, minute);
    while (scheduledDate.weekday != day) {
      scheduledDate = scheduledDate.add(const Duration(days: 1));
    }
    return scheduledDate;
  }

Notifikasi Daily/Harian di Setiap jam Tertentu

Future<void> scheduleDailyHour(int id,String payload,String title,String pesan,int hour,int minute) async {
    if(await getNotifPermission()==true){
      await flutterLocalNotificationsPlugin.zonedSchedule(
          id,title,pesan,
          _nextInstanceOfHour(hour,minute),
          NotificationDetails(android: androidPlatformChannelSpecifics),
          androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
          uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
          matchDateTimeComponents: DateTimeComponents.time,
          payload: payload
      );
    }
  }

Notifikasi Weekly/Mingguan di Setiap Hari & Jam Tertentu

Future<void> scheduleWeeklyHour(int id,String payload,String title,String pesan,int day,int hour,int minute) async {
    if(await getNotifPermission()==true){
      await flutterLocalNotificationsPlugin.zonedSchedule(
          id,title,pesan,
          _nextInstanceOfDayHour(day,hour,minute),
          NotificationDetails(android: androidPlatformChannelSpecifics),
          androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
          uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
          matchDateTimeComponents: DateTimeComponents.dayOfWeekAndTime,
          payload: payload
      );
    }
  }

Notifikasi Monthly/Bulanan di Setiap Hari & Jam Tertentu

Future<void> scheduleMonthlyDayHour(int id,String title,String pesan,int day,int hour,int minute) async {
    if(await getNotifPermission()==true){
      await flutterLocalNotificationsPlugin.zonedSchedule(
        id,
        title,
        pesan,
        _nextInstanceOfDayHour(day,hour,minute),
        NotificationDetails(android: androidPlatformChannelSpecifics),
        androidScheduleMode: AndroidScheduleMode.exactAllowWhileIdle,
        uiLocalNotificationDateInterpretation: UILocalNotificationDateInterpretation.absoluteTime,
        matchDateTimeComponents: DateTimeComponents.dayOfMonthAndTime
      );
    }
  }

Cek Active Notifikasi

Future<List<ActiveNotification>> cekActive() async{
    debugPrint("Notif Aktif");
    List<ActiveNotification> list = await flutterLocalNotificationsPlugin.getActiveNotifications();
    return list;
  }

Menghapus Semua Notifikasi

Future<void> cancelAll() async {
    await flutterLocalNotificationsPlugin.cancelAll();
}

Menghapus Notifikasi By ID

Future<void>deleteByID(Wirid w) async{
    if (w.wiridId != "0"){
      Map<String,dynamic> objIstiqomah = jsonDecode(w.istiqomah);
      List<dynamic> listID = objIstiqomah['istiqomahId'];
      for (var i = 0; i < listID.length; i++) {
        await flutterLocalNotificationsPlugin.cancel(listID[i]);
      } 
    }
  }

Kode Pengujian

Future<void> showNotification() async {
    MyNotif notif = MyNotif();
    await notif.showSimpleNotif();
    // await notif.showSimpleSchedule();
    // await notif.scheduleDailyHour(0, "Wirid 1", "Saatnya Wirid", 2, 38);
    // await notif.scheduleWeeklyHour(0, "Wirid", "Saatnya Wirid",[4] ,2, 1);
    
    // await debugCancelNotif(notif, 0);

  }

Panggil method diatas di tombol onPressed dsb.

Untuk File class MyNotif bisa didownload disini

flutter notifikasi notification