Flutter block push notification permission on iOS at startup
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
masudani
Updated on December 06, 2022Comments
-
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