如何在点击Flutter的推送通知时打开特定屏幕

109 人关注

我正试图实现在点击推送通知时打开特定的屏幕,我的有效载荷看起来像这样。

 var payload = {
        notification: {
            title: notificationTitle,
            body: notificationMessage,
            click_action:"/screena",sound:"default",

我收到了通知,但我无法在flutter中捕获通知的点击事件,如何捕获它。我正在使用flutter消息传递

https://github.com/flutter/plugins/tree/master/packages/firebase_messaging

我的Firebase推送信息服务代码是这样的

 pushMessagingService() async{
messagingreference.configure(
onMessage: (Map<String, dynamic> message) {
  print("I am here in on message");
  print(message);
onLaunch: (Map<String, dynamic> message) {
  print("I am here onLaunch");
  print(message);
onResume: (Map<String, dynamic> message) {
  print("I am hereonResume");
  print(message);
  messagingreference.requestNotificationPermissions(
  const IosNotificationSettings(sound: true, badge: true, alert: true));
 messagingreference.onIosSettingsRegistered
  .listen((IosNotificationSettings settings) {
print("Settings registered: $settings");
 messagingreference.getToken().then((String token) async {
print(token);

在这里,当我的应用程序处于前台时,我可以得到@xqwzts所说的信息,但我的问题是如何从系统托盘中提出的推送通知中捕获点击事件,并导航到所需的屏幕。

1 个评论
我也有同样的问题。
android
ios
flutter
dart
firebase-cloud-messaging
siva kumar
siva kumar
发布于 2018-01-23
15 个回答
xqwzts
xqwzts
发布于 2019-04-15
已采纳
0 人赞同

这里有几件事。

1- click_action 要设置为 "FLUTTER_NOTIFICATION_CLICK"

2- click_action 必须在有效载荷的 data 部分进行设置。

DATA='{
  "notification": {
    "body": "this is a body",
    "title": "this is a title",
  "data": {
    "click_action": "FLUTTER_NOTIFICATION_CLICK",
    "sound": "default", 
    "status": "done",
    "screen": "screenA",
  "to": "<FCM TOKEN>"

这应该可以让你在你的flutter应用程序中的onMessage处理程序中收到消息。

从那里你可以拨打Navigator.of(context).pushNamed(message['screen'])

如果你当时没有BuildContext,你可以注册一个GlobalKey作为你的MaterialAppnavigatorKey属性,并使用它来访问你的Navigator全局,通过GlobalKey.currentState

在这里,当我的应用程序处于前台时,我可以得到你所说的信息,但我的问题是如何从系统托盘中提出的推送通知中捕获点击事件,并导航到所需的屏幕。
我能够捕捉到message['screen'],而调用Navigator并没有打开路线
对我来说不起作用。以下是我在onMessage中得到的信息 {notification: {title: First Notification, body: hELLO hELLO Test}, data: {click_action: FLUTTER_NOTIFICATION_CLICK}} ,但重定向不起作用。我把onMessage和onResume配置为 Navigator.of(navigatorKey.currentContext).pushNamed('test'); ,navigatorKey是GlobalKey,用它的navigatorKey设置MaterialApp。
kris
我对Dart很陌生,最后一段话让我很迷茫--你能不能再解释一下@xqwzts?
如果你对如何实现navigatorKey感到困惑,请看这个答案。 stackoverflow.com/a/53397266/9605341
Alphapico
Alphapico
发布于 2019-04-15
0 人赞同

如果有人想在Null Safety之前迁移到最新版本的Firebase Messaging(在iOS和Android上工作),以下是步骤

pubspec.yaml

firebase_core: ^0.7.0
firebase_messaging: ^8.0.0-dev.15

main.dart

GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
Future<void> main() async {
        WidgetsFlutterBinding.ensureInitialized();
        await Firebase.initializeApp();
        await FirebaseMessaging.instance.setForegroundNotificationPresentationOptions(
          alert: true,
          badge: true,
          sound: true,
        runApp(new MyApp());
class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
class _MyAppState extends State<MyApp> {
@override
  Widget build(BuildContext context) {
  return MaterialApp(
              navigatorKey: navigatorKey,
              title: ...

homeScreen.dart

    Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
      print("onBackgroundMessage: $message");
    class HomeScreen extends StatefulWidget {
      @override
      _HomeScreenState createState() => _HomeScreenState();
    class _HomeScreenState extends State<HomeScreen>{
      @override
      void initState() {
        super.initState();
    FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
    FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
        print("onMessage: $message");
    FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
        print("onMessageOpenedApp: $message");
          if (message.data["navigation"] == "/your_route") {
            int _yourId = int.tryParse(message.data["id"]) ?? 0;
            Navigator.push(
                    navigatorKey.currentState.context,
                    MaterialPageRoute(
                        builder: (context) => YourScreen(
                              yourId:_yourId,

注意到iOS的通知会出现在顶部(抬头显示)和触发方法的onMessage(当应用程序在前台时)和onBackgroundMessage(当应用程序在后台或终止时)。

对于安卓系统来说,通知将出现在顶部的托盘上,触发方法为onBackgroundMessage(当应用程序在后台或被终止时),只有。你必须使用第三方解决方案,如flutter_local_notificationsoverlay_support来显示通知。onMessage(应用程序在前台)。

对于iOS,当通知被点击时(当应用程序在后台,终止或前台),方法onMessageOpenedApp将被触发。对于安卓系统,当应用程序在后台或终止时,这种情况将起作用(如果启用了抬头通知显示/横幅--你需要为安卓系统创建通道_id)。

你不再需要在数据负载上发送click_action: FLUTTER_CLICK_ACTION,以便在通知上有可点击事件。FirebaseMessaging将为你处理

如果通知类型是数据,onMessageOpenedApp不被调用,有什么想法吗?
请你将答案与有效载荷一起更新,或者查看这个链接。 stackoverflow.com/questions/68798736/...
我试着这样做,如果应用程序是开放的,当我点击通知,特定的页面打开。但是,如果应用程序终止了,我点击通知,它就会打开应用程序的主页面。
Muhammad Umair Saqib
在我的情况下,onMessageOpenedApp没有被触发。
Rajesh
Rajesh
发布于 2019-04-15
0 人赞同

由于@xqwzts的方法对接收App上的信息很有效,是一种开放状态。

下面的例子将导航到一个特定的页面。

[代码取自Firebase消息插件的示例代码 的代码,它导航到一个命名的页面,在这个页面中,我们通过 firebase控制台]。

//eg: if you give /Nexpage3  in the status field then it will navigate to Nextpage3 of your App

第一个信息标题在你的Firebase云信息传递页面中的部分被称为通知数据[当应用程序被最小化或关闭时,它将显示为一个通知]。

位于网页底部的第二个信息标题部分被称为信息数据。它将以通知或警报对话的形式显示在应用程序内部,这取决于你的愿望。

STEPS 创建一个假的项目,然后使用Firebase消息插件,在这个盒子里把宝马汽车作为 主题,然后点击订阅

现在去你的控制台,然后发送一条格式为FollowOWING的信息,它必须包含IdStatus键,因为我们正在解析Id和Status键,以便用Status键的值显示NextPage,但如果你喜欢标题或正文这样的字段,你也可以这样做,但要确保在你的flutter代码中解析map值。

//THIS IS A LITTLE BIT MODIFIED VERSION OF Example Code given in Firebase 
//Messaging Plugin
//WHEN U PASTE THE CODE IN UR VS CODE OR ANDROID STUDIO PLEASE Format the 
//Document because it is aligned in single lines
import 'dart:async';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
void main() {
  runApp(
    new MaterialApp(
      home: new PushMessagingExample(),
      routes: <String,WidgetBuilder>{
        "/Nexpage1":(BuildContext context)=> new Nexpage1(),
        "/Nexpage2":(BuildContext context)=> new Nexpage2(),
        "/Nexpage3":(BuildContext context)=> new Nexpage3(),
        } ),);}
//INITIAL PARAMETERS
String _homeScreenText = "Waiting for token...";
bool _topicButtonsDisabled = false;
final FirebaseMessaging _firebaseMessaging = new FirebaseMessaging();
final TextEditingController _topicController = new TextEditingController(text: 'topic');
final Map<String, Item> _items = <String, Item>{};
Item _itemForMessage(Map<String, dynamic> message) {
  final String itemId = message['id'];
  final Item item = _items.putIfAbsent(itemId, () => new Item(itemId: itemId))..status = message['status'];
      return item;
//MAIN CLASS WHICH IS THE HOMEPAGE
class PushMessagingExample extends StatefulWidget {
  @override
  _PushMessagingExampleState createState() => new _PushMessagingExampleState();
class _PushMessagingExampleState extends State<PushMessagingExample> {
void _navigateToItemDetail(Map<String, dynamic> message) {
final String pagechooser= message['status'];
Navigator.pushNamed(context, pagechooser);
//CLEAR TOPIC
void _clearTopicText() {setState(() {_topicController.text = "";_topicButtonsDisabled = true;});}
//DIALOGUE
void _showItemDialog(Map<String, dynamic> message) {showDialog<bool>(context: context,builder: (_) => _buildDialog(context, _itemForMessage(message)),).then((bool shouldNavigate) {if (shouldNavigate == true) {_navigateToItemDetail(message);}});}
//WIDGET WHICH IS GOING TO BE CALLED IN THE ABOVE DIALOGUE
Widget _buildDialog(BuildContext context, Item item) {return new AlertDialog(content: new Text("Item ${item.itemId} has been updated"),actions: <Widget>[new FlatButton(child: const Text('CLOSE'),onPressed: () {Navigator.pop(context, false);},),new FlatButton(child: const Text('SHOW'),onPressed: () {Navigator.pop(context, true);},),]);}
@override
void initState() {
super.initState();
_firebaseMessaging.configure(
onLaunch: (Map<String, dynamic> message) async { _navigateToItemDetail(message);},
onResume: (Map<String, dynamic> message) async { _navigateToItemDetail(message);},
onMessage: (Map<String, dynamic> message) async {_showItemDialog(message);},);
//GETTING TOKEN FOR TESTING MANUALY
_firebaseMessaging.getToken().then((String token) {assert(token != null);setState(() {_homeScreenText = "Push Messaging token: $token";});print(_homeScreenText);});}
  @override
  Widget build(BuildContext context) {
    return new Scaffold(
        appBar: new AppBar(  title: const Text('Push Messaging Demo'),),
        body: new Material(
          child: new Column(
            children: <Widget>[
              new Center(
                child: new Text(_homeScreenText),
              new Row(children: <Widget>[
                new Expanded(
                  child: new TextField(
                      controller: _topicController,
                      onChanged: (String v) {
                        setState(() {
                          _topicButtonsDisabled = v.isEmpty;
                new FlatButton(
                  child: const Text("subscribe"),
                  onPressed: _topicButtonsDisabled
                      ? null
                      : () {
                          _firebaseMessaging
                              .subscribeToTopic(_topicController.text);
                          _clearTopicText();
new FlatButton(child: const Text("unsubscribe"),
onPressed: _topicButtonsDisabled? null: () { _firebaseMessaging.unsubscribeFromTopic(_topicController.text);
 _clearTopicText();},),
])],),));}}
//THREE DUMMY CLASSES FOR TESTING PURPOSE 
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//PAGE1
class Nexpage1 extends StatefulWidget {  @override  _Nexpage1State createState() => _Nexpage1State();}
class _Nexpage1State extends State<Nexpage1> { @override Widget build(BuildContext context) { return Scaffold(body: new Center(child: new Text(" Page1"),));}}
//PAGE2
class Nexpage2 extends StatefulWidget {  @override  _Nexpage2State createState() => _Nexpage2State();}
class _Nexpage2State extends State<Nexpage2> {  @override  Widget build(BuildContext context) {    return Scaffold(      body: Center(child: new Text("2pending"),)      );  }}
//PAGE3
class Nexpage3 extends StatefulWidget {  @override  _Nexpage3State createState() => _Nexpage3State();}
class _Nexpage3State extends State<Nexpage3> {  @override  Widget build(BuildContext context) {    return Scaffold(      body: Center(child: new Text("3connected"),)      );  }}
//THIS IS THE CLASS WHICH IS USED TO PARSE THE INFORMATION
class Item {
  Item({this.itemId});
  final String itemId;
  StreamController<Item> _controller = new StreamController<Item>.broadcast();
  Stream<Item> get onChanged => _controller.stream;
  String _status;
  String get status => _status;
  set status(String value) {
    _status = value;
    _controller.add(this);
  static final Map<String, Route<Null>> routes = <String, Route<Null>>{};
  Route<Null> get route {
    final String routeName = '/detail/$itemId';
    return routes.putIfAbsent(
      routeName,
      () => new MaterialPageRoute<Null>(
            settings: new RouteSettings(name: routeName),
            builder: (BuildContext context) => new Nexpage3(),
    
iamcloud.dev
iamcloud.dev
发布于 2019-04-15
0 人赞同

为了提供有效载荷的使用。

1- click_action必须设置为 "FLUTTER_NOTIFICATION_CLICK"--在android清单文件中,我们已经为它定义了意图。

2- click_action必须在有效载荷的数据部分设置。

为NavigatorState定义一个全局变量。

import 'package:flutter/cupertino.dart';
/// Global variables
/// * [GlobalKey<NavigatorState>]
class GlobalVariable {
  /// This global key is used in material app for navigation through firebase notifications.
  /// [navState] usage can be found in [notification_notifier.dart] file.
  static final GlobalKey<NavigatorState> navState = GlobalKey<NavigatorState>();

进入你的MaterialApp并添加

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return ScrollConfiguration(
      behavior: BounceScrollBehavior(),
      child: MaterialApp(
        navigatorKey: GlobalVariable.navState,
        debugShowCheckedModeBanner: false,
        theme: themeData,
        home: App(),

当你按下应用栏的通知时,它会调用onResume。你可以按以下方式导航到所需的页面。

void listenToNotification() {
    fcm.configure(
      onMessage: (Map<String, dynamic> message) async {
        print("onMessage: $message");
        getPreviousNotifications();
      onLaunch: (Map<String, dynamic> message) async {
        print("onLaunch: $message");
      onResume: (Map<String, dynamic> message) async {
        print("onResume: ${message["data"]}");
        SchedulerBinding.instance.addPostFrameCallback((_) {
          Navigator.of(GlobalVariable.navState.currentContext)
              .push(MaterialPageRoute(
                  builder: (context) => TimelineView(
                        campaignId: message["data"]["campaign"],
    
这是最简单的解决方案,而且很有效。谢谢
我们如何提出这样的解决方案? 这是个办法,不需要使用我在其他回复中看到的任何本地代码。
Why do you use addPostFrameCallback ?
Dhaval Kansara
Dhaval Kansara
发布于 2019-04-15
0 人赞同

Step 1: 在Firebase通知中传递一个键值对作为 click_action FLUTTER_CLICK_ACTION .

Step 2: 使用步骤1,你会在 onResume onLaunch 方法内收到通知的onTap回调。

Step 3: 执行以下方案,在点击通知时导航到一个特定的屏幕。

  • When you build your MaterialApp, pass a navigatorKey parameter which specifies the key to use for the navigator and then assign that key to your material app as shown below:
  • class _MyHomePageState extends State<MyHomePage> {
      final GlobalKey<NavigatorState> navigatorKey = GlobalKey(debugLabel: "Main Navigator");
      @override
      Widget build(BuildContext context) {
        return new MaterialApp(
          navigatorKey: navigatorKey,
          home: new Scaffold(
            appBar: AppBar(),
            body: new Container(),
    
  • Now, from the onResume or onLaunch method navigate to your screen using below line of code:
  •  navigatorKey.currentState.push(
        MaterialPageRoute(builder: (_) => Dashboard())
        
    我们如何从一个内部方法访问全局键?
    @humblePilgrim 你也可以在全局层面上声明它。
    Rashid Iqbal
    Rashid Iqbal
    发布于 2019-04-15
    0 人赞同

    如果你的应用程序被终止了,你需要使用 初步信息(getInitialMessage function

     RemoteMessage terminatedMessage =
            await FirebaseMessaging.instance.getInitialMessage();
     if (terminatedMessage != null) {
         // this is a function I created to route to a page
        _processPushNotification(message: terminatedMessage);
    

    processPushNotification函数

    void _processPushNotification({@required RemoteMessage message}) async {
        print("message data ${message.data}");
        print("Processing Future after 46 seconds data ${message.data}");
        Future.delayed(Duration(
          seconds: 4,
        )).then((value) async { }); 
        
    你能分享一下 _processPushNotification 的功能代码吗。
    你可以看到上面的代码
    不,我想知道你是如何路由到一个新页面的。你从哪里获取上下文?或者你在哪里调用这个函数?
    当我点击通知时,它没有进入OnMessageOpenedApp或检查初始信息,谁知道为什么? 这是我的问题。 stackoverflow.com/q/72547014/11567530
    Unais IB
    Unais IB
    发布于 2019-04-15
    0 人赞同
     FirebaseMessaging.instance.getInitialMessage().then((message) {
      RemoteNotification notification = message.notification;
      AndroidNotification android = message.notification?.android;
      if (notification != null && android != null) {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) => NotificationScreen(
              name: message.data['name'],
              place: message.data['place'],
              address: message.data['address'],
    });// handles notification clicks while the app is in the terminated state
        
    你在哪里添加这个函数?在MyApp的启动部分还是哪里?
    inside @override void initState() { super.initState(); //code comes here}.
    你知道为什么信息是空的,但我收到通知,当我点击它时,getInitialState被触发了。
    Cnu Federer
    Cnu Federer
    发布于 2019-04-15
    0 人赞同

    这对我来说很有效。 你需要在AndroidManifest.xml文件中添加这段代码。你可以用任何东西作为 "click_action",但它必须与清单文件中的内容相同。不清楚iOS的情况。

    Rishabh Rawat
    Rishabh Rawat
    发布于 2019-04-15
    0 人赞同

    我已经来不及回答这个问题了,但我终于用一些安卓原生代码,当然还有flutter代码实现了这一点。所以,让我们从头开始,一步步来

    1.)转到你的build.gradle文件(PATH android>app>buid.gradle )。添加Firebase messaging依赖,然后从android studio同步该文件

    implementation 'com.google.firebase:firebase-messaging'
    

    2.)在MainActivity文件路径(PATH android>app>src>main>kotlin>com>yourpackage>MyApplication.java)中制作一个新的文件名MyApplication.java。

    import android.app.NotificationChannel;
    import android.app.NotificationManager;
    import android.content.Context;
    import android.os.Build;
    import io.flutter.app.FlutterApplication;
    import io.flutter.plugin.common.PluginRegistry;
    import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService;
    import io.flutter.plugins.pathprovider.PathProviderPlugin;
    public class MyApplication extends FlutterApplication implements PluginRegistry.PluginRegistrantCallback {
        @Override
        public void onCreate() {
            super.onCreate();
            this.createChannel();
            FlutterFirebaseMessagingService.setPluginRegistrant(this);
        @Override
        public void registerWith(PluginRegistry registry) {
            io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
            PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));
        private void createChannel(){
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                String name = getString(R.string.default_notification_channel_id);
                NotificationChannel channel = new NotificationChannel(name, "default", NotificationManager.IMPORTANCE_HIGH);
                NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                notificationManager.createNotificationChannel(channel);
    

    3.)进入你的安卓应用清单文件(PATH android>app>src>main>AndroidManifest.xml),添加替换<application android:name with ".MyApplication"标签,如下所示

    <application
            android:name=".MyApplication" //replace your name with .MyApplication
            android:label="helpwise"
            android:icon="@mipmap/ic_launcher">
    

    4.)现在你需要在flutter项目中添加firebase消息的依赖。所以在pubspec.yaml中添加

    firebase_messaging: ^6.0.9
    

    5.)在你的main.dart文件中加入firebase代码

    Future<dynamic> myBackgroundMessageHandler(Map<String, dynamic> message) {
      if (message.containsKey('data')) {
        final dynamic data = message['data'];
        print('Notification data is ');
        print(message['data']);
      if (message.containsKey('notification')) {
        // Handle notification message
        final dynamic notification = message['notification'];
    class SelectMailbox extends StatefulWidget {
      static const routeName = '/mailbox-screen';
      @override
      _SelectMailboxState createState() => _SelectMailboxState();
    class _SelectMailboxState extends State<SelectMailbox> {
      final FirebaseMessaging _firebaseMessaging = FirebaseMessaging();
      @override
      void initState() {
        _firebaseMessaging.getToken().then((token) async{
          SharedPreferences preferences = await SharedPreferences.getInstance();
          final String userData = preferences.get('userData');
          final String authToken=jsonDecode(userData)['token'];
          print("Device token is $token"); //I will use this token to send notif.
          await http.post("https://your_domain/mobile/save-token",
              headers: {"Content-Type": "application/json"},
              body: jsonEncode({"device_token": token,"type":"android","token":authToken}));
        _firebaseMessaging.configure(
            onMessage: (Map<String, dynamic> message) async {
            }, onBackgroundMessage: Platform.isAndroid?myBackgroundMessageHandler:null,
            onResume: (Map<String, dynamic> message) async {
               print("onBackground Message $message"); 
              _selectIdsNotification(message['data']['thread_id'],message['data']['mailbox_id'],14,message['data']['mailboxType'],"All",context);
            }, onLaunch: (Map<String, dynamic> message) async {
          print("onLaunch Message $message");
          _selectIdsNotification(message['data']['thread_id'],message['data']['mailbox_id'],14,message['data']['mailboxType'],"All",context);
        super.initState();
      _selectIdsNotification(threadID,mailboxId,subBox,mailboxType,mailboxTab,myContext) async {
        // YOU CAN ADD THE LOGIC OF DIFFERENT PAGE ROUTE ACCORDING TO DATA PASS FROM NOTIFICATION in my case i could use the mailboxType
        Navigator.push(
          myContext,
          MaterialPageRoute(
            builder: (context) => ThreadDetail(threadID, mailboxType,notificationMailboxId: mailboxId),
    

    6.)再次进入你的AndoridManifest.文件,在活动标签内添加意图过滤器代码,在活动结束标签后添加元数据标签代码

        <application
                android:name=".MyApplication"
                android:label="helpwise"
                android:icon="@mipmap/ic_launcher">
                <activity
                    android:name=".MainActivity"
                    android:launchMode="singleTop"
                    android:theme="@style/LaunchTheme"
                    android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
                    android:hardwareAccelerated="true"
                    android:windowSoftInputMode="adjustResize">
                    <meta-data
                      android:name="io.flutter.embedding.android.NormalTheme"
                      android:resource="@style/NormalTheme"
                    <meta-data
                      android:name="io.flutter.embedding.android.SplashScreenDrawable"
                      android:resource="@drawable/launch_background"
                    <intent-filter>
                        <action android:name="android.intent.action.MAIN"/>
                        <category android:name="android.intent.category.LAUNCHER"/>
                    </intent-filter>
        <-- ADD THIS INTENT FILTER IN YOUR CODE -->
                    <intent-filter>
                        <action android:name="FLUTTER_NOTIFICATION_CLICK" />
                        <category android:name="android.intent.category.DEFAULT" />
                    </intent-filter>
                </activity>
                <meta-data
                    android:name="flutterEmbedding"
                    android:value="2" />
     <-- ADD THIS META DATA TAG IN YOUR CODE -->
                <meta-data android:name="com.google.firebase.messaging.default_notification_channel_id"
                           android:value="@string/default_notification_channel_id" />
            </application> 
    

    7.)现在进入android值文件夹PATH(android>app>src>main>res>values>strings.xml)。如果你没有看到strings.xml文件,那么在与strings.xml文件相同的路径上创建一个文件,并添加以下代码

    <?xml version="1.0" encoding="utf-8"?>
    <resources>
        <string name="default_notification_channel_id">default_notification_channel_id</string>
    </resources>
    

    10.)这就是它的人。现在,你需要重新启动应用程序,并调用Firebase消息通知API到设备令牌。

        ar axios = require('axios');
    var data = JSON.stringify(
      "to": "your_mobile_device_token",
      "data": {
        "mailbox_id": "11111",
        "thread_id": "1111",
        "mailboxType": "email",
        "click_action": "FLUTTER_NOTIFICATION_CLICK"
      "priority": "high",
      "notification": {
        "body": "Hi, You have received new Message",
        "title": "Flutter",
        "image": "your_image_cdn_path"
      "click_action": "FLUTTER_NOTIFICATION_CLICK"
    var config = {
      method: 'post',
      url: 'https://fcm.googleapis.com/fcm/send',
      headers: { 
        'Authorization': 'key=your_firebase_server_key', 
        'Content-Type': 'application/json'
      data : data
    axios(config)
    .then(function (response) {
      console.log(JSON.stringify(response.data));
    .catch(function (error) {
      console.log(error);
        
    Magesh Pandian
    Magesh Pandian
    发布于 2019-04-15
    0 人赞同

    起初,@xqwzts的回答对我不起作用。经过大量的研究,我发现我们需要延迟初始化configure方法。我附上了下面的代码。它将对其他人有帮助。

    void initState() {
            // TODO: implement initState
            super.initState();
            _firebaseMsgListener();
          void _firebaseMsgListener() {
            // if (Platform.isIOS) iOS_Permission();
            _firebaseMessaging.getToken().then((token) {
              Fimber.d("=====> token : $token");
              UpdateTokenRequest request = UpdateTokenRequest();
              request.token = token;
              homeBloc.updateFCMToken(request);
            Future.delayed(Duration(seconds: 1), () {
              _firebaseMessaging.configure(
                onBackgroundMessage: myBackgroundMessageHandler,
                onMessage: (Map<String, dynamic> message) async {
                  Fimber.d("=====>on message $message");
                  Fluttertoast.showToast(msg: "onMessage $message");
                onResume: (Map<String, dynamic> message) async {
                  Fimber.d("=====>onResume $message");
                  Fluttertoast.showToast(msg: "onResume $message");
                onLaunch: (Map<String, dynamic> message) async {
                  Fimber.d("=====>onLaunch $message");
                  Fluttertoast.showToast(msg: "onLaunch $message");
          Future<dynamic> myBackgroundMessageHandler(
              Map<String, dynamic> message) async {
            print("_backgroundMessageHandler");
            if (message.containsKey('data')) {
              // Handle data message
              final dynamic data = message['data'];
              print("_backgroundMessageHandler data: ${data}");
            if (message.containsKey('notification')) {
              // Handle notification message
              final dynamic notification = message['notification'];
              print("_backgroundMessageHandler notification: ${notification}");
              Fimber.d("=====>myBackgroundMessageHandler $message");
            return Future<void>.value();
        
    apurv thakkar
    apurv thakkar
    发布于 2019-04-15
    0 人赞同

    在处理推送通知重定向代码之前,有几件事需要注意。

    首先,添加 "click_action"。"FLUTTER_NOTIFICATION_CLICK",在推送通知有效载荷的数据块中。

    第二,在firebasehelper类中定义下面的回调。

    //This method will call when the app is in kill state
        FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
          if (message != null) {
            //Handle push notification redirection here
        //This method will call when the app is in foreground state
        FirebaseMessaging.onMessage.listen((RemoteMessage? message) async {
          if (message != null && message.data.isNotEmpty) {
            //Handle push notification redirection here
        //This method will call when the app is in background state
        FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage? message) {
          if (message != null) {
            //Handle push notification redirection here
    

    Firebase帮助类代码

    class FirebaseHelper {
      static late FirebaseApp _firebaseApp;
      static late FirebaseMessaging _firebaseMessaging;
      static final FirebaseHelper _singleton = FirebaseHelper._internal();
      static late Timer _timer;
      factory FirebaseHelper() {
        return _singleton;
      FirebaseHelper._internal();
      // To Initialize Firebase
      static Future<void> init() async {
        _firebaseApp = await Firebase.initializeApp();
        await _initCloudMessaging();
      static FirebaseApp getFireBaseApp() {
        return _firebaseApp;
      // To Initialize Firebase FCM
      static Future<void> _initCloudMessaging() async {
        _firebaseMessaging = FirebaseMessaging.instance;
        _firebaseMessaging.setForegroundNotificationPresentationOptions(sound: true, badge: true);
        await requestNotificationPermissions();
        _setUpNotificationListener();
      static Future<NotificationSettings> getNotificationSettings() async {
        return await FirebaseMessaging.instance.getNotificationSettings();
      // To Request Notification Permissions (For IOS)
      static Future<NotificationSettings> requestNotificationPermissions() async {
    // for permission
        return await FirebaseMessaging.instance.requestPermission(
          alert: true,
          badge: true,
          provisional: false,
          sound: true,
      // To Set On Notification Listener
      static void _setUpNotificationListener() {
        //This method will call when the app is in kill state
        FirebaseMessaging.instance.getInitialMessage().then((RemoteMessage? message) {
          if (message != null) {
            //Handle push notification redirection here
        //This method will call when the app is in foreground state
        FirebaseMessaging.onMessage.listen((RemoteMessage? message) async {
          if (message != null && message.data.isNotEmpty) {
            //Handle push notification redirection here
        //This method will call when the app is in background state
        FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage? message) {
          if (message != null) {
            //Handle push notification redirection here
      // To Get Device Token
      static Future<String?> getDeviceToken() async {
        return await _firebaseMessaging.getToken();
    

    你需要在main.dart文件的runApp函数前初始化这个类,像这样。

     WidgetsFlutterBinding.ensureInitialized();
      FirebaseHelper.init();
        
    Samar Ali Qazalbash
    Samar Ali Qazalbash
    发布于 2019-04-15
    0 人赞同

    使用firebase_messaging。"^8.0.0-dev.10" FlutterFire FCM FlutterFire FCM的通知

    按照这个代码。这就容易多了。

    class Application extends StatefulWidget {
      @override
      State<StatefulWidget> createState() => _Application();
    class _Application extends State<Application> {
      @override
      void initState() async {
        super.initState();
        // Get any messages which caused the application to open from
        // a terminated state.
        RemoteMessage initialMessage =
            await FirebaseMessaging.instance.getInitialMessage();
        // If the message also contains a data property with a "type" of "chat",
        // navigate to a chat screen
        if (initialMessage?.data['type'] == 'chat') {
          Navigator.pushNamed(context, '/chat',
              arguments: ChatArguments(initialMessage));
        // Also handle any interaction when the app is in the background via a
        // Stream listener
        FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
          if (message.data['type'] == 'chat') {
            Navigator.pushNamed(context, '/chat',
              arguments: ChatArguments(message));
      @override
      Widget build(BuildContext context) {
        return Text("...");
        
    gamerwalt
    gamerwalt
    发布于 2019-04-15
    0 人赞同

    从文件中( https://pub.dev/packages/firebase_messaging )的软件包,它明确指出你需要在android/app/src/main/java/app/{{appName}}的位置创建一个Application.java。

    在该文件(Application.java)中,它指定了你需要包括的确切代码。

    一旦完成,对于flutter,代码,确保你在main.dart文件中设置你的backgroundMessageHandler函数,因为它需要是一个顶级函数。

    还有一件事要注意,如果你的PluginRegistry出现错误,请使用下面的代码。

    import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin;
    FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
    

    当你发送一个通知,并且你希望你的backgroundMessage能够捕捉到,以及当你点击通知时onResume能够捕捉到,确保你的通知有标题、正文、click_action,然后你的数据也应该有一个标题、正文,然后是你想要的任何数据。

    我在自己的例子中使用了这一点。

    $notification = [
            'title' => 'New notification',
            'body' => "{$group->group_name} needs it's members to be updated. It starts on {$startDate->toFormattedDateString()}, however...",
            'icon' => '',
            'click_action'=> 'FLUTTER_NOTIFICATION_CLICK',
            'Test' => 'Some testing data',
        $data = [
            'title' => 'This title is in the data',
            'body' => "this body is in the data",
            'Test' => 'Some testing data',
            'click_action'=> 'FLUTTER_NOTIFICATION_CLICK'
        
    alpc
    alpc
    发布于 2019-04-15
    0 人赞同
          onBackgroundMessage: myBackgroundMessageHandler,
      onLaunch: (Map<String, dynamic> message) async {
        await print("onLaunch: $message");
        ///_navigateToItemDetail(message);
        await _showItemDialog(message); // Diyalog Kutusu Oluştur
      onResume: (Map<String, dynamic> message) async {
        await print("onResume: $message");
        ///_navigateToItemDetail(message);      
        await _showItemDialog(message); // Diyalog Kutusu Oluştur
    

    添加等待 is working

    what is await print("onLaunch: $message"); ,
    Gilang
    Gilang
    发布于 2019-04-15
    0 人赞同
        onLaunch: (Map<String, dynamic> message) {
          print("I am here onLaunch");
          print(message);
          Navigator.push(
           context,
           MaterialPageRoute(
            builder: (context) => ScreenA()
        onResume: (Map<String, dynamic> message) {
          print("I am here onResume");
          print(message);
          Navigator.push(
           context,
           MaterialPageRoute(
            builder: (context) => ScreenA()