Flutter 在启动时阻止 iOS 上的推送通知权限
Posted
技术标签:
【中文标题】Flutter 在启动时阻止 iOS 上的推送通知权限【英文标题】:Flutter block push notification permission on iOS at startup 【发布时间】:2021-03-18 15:47:06 【问题描述】:我正在部署一个颤振应用程序,但我遇到了一个问题:在 ios 设备上运行它时,我在启动时获得了推送通知请求权限,但我想在未来的屏幕上请求权限。 具体来说,我想在带有按钮的专用页面中向用户请求许可:
Future<NotificationSettings> checkPermissions() async
settings = await FirebaseMessaging.instance.requestPermission(
announcement: true,
carPlay: true,
criticalAlert: true,
);
return settings;
这是我的 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,
);
你有什么想法吗?
谢谢
【问题讨论】:
【参考方案1】:我是这样解决的:
initializationSettingsIOS = IOSInitializationSettings(
requestAlertPermission: false,
requestBadgePermission: false,
requestSoundPermission: false,
这是关于初始化方法的sdk建议:
/// 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);
【讨论】:
【参考方案2】:我们遇到了同样的问题,我们发现 FlutterLocationNotificationsPlugin 是罪魁祸首。在我们的例子中,我们不再需要本地通知插件(我们使用 Firebase 远程消息,并且只使用本地通知进行测试)。
所以要么:从pubspec.yml
中删除flutter_local_notifications
,或者在使用它们之前应用@masudani 描述的补丁。
关于 Flutter 的 Github 问题的信息:https://github.com/FirebaseExtended/flutterfire/issues/5897
【讨论】:
以上是关于Flutter 在启动时阻止 iOS 上的推送通知权限的主要内容,如果未能解决你的问题,请参考以下文章
如果应用程序未启动,Flutter Firebase 推送通知无法数据
Android 5 Asus ZenFone 2 在应用关闭时阻止推送通知