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

时间:2018-01-23 14:11:45

标签: android ios dart flutter

我正在尝试在点击推送通知时实现打开特定屏幕,我的有效负载如下所示:

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

我收到通知但是我无法捕捉到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在我的应用程序处于前台时在消息中说,但我的问题是如何从系统托盘中引发的推送通知中捕获点击事件并导航到所需的屏幕。

14 个答案:

答案 0 :(得分:17)

这里有一些事情:

1- click_action必须设置为"FLUTTER_NOTIFICATION_CLICK"

必须在有效负载的click_action部分设置

2- 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注册为navigatorKey的{​​{1}}属性,并将其用于通过MaterialApp

全球访问您的Navigator

答案 1 :(得分:8)

提供有效载荷使用:

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

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"],
                      )));
        });
      },
    );
  }

答案 2 :(得分:5)

由于@xqwzts方法非常适合在App处于打开状态时接收消息,

以下示例将导航到特定页面,

  

[该代码取自FIREBASE消息插件示例代码   仅当它通过数据发送时,它才导航到一个命名页面   FIREBASE控制台]

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

enter image description here

  

了解这2项,FCM通知有2节

Firebase云消息传递页面中的

第一消息标题部分称为通知数据 [当应用程序最小化或关闭时,它将显示为通知]

位于网页底部的第二个消息标题字段称为消息数据,[它会根据您的意愿显示在应用程序内部作为通知或警报对话框]

STEPS 创建一个虚拟项目,然后使用firebase消息插件,在该框中给BMW Cars作为 主题,然后单击订阅

现在转到您的控制台,然后使用以下格式发送消息,该消息必须包含IdStatus键,因为我们正在解析ID和状态键,以便显示带有状态键的Vlaue的NextPage,但如果您更喜欢标题或正文之类的字段,那么您也可以这样做,但请确保使用您的Flutter代码解析地图值。

//THIS IS A LITTLE BIT MODIFIED VERSION OF Example Code given in Firebase 
//Messagaing Plugin
//WHEN U PASTE THE CODE IN UR VSCODE 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(),
          ),
    );
  }
}

答案 3 :(得分:5)

对于任何想要在 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 strong>(当应用在后台或终止时)。

Android 通知将出现在顶部托盘和 onBackgroundMessage 的触发方法(当应用程序在后台或终止时)。您必须使用 flutter_local_notificationsoverlay_support 等第三方解决方案才能在 onMessage(前台应用)期间显示通知。

对于 iOS,当点击通知时(当应用在后台、终止或前台时),方法 onMessageOpenedApp 将被触发。对于 Android,当应用程序在后台运行或仅终止时,此方案将起作用(如果启用了抬头通知显示/横幅 - 您需要为 android 创建 channel_id)

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

答案 4 :(得分:3)

步骤1:在Firebase通知中以click_actionFLUTTER_CLICK_ACTION的形式传递一个键值对。

步骤2:使用步骤1,您将在onResumeonLaunch方法内收到通知的onTap回调。

第3步:点击通知按钮,执行以下操作以导航到特定屏幕。

  • 在构建MaterialApp时,传递一个navigatorKey参数,该参数指定用于导航器的键,然后将该键分配给您的材料应用,如下所示:
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(),
      ),
    );
  }
}
  • 现在,使用以下代码行通过onResumeonLuanch方法导航到屏幕:
 navigatorKey.currentState.push(
    MaterialPageRoute(builder: (_) => Dashboard())
 );

答案 5 :(得分:1)

AndroidManifest.xml

这对我有用。 您需要在 AndroidManifest.xml 文件中添加此代码。您可以将任何内容作为“click_action”,但它需要与清单文件中的相同。不确定 iOS。

答案 6 :(得分:1)

我来不及回答这个问题,但最后,我已经用一些 android 原生代码和颤振代码实现了这一点。那么,让我们从头开始一步一步

1.) 转到您的 build.gradle 文件(路径 android>app>buid.gradle)。添加 firebase 消息传递依赖项,然后从 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.) 转到您的 android 应用清单文件 (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.file 并在活动结束标记之后的活动标记和元数据标记代码中添加意图过滤器代码

    <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);
});

答案 7 :(得分: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();
      }

答案 8 :(得分:0)

使用firebase_messaging:“ ^ 8.0.0-dev.10” FlutterFire FCM FlutterFire FCM notifications

遵循此代码。容易得多。

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("...");
  }
}

答案 9 :(得分:0)

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

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

一旦完成,对于颤动代码,请确保在 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'
    ];

答案 10 :(得分:0)

如果您的应用被终止,您需要使用 getInitialMessage 函数

 RemoteMessage terminatedMessage =
        await FirebaseMessaging.instance.getInitialMessage();

 if (terminatedMessage != null) {
     // this is a function I created to route to a page
    _processPushNotification(message: terminatedMessage);
 }

答案 11 :(得分:-1)

    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()
       )
      );
    },

尝试

答案 12 :(得分:-2)

单击通知后,我将移动到onResume和onLaunch上的特定屏幕。但是当我的应用程序终止并单击通知时,我仍然遇到问题,我的屏幕处于打开状态,几秒钟后我的默认应用程序屏幕处于打开状态。 guid。

答案 13 :(得分:-3)

      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
  },

添加等待正在工作