Flutter block push notification permission on iOS at startup

2,840

Solution 1

I've resolved in this way:

initializationSettingsIOS = IOSInitializationSettings(
      requestAlertPermission: false,
      requestBadgePermission: false,
      requestSoundPermission: false,

This is the sdk suggestion about initialize method:

/// Call this method on application before using the plugin further.
    ///
    /// Will return a [bool] value to indicate if initialization succeeded. On iOS this is dependent on if permissions have been granted to show
    /// notification When running in environment that is neither Android and iOS (e.g. when running tests), this will be a no-op and return true.
    ///
    /// Note that on iOS, initialisation may also request notification permissions where users will see a permissions prompt. This may be fine in
    /// cases where it's acceptable to do this when the application runs for the first time. However, if your application needs to do this at a
    /// later point in time, set the [IOSInitializationSettings.requestAlertPermission], [IOSInitializationSettings.requestBadgePermission] and
    /// [IOSInitializationSettings.requestSoundPermission] values to false. [IOSFlutterLocalNotificationsPlugin.requestPermissions] can then be
    /// called to request permissions when needed.



await flutterLocalNotificationsPlugin.initialize(initializationSettings,
        onSelectNotification: (String payload) async {
      onNotificationClick(payload);

Solution 2

We had the same problem, we found out that FlutterLocationNotificationsPlugin is the culprit. In our case, we didn't needed the Local Notifications Plugin anymore (we are using Firebase Remote Messages, and only used Local Notifications for test).

So either: remove flutter_local_notifications from pubspec.yml or apply the patch like described by @masudani before using them.

Info on Flutter's Github issue: https://github.com/FirebaseExtended/flutterfire/issues/5897

Share:
2,840
masudani
Author by

masudani

Updated on December 06, 2022

Comments

  • masudani
    masudani over 1 year

    I'm deploying a flutter app and I ve a problem: when run it in iOS device I've a push notification request permission on a startup but I'd like to ask for permission in future screen. In detail I'd like to ask permission to the user in a dedicated page with a button:

    Future<NotificationSettings> checkPermissions() async {
        settings = await FirebaseMessaging.instance.requestPermission(
          announcement: true,
          carPlay: true,
          criticalAlert: true,
        );
        return settings;
      }
    }
    

    This is my main.dart

    import 'dart:async';
    import 'package:firebase_core/firebase_core.dart';
    import 'package:firebase_messaging/firebase_messaging.dart';
    import 'package:flutter_local_notifications/flutter_local_notifications.dart';
    
    
    Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
      await Firebase.initializeApp();
      print('------- onBackgroundMessage ----------');
    }
    
    // ACTIVATE ANDROID NOTIFICATION IN FOREGROUND
    const AndroidNotificationChannel channel = AndroidNotificationChannel(
      'high_importance_channel', // id
      'High Importance Notifications', // title
      'This channel is used for important notifications.', // description
      importance: Importance.high,
    );
    
    // ACTIVATE ANDROID NOTIFICATION IN FOREGROUND
    final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
        FlutterLocalNotificationsPlugin();
    
    //RemoteMessage globalMessage;
    
    Future<void> main() async {
      WidgetsFlutterBinding.ensureInitialized();
      await Firebase.initializeApp();
      FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
    
      // ACTIVATE ANDROID NOTIFICATION IN FOREGROUND
      await flutterLocalNotificationsPlugin
          .resolvePlatformSpecificImplementation<
              AndroidFlutterLocalNotificationsPlugin>()
          ?.createNotificationChannel(channel);
    
      // ACTIVATE IOS NOTIFICATION IN FOREGROUND
      await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
        alert: true,
        badge: true,
        sound: true,
      );
    
      runApp(MyApp());
    }
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          routes: {
            '/': (context) => Application(),
            '/pushNotification': (context) => MessageScreen()
          },
        );
      }
    }
    
    class Application extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => _Application();
    }
    
    class _Application extends State<Application> {
      var initializationSettings;
      var initializationSettingsAndroid;
      var initializationSettingsIOS;
      RemoteMessage foregroundMessage;
    
      @override
      void initState() {
        super.initState();
    
        print("_Application : inizio initState()");
    
        initializationSettingsAndroid =
            AndroidInitializationSettings('launch_background');
        initializationSettingsIOS = IOSInitializationSettings(
          requestAlertPermission: true,
          requestBadgePermission: true,
          requestSoundPermission: false,
          onDidReceiveLocalNotification: (id, title, body, payload) async {
            // your call back to the UI
          },
        );
        initializationSettings = InitializationSettings(
            android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
    
        setOnNotificationClick(onNotificationClick);
    
        FirebaseMessaging.instance
            .getInitialMessage()
            .then((RemoteMessage message) {
          if (message != null) {
            //Navigator.push(context,
            //new MaterialPageRoute(builder: (context) => new LoginScreen()));
            Navigator.pushNamed(context, '/pushNotification',
                arguments: MessageArguments(message, true));
          }
        });
    
        FirebaseMessaging.onMessage.listen((RemoteMessage message) {
          RemoteNotification notification = message.notification;
          AndroidNotification android = message.notification?.android;
    
          foregroundMessage = message;
    
          print('-------- onMessage ----------');
    
          //serve per notificare in android quando l'app è in foreground
          if (notification != null && android != null) {
            flutterLocalNotificationsPlugin.show(
                notification.hashCode,
                notification.title,
                notification.body,
                NotificationDetails(
                  android: AndroidNotificationDetails(
                    channel.id,
                    channel.name,
                    channel.description,
                    // TODO add a proper drawable resource to android, for now using
                    //      one that already exists in example app.
                    icon: 'launch_background',
                  ),
                ),
                payload: message.data.toString());
          }
        });
    
        FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
          print('---- onMessageOpenedApp ------------------');
          //Navigator.push(context,
          //  new MaterialPageRoute(builder: (context) => new LoginScreen()));
          Navigator.pushNamed(context, '/pushNotification',
              arguments: MessageArguments(message, true));
        });
      }
    
      setOnNotificationClick(Function onNotificationClick) async {
        await flutterLocalNotificationsPlugin.initialize(initializationSettings,
            onSelectNotification: (String payload) async {
          onNotificationClick(payload);
        });
      }
    
      onNotificationClick(String payload) {
        print('---- onNotificationClick ------------------');
        print(payload);
        Navigator.pushNamed(context, '/pushNotification',
            arguments: MessageArguments(foregroundMessage, false));
      }
    
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'XYZ',
          debugShowCheckedModeBanner: false,
          theme: ThemeData(
            primarySwatch: Colors.blue,
          ),
          initialRoute: '/',
          onGenerateRoute: RouteGenerator.generateRoute,
        );
      }
    }
    

    Do you have any ideas?

    thank you