-
Notifications
You must be signed in to change notification settings - Fork 4k
[firebase_messaging] background messaging documentation prob #199
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
Can you be more specific on how exactly you solved the problem. Tried making the handler static and it broke during compile time |
I have the same problem. Can you update the documentation? I am confused by this
Thank you for help. |
Yes I have the same question as @kleinpetr |
On Mon, Sep 23, 2019 at 12:05 PM kleinpetr ***@***.***> wrote:
I have the same problem. Can you update the documentation? I am confused
by this
1. Add an Application.java class to your app *(where??)*
2. Set name property of application in AndroidManifest.xml *(where??,
how??)*
3. Define a top level Dart method to handle background messages *(where??
at the same time when I configured onMessage callback?)*
Thank you for help.
Here's what worked for me (with names changed to protect the innocent):
In android/app/src/main/AndroidManifest.xml:
<application android:name="org.your.app.Application"
In android/app/src/main/java/org/your/app/Application.java:
package org.your.app;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
import io.flutter.plugins.GeneratedPluginRegistrant;
import
io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService;
public class Application extends FlutterApplication implements
PluginRegistrantCallback {
@OverRide
public void onCreate() {
super.onCreate();
FlutterFirebaseMessagingService.setPluginRegistrant(this);
}
@OverRide
public void registerWith(PluginRegistry registry) {
GeneratedPluginRegistrant.registerWith(registry);
}
}
Note that there is also
android/app/src/main/java/org/your/app/MainActivity.java, which is
generated by Flutter (I think).
In you flutter code (assume main.dart), follow the basic instructions for
initializing Firebase etc. from the example at
https://github.com/FirebaseExtended/flutterfire/blob/master/packages/firebase_messaging/example/lib/main.dart
At the top level (i.e. not within a class definition) add:
Future<dynamic> _backgroundMessageHandler(Map<String, dynamic> message) {
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}");
}
I added the "_" prefix to keep this function private to main.dart. It can
still be passed to _firebaseMessaging.configure, since it is a named
function. You can also define it within the same class in which you call
_firebaseMessaging.configure, but ONLY if it is marked static. If it is a
non-static method, Flutter (or Dart) will treat it as an anonymous closure,
which cannot be used as a callback (a cb must be either a function object
or a static method). See the comment in GetCallbackFromHandle in
https://github.com/flutter/engine/blob/master/lib/ui/dart_runtime_hooks.cc.
Then pass the callback in your call to configure (you also need to provide
callbacks to onLaunch and onResume; these can be :
_firebaseMessaging.configure(
onMessage: myForegroundMessageHandler,
onBackgroundMessage: _backgroundMessageHandler,
...
The callbacks must have type MessageHandler defined in
firebase_messaging.dart in the package: typedef Future<dynamic>
MessageHandler(Map<String, dynamic> message);
That takes care of the frontend. The backend must also be properly
configured, and you must send your message (either a data message or a
notification message with a data payload) from your server, not from the FB
console. In particular, for notification+data, you must pass
"FLUTTER_NOTIFICATION_CLICK" as value for the click_notification key of the
android config stanza. Which means you need to set a platform-specific
field. The details are at
https://firebase.google.com/docs/cloud-messaging/concept-options#when_to_use_platform-specific_fields;
sample server code is at
https://firebase.google.com/docs/cloud-messaging/send-message#example_notification_message_with_platform-specific_delivery_options
but you need to add a call to setClickAction on the AndroidConfig.Builder (
https://firebase.google.com/docs/reference/admin/java/reference/com/google/firebase/messaging/AndroidNotification.Builder.html
)
e.g. .setClickAction("FLUTTER_NOTIFICATION_CLICK")
HTH,
Gregg
<
… —
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#199>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAES2NEVQ2D6RDIBURQWVFLQLDZO3ANCNFSM4IZDYWKQ>
.
|
I can't configure firebase at the main.dart because I have some logic about this. For example I am initing the FCM only if user is logged, etc. So I have to configure firebase inside a class. You said the background callback must be static, OK I set static method, but still not working.
|
Okay I don't know how I managed to get mine to work honestly. I just followed all the instructions and commented out the onBackgroundMessage because it was giving fatal compile time errors.
like that but I'm confused why my _backgroundMessageHander top-level function gets triggered even on app terminated or forground. I also made sure that all my handlers including message, resume, and launch are top-level functions. (NOT IN ANY CLASS). I hope this helps someone because I've been struggling with this for days. |
On Wed, Sep 25, 2019 at 2:24 AM kleinpetr ***@***.***> wrote:
I dont understand the part of AndroidManifest.xml. Can I use
MainActivity.java generated by Flutter or rewrite this file by
Application.java from tutorial. Or add Application.java within
MainActivity.java. But how can I set in AnroidManifest.xml ??
<application android:name="cz.example.myapp.Application"></application>
<application android:name="io.flutter.app.FlutterApplication" android:label="MyApp" ***@***.***/ic_launcher">
<!-- <meta-data android:name="com.google.android.geo.API_KEY" android:value="AIzaSyBmpFHEI4rZ7eIenkwaEDYvXGYMxt60yNM"/> -->
<activity android:name=".MainActivity" android:launchMode="singleTop" ***@***.***/LaunchTheme" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode" android:hardwareAccelerated="true" android:windowSoftInputMode="adjustResize">
<!-- disable splashScreen -->
<meta-data android:name="io.flutter.app.android.SplashScreenUntilFirstFrame" android:value="false" />
This is not working
We cannot help you with "this is not working." If you can give specifics
we can try.
… —
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#199>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAES2NFZ6DWCYUW2ZEUJVJDQLMGZRANCNFSM4IZDYWKQ>
.
|
What do you mean top-level handler? I need working with variables and methods from the class in fcm calbacks.. is there some chance ro declare onBackgroundMessage callback the same way as other callbacks?? |
Please update example of firebase_messaging where it handles background messages. Seriously it's very confusing or anyone please upload demo working project for handling onBackground messages. |
@ektelat It means you need to use your custom Application class instead of the default flutter Application class You have this in manifets (probably) And you need replace io.flutter.app.FlutterApplication to your Application class for example com.yourdomain.Application or or .Application (maybe) |
@kleinpetr stop here.... |
@ektelat show me your Application.java please |
@kleinpetr i get my mistake, i just copy the same example of flutter document so it's with so what to do with: onBackgroundMessage i need it here the myBackgroundMessageHandler: what is my problem?? |
@ektelat Yes I stoped in the same moment as you... I don't know where is the problem. I still waiting for update example on pub.dev ... or some answer here.. |
I've had so much trouble making any of this work, I don't dare try background stuff. So I have not attempted to use background notifications. I have noticed, however, that none of my messages, sent either by the firebase messaging console or the firebase Admin SDK ever reach the system tray. Doesn't matter that the app is terminated, or background or whatever. Gmail notifications are still showing up, by mine don't. Notifications enabled and double checked for my app. If the app is running, I get the messages I finally created an app that just tries to do push, nothing else. Same thing. Working great on Android. I could do without the background stuff if my messages would hit the system tray. |
Ok I got it worked. If u send any notification from firebase console it'll never call onBackground... Try postman or any other to send notification using fcm notification api. And send only data message. Remove title and body from notification parameter... Now you will get onBackground. |
That's makes sense, right? Messages with notifications go to the system tray, so only "data only" messages will trigger background logic. And the console forces you to send title and body, so it's a notification message. I just can't get a simple notification to show in the system tray. Wrong thread I guess. Good to hear you got it working. |
FYI what I have found is:
- If you send a Notification+Data message (
https://firebase.google.com/docs/cloud-messaging/concept-options#notification-messages-with-optional-data-payload)
then the message will go to the system tray if your app is backgrounded or
terminated. If you tap the message, it will call onLaunch if your app is
terminated, and onResume if your app is backgrounded. In both cases the
data payload is delivered. It will not call your onBackgroundMessage
routine; evidently that's for pure data messages.
Note that the doc (for the flutter fb messaging package) says data
notifications will be lost if your app is terminated.
HTH,
Gregg
…On Mon, Sep 30, 2019 at 2:18 AM Lokesh Jain ***@***.***> wrote:
Ok I got it worked.
If u send any notification from firebase console it'll never call
onBackground...
Try postman or any other to send notification using fcm notification api.
And send only data message. Remove title and body from notification
parameter... Now you will get onBackground.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#199>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/AAES2NEG6AT6WOVSBF6RRY3QMGR4DANCNFSM4IZDYWKQ>
.
|
@mobileink You're 100% on this one. When I was working in Xamarin, you actually had to have a second app, especially in iOS, that knew what to do with the incoming data only messages. My solution was to create a local notification and dump it into the system tray myself so it would show up - but only if I needed it to. At that point, all my messages were data messages, but I was adding content to them so I could show them if needed. That approach started with a "logout all device" where I wanted to clear access tokens on every device the user had and ended up adding buttons so actions could be taken directly in the notification in the system tray. It was pretty cool, but Xamarin Forms finally did me in after a couple of years and I gave it up. |
Sorry for the maybe dumb question, but how can i send a notification that triggers such callback? |
@nerder for example like this https://medium.com/android-school/test-fcm-notification-with-postman-f91ba08aacc3 |
Thank you very much, sir, I guess you have the solution. The official wiki is incomplete, in my opinion. In addition to this issue, I've got a very strange behavior : Is this an expected behavior? Or am I missing something in my understanding of this plugin (which is totally possible as well, I'm not very familiar with flutter FCM) Thanks y'all ! |
I'm leaving this issue open |
See my previous response: #199 (comment) I believe this is expected behavior for notification messages with data payload. A pure data message would be handled by onBackgroundMessage (I think), but that is evidently not yet supported by the plugin. Gregg |
Hello, I am implementing push notification currently. My onbackgroundmessage() is not getting called even my app is terminated. How to solve the issue. I am getting data payload inside onLaunch(). Can anyone tell me why onbackgroundmessage() might not getting called. I have added my Application class and followed all the things as per pub documentation. Not getting any errors. @iapicca @mobileink Can anyone help ? Thanks. |
El mismo error. |
I was having app crash, I am not using the .configure on the Main, I use on another class. I did delay de config and worked. Future.delayed(const Duration(milliseconds: 1000), () { |
can someone write Kotlin version of Application.java please? |
package com.example.projectname
import io.flutter.app.FlutterApplication
import io.flutter.plugin.common.PluginRegistry
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback
import io.flutter.plugins.GeneratedPluginRegistrant
import io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService
class Application : FlutterApplication(), PluginRegistrantCallback {
override fun onCreate() {
super.onCreate()
FlutterFirebaseMessagingService.setPluginRegistrant(this)
}
override fun registerWith(registry: PluginRegistry) {
GeneratedPluginRegistrant.registerWith(registry)
}
} That's how you can do it in Kotlin |
it's worked for me, Thanks!!! |
How do I access variables and other plugins from the background message handler? |
Any suggestion about this case please ? I have the same problem |
Hi @ifs-slaheddine, @hb0nes,
And then make your widget (e.g your root page) overrides didChangeAppLifecycleState to process any changes that happened in background.
In my case, I set a flag in shared preferences to determine if the freshly resumed app need to refresh data from webservices. Hope it will help you |
Yeah, a better way to communicate between isolates is to use receiveport
and sendport, in my opinion. I don't have access to our code now but that
was the most robust way. Registering a receiveport with a statically
declared name and using That name to get the instance of that port to send
stuff to, so that the listener can process the event/data. Good luck
…On Wed, Feb 12, 2020, 13:31 BazinC ***@***.***> wrote:
Hi @ifs-slaheddine <https://github.com/ifs-slaheddine>, @hb0nes
<https://github.com/hb0nes>,
like you i had a hard time managing to make background message handler
useful.
Backgound message handler runs in a different isolate, so you don't have
access to the Flutter UI memory.
So far the only workaround I found is to use persistent data with flutter
SharedPreferences.
Future<void> onBackgroundMessageHandler(Map<String, dynamic> message) async {
final prefs = await SharedPreferences.getInstance();
// SharedPreferences could have been modified in the UI isolate, so we have to fetch it from the host platform.
await prefs.reload();
// await prefs.getOrSetWhateverYouNeed();
}
And then make your widget (e.g your root page) overrides
didChangeAppLifecycleState to process any changes that happened in
background.
@OverRide
Future<void> didChangeAppLifecycleState(AppLifecycleState state) async {
if (state == AppLifecycleState.resumed) {
// Shared preferences
final prefs = await SharedPreferences.getInstance();
// Since the changes during background notification handler are made in a different isolate, we fetch the latest values from the host platform
await prefs.reload();
// Do what you want with prefs.
}
}
In my case, I set a flag in shared preferences to determine if the freshly
resumed app need to refresh data from webservices.
Hope it will help you
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#199>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AJIOJVJXPYP22GTVGWBT5ATRCPTZ7ANCNFSM4IZDYWKQ>
.
|
I did not try this way. I was not familiar with receive and send ports. Thanks for the tip :) |
Could everyone who still has this problem please file a new issue with the exact descriptions what happens, logs and the output of 'flutter doctor -v' please. |
I also think this should be clearer in the documentation |
My question is about the iOS part. |
When i try to run SharedPreferences in onBackgroundMessageHandler i will have the following error MissingPluginException(No implementation found for method getAll on channel plugins.flutter.io/shared_preferences) |
Define your shared preference plugin in application level. like Using above method you can show notification also. Am implemented in my project now am able to handle data messages and show notification from background_handler.Its working fine. |
Thank you. It's really worked to me. |
Throws error:
|
cast registry to (FlutterEngine) |
Again i need to write the same code, which was written for receive FCM. But outside the class. `Future myBackgroundMessageHandler(Map<String, dynamic> message) async { if (Platform.isAndroid) { var androidPlatformChannelSpecifies = new AndroidNotificationDetails(
return Future.value(flutterLocalNotificationsPlugin); |
Describe the bug
It took me about three hours to figure out why my background message handler wasn't working. The documentation says "Define a top level Dart method to handle background messages." This is confusing, since there are no top level "methods", only top-level functions. Naturally I defined a handler in my class (it works for onMessage, ought to work for onBackgroundMessage, right?) and had to dig through the flutter source to figure out the problem.
To Reproduce
Steps to reproduce the behavior:
The following NoSuchMethodError was thrown building Builder:
I/flutter (25669): The method 'toRawHandle' was called on null.
I/flutter (25669): Receiver: null
I/flutter (25669): Tried calling: toRawHandle()
Expected behavior
The documentation should be amended to indicate that the handler must be either a top level function, or a static method.
Thanks for the plugin!
The text was updated successfully, but these errors were encountered: