OiO.lk Blog Android flutter local notification action button can't recognize button tap in backgound
Android

flutter local notification action button can't recognize button tap in backgound


send notification with action button from server its showing fine and tap action button works,
but when i killed the app and send notification and tap action button its open app but can’t recognize action button tap its normally open app without print actionid when its happen mean showuserinterface set true otherwise set false to working good printing actionid and trigger api call everything fine,
so i need when action button tap in background app. launch navigate to specific screen

notification service class

import 'dart:convert';
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:get/get.dart';
import 'package:shared_preferences/shared_preferences.dart';

import '../../core/shared_pref_manager.dart';
import '../../features/chat/presentation/getx/call_controller.dart';
import '../domain/entities/action_button.dart';
import '../presentation/constants/app_routes.dart';
import '../presentation/constants/app_texts.dart';

@pragma('vm:entry-point')
void notificationTapBackground(NotificationResponse notificationResponse) {
  print('tapped background');
  print(notificationResponse.actionId);
  handleNotificationTapFunction(notificationResponse);
}

void notificationTapForeground(NotificationResponse notificationResponse) {
  print('tapped foreground');
  handleNotificationTapFunction(notificationResponse);
}

Future acceptOrDeclineCall(String conversation_id, action) async {
  var _token = Get.find<SharedPrefsManager>().getAccessToken();
  if (_token != null) {
    final Dio dio = Dio();
    dio.options.headers['Authorization'] = 'Bearer $_token';
    try {
      final _url =
          "${AppConstants.baseUrl}chat/call/accept_decline/$conversation_id/";
      await dio.post(_url, data: {"action": action});
    } catch (e) {
      print(e);
    }
  }
}

Future handleNotificationTapFunction(
    NotificationResponse notificationResponse) async {
  print(notificationResponse.actionId);
  if (notificationResponse.payload != null) {
    Map<String, dynamic> payload = jsonDecode(notificationResponse.payload!);
    final topic = payload['topic'];
    if (topic == 'call') {
      print(topic);
      await Get.putAsync<SharedPrefsManager>(() async {
        final SharedPreferences sharedPreferences =
            await SharedPreferences.getInstance();

        return SharedPrefsManager(sharedPreferences);
      }, permanent: true);
      var _data = json.decode(payload['data']);
      var conversation_id = _data['conversation_id'];
      var conversation_room_id = _data['conversation_room_id'];
      if (notificationResponse.actionId == 'accept') {
        acceptOrDeclineCall(conversation_id, 'Accept');
        Get.put(CallController(conversation_room_id), permanent: true);
        AppRoute.initial = AppRoute.callScreen;
        Get.key.currentState?.pushNamed(AppRoute.callScreen);
      } else if (notificationResponse.actionId == 'decline') {
        acceptOrDeclineCall(conversation_id, "Decline");
      }
    }
  }
}

class NotificationService {
  final FlutterLocalNotificationsPlugin _flutterLocalNotificationsPlugin =
      FlutterLocalNotificationsPlugin();
  AndroidNotificationChannel channel = const AndroidNotificationChannel(
    'high_importance_channel', // id
    'High Importance Notifications', // title
    description:
        'This channel is used for important notifications.', // description
    importance: Importance.high,
  );
  Future<void> initialize() async {
    _requestPermissions();
    const AndroidInitializationSettings initializationSettingsAndroid =
        AndroidInitializationSettings('@mipmap/ic_launcher');
    const InitializationSettings initializationSettings =
        InitializationSettings(
      android: initializationSettingsAndroid,
      iOS: DarwinInitializationSettings(
        requestAlertPermission: true,
        requestSoundPermission: true,
      ),
    );

    await _flutterLocalNotificationsPlugin.initialize(initializationSettings,
        onDidReceiveBackgroundNotificationResponse: notificationTapBackground,
        onDidReceiveNotificationResponse: notificationTapForeground);
  }

  Future<void> showNotification(String data) async {
    Map<String, dynamic> payload = jsonDecode(data);
    List<dynamic> actionButtonsJson = [];
    if (payload['actionButtons'] != null) {
      actionButtonsJson = payload['actionButtons'] is String
          ? jsonDecode(payload['actionButtons'])
          : payload['actionButtons'];
    }
    AndroidNotificationDetails androidDetails = AndroidNotificationDetails(
      channel.id,
      channel.name,
      channelDescription: channel.description,
      actions: actionButtonsJson.isNotEmpty
          ? actionButtonsJson.map((actionbutton) {
              final _actionButton = ActionButton.fromJson(actionbutton);
              return AndroidNotificationAction(
                _actionButton.id,
                _actionButton.title,
                cancelNotification: true,
                showsUserInterface: _actionButton.showsUserInterface,
              );
            }).toList()
          : [],
      enableLights: true,
      importance: Importance.defaultImportance,
    );

    NotificationDetails notificationDetails = NotificationDetails(
        android: androidDetails, iOS: DarwinNotificationDetails());

    await _flutterLocalNotificationsPlugin.show(
        DateTime.now().millisecondsSinceEpoch ~/ 1000,
        payload['title'],
        payload['body'],
        notificationDetails,
        payload: data);
  }

  Future<void> _requestPermissions() async {
    if (Platform.isIOS) {
      await _flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              IOSFlutterLocalNotificationsPlugin>()
          ?.requestPermissions(
            alert: true,
            badge: true,
            sound: true,
          );
      await _flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              MacOSFlutterLocalNotificationsPlugin>()
          ?.requestPermissions(
            alert: true,
            badge: true,
            sound: true,
          );
    } else if (Platform.isAndroid) {
      await _flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>()
          ?.createNotificationChannel(channel);
    }
  }
}

main.dart

import 'package:flutter/material.dart';
import 'package:get/get.dart';
import 'package:sizer/sizer.dart';

import '/features/splash/presentation/getx/bindings/splash_bindings.dart';
import '/shared/presentation/constants/app_pages.dart';
import '/shared/presentation/constants/app_routes.dart';
import '/shared/presentation/constants/app_theme.dart';
import 'shared/presentation/getx/main_bindings.dart';
import 'shared/services/firebase_service.dart';
import 'shared/services/notification_service.dart';

GlobalKey<NavigatorState> navKey = GlobalKey<NavigatorState>();
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await MainBindings().dependencies();

  final NotificationService notificationService = NotificationService();
  await notificationService.initialize();
  await FirebaseService.initialize();
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return ResponsiveSizer(builder: (context, orm, scrtyp) {
      return GetMaterialApp(
    
        navigatorKey: Get.key,
        theme: AppTheme.lightTheme,
        darkTheme: AppTheme.darkTheme,
        themeMode: ThemeMode.dark,
        defaultTransition: Transition.rightToLeftWithFade,
        initialRoute: AppRoute.splash,
        initialBinding: SplashBindings(),
        getPages: AppPages.pages,
      );
    });
  }
}

Firebase service class

import 'dart:convert';
import 'dart:developer';

import 'package:datevision/features/chat/domain/usecases/call_usecases.dart';
import 'package:datevision/shared/services/notification_service.dart';
import 'package:firebase_analytics/firebase_analytics.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';

import '../../firebase_options.dart';
import '../presentation/getx/main_bindings.dart';

@pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
  print('Handling a background message ${message.messageId}');
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
  await MainBindings().dependencies();
  await NotificationService().initialize();
  await NotificationService().showNotification(jsonEncode(message.data));
  print('Handling a background message ${message.messageId}');
}

class FirebaseService {
  final CallUseCases _callUseCases;
  FirebaseService(this._callUseCases);
  static Future<void> initialize() async {
    await Firebase.initializeApp(
      options: DefaultFirebaseOptions.currentPlatform,
    );
    FirebaseAnalytics.instance.setAnalyticsCollectionEnabled(true);

    final FirebaseMessaging _firebaseMessaging = FirebaseMessaging.instance;

    await _firebaseMessaging.requestPermission(
      alert: true,
      badge: true,
      sound: true,
    );
    FirebaseMessaging.instance
        .getToken()
        .then((value) => log("fcm token: $value"));

    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);

    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
      await NotificationService().initialize();
      await NotificationService().showNotification(jsonEncode(message.data));
    });
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
      await NotificationService().initialize();
      NotificationService().showNotification(jsonEncode(message.data));
    });
  }
}



You need to sign in to view this answers

Exit mobile version