My flutter doctor is perfect.
I'm using firebase-admin on nodejs to send push notifications to users:
https://firebase.google.com/docs/admin/setup
I'm using firebase_messaging 6.0.13 on flutter:
https://pub.dev/packages/firebase_messaging
I'm trying to send a push notification with the highest priority on both android and ios.
firebase.messaging(firebaseApp).send({
token,
notification,
android: { priority: 'high' },
apns: { headers: { 'apns-priority': '10' }, payload: { aps: { sound: 'default' } } },
data
}
On my development devices it works like a charm both when the app is in the background and when it's terminated.
I'm receiving push notifications that visibly pop and make a sound 100% of the time, on both android and ios.
The issue is on other devices -
If the app is in the background, I can sometimes see an actual push notification visibly pop, and make a sound as it should. Sometimes not.
If the app is terminated, a push notification is received - but it doesn't visibly pop nor make a sound, I can only see it if I scroll down the menu from the top of the screen, it's listed as a received push notification.
Sometimes the notification is not receieved at all.
I tried to change the priority of notifications from my app to high on the actual device as well, but it didn't change anything.
My users keep complaining that they're not receiving push notifications - I'm guessing they either actually don't receieve them or simply don't see them since they're recieved silently as I described above.
I literally have no idea what's going on and why it doesn't work as it should on devices other than my own development devices.
Any ideas?
Hi @royibernthal
Is the issue on other devices are just android or both iOS and Android?
can you please provide your flutter doctor -v and flutter run --verbose?
Can you please your MainActivity and build.gradle?
Also, to better address the issue, would be helpful if you could post a minimal code sample to reproduce the problem
Thank you
Hi @TahaTesser
The issue is on both iOS and Android.
flutter doctor -v on the machine that compiles for android
[√] Flutter (Channel stable, v1.17.1, on Microsoft Windows [Version 10.0.18363.836], locale en-US)
• Flutter version 1.17.1 at D:\flutter
• Framework revision f7a6a7906b (9 days ago), 2020-05-12 18:39:00 -0700
• Engine revision 6bc433c6b6
• Dart version 2.8.2
[√] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
• Android SDK at C:\Users\royib\AppData\Local\Android\Sdk
• Platform android-29, build-tools 29.0.3
• ANDROID_HOME = C:\Users\royib\AppData\Local\Android\Sdk
• Java binary at: D:\Program Files\Android\Android Studio\jre\bin\java
• Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b04)
• All Android licenses accepted.
[√] Android Studio (version 3.6)
• Android Studio at D:\Program Files\Android\Android Studio
• Flutter plugin version 45.1.1
• Dart plugin version 192.8052
• Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b04)
I have a different machine for compiling ios, I can provide flutter doctor for that a bit later. There are no errors there though, is there other info you'd like to see there?
flutter run --verbose produces a very long log that gets cut in the terminal, is there any way for me to get the full log?
MainActivity.kt
package com.lumney
import androidx.annotation.NonNull;
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugins.GeneratedPluginRegistrant
class MainActivity: FlutterActivity() {
override fun configureFlutterEngine(@NonNull flutterEngine: FlutterEngine) {
GeneratedPluginRegistrant.registerWith(flutterEngine);
}
}
android/build.gradle
buildscript {
ext.kotlin_version = '1.3.50'
repositories {
google()
jcenter()
maven {
url 'https://maven.fabric.io/public'
}
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath 'com.google.gms:google-services:4.3.2'
classpath 'io.fabric.tools:gradle:1.26.1'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
android/app/build.gradle
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
apply plugin: 'io.fabric'
apply plugin: 'com.google.gms.google-services'
def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}
android {
compileSdkVersion 28
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
}
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
applicationId "com.lumney"
minSdkVersion 21
targetSdkVersion 28
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
signingConfigs {
release {
keyAlias keystoreProperties['keyAlias']
keyPassword keystoreProperties['keyPassword']
storeFile keystoreProperties['storeFile'] ? file(keystoreProperties['storeFile']) : null
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
release {
signingConfig signingConfigs.release
}
}
}
flutter {
source '../..'
}
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation 'com.google.firebase:firebase-messaging:20.1.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
}
I'm not sure how I could post a minimal code sample to reproduce the problem without creating a separate app on both flutter and firebase and testing it on many devices, and that'd be a huge task. Correct me if I'm wrong.
Same issue I am having currently
I have got the same problem. Push notifications show instantly on one iOS device (iPhone 5c, 10.3.3) and not at all if app is in background/terminated on other (iPhone 6S, 13.5). App was installed from the same archive through diawi in debug mode. On iPhone 6S onMessage() is called if app is in foreground or after resuming app.
It works fine both foreground and background on any Android I tested it on.
I won't be able to post flutter run --verbose because I'm working on commercial product. There is too much information reviled there and it is too long to anonymize it. If some can publish that kind of logs you can run flutter run --verbose | tee log.txt. It will save copy of console printed text to file.
[✓] Flutter (Channel stable, v1.17.1, on Mac OS X 10.15.4 19E287, locale en-GB)
• Flutter version 1.17.1 at /Users/X/flutter
• Framework revision f7a6a7906b (13 days ago), 2020-05-12 18:39:00 -0700
• Engine revision 6bc433c6b6
• Dart version 2.8.2
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
• Android SDK at /Users/X/Library/Android/sdk
• Platform android-R, build-tools 29.0.3
• ANDROID_HOME = /Users/X/Library/Android/sdk
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.5, Build version 11E608c
• CocoaPods version 1.8.4
[✓] Android Studio (version 3.6)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 45.1.1
• Dart plugin version 192.7761
• Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b4-5784211)
I am also experiencing the same issue on Android. When the app is in the foreground, notifications are handled in the onMessage handler. When the app is in the background, notifications appear in the system tray. But when the app is killed/terminated, nothing happens.
Try to remove all notification attributes from the payload of send requests and use only the data attribute with default information like title and body. Maybe this will work. Something like this:
HTTP v1 version
{
"message": {
"token": "DEVICE_TOKEN",
"data": {
"title": "title",
"body": "body",
"image": "IMAGE_URL",
"click_action" : "FLUTTER_NOTIFICATION_CLICK"
},
"android": {
"priority" : "HIGH"
},
"apns": {
"headers": {
"apns-priority": "10"
}
}
}
}
Legacy version
{
"to" : "DEVICE_TOKEN",
"priority" : "high",
"content_available" : true,
"data" : {
"body" : "body",
"title": "title",
"click_action" : "FLUTTER_NOTIFICATION_CLICK",
"image" : "IMAGE_URL"
}
}
Try to remove all notification attributes from the push send and use only the data attribute with default information like title and body. Maybe this will work. Something like this:
HTTP v1 version
{ "message": { "token": "DEVICE_TOKEN", "data": { "title": "title", "body": "body", "image": "IMAGE_URL", "click_action" : "FLUTTER_NOTIFICATION_CLICK" }, "android": { "priority" : "HIGH" }, "apns": { "headers": { "apns-priority": "10" } } } }Legacy version
{ "to" : "DEVICE_TOKEN", "priority" : "high", "content_available" : true, "data" : { "body" : "body", "title": "title", "click_action" : "FLUTTER_NOTIFICATION_CLICK", "image" : "IMAGE_URL" } }
Wouldn't omitting the notification key result in a data-only notification which by definition will not be visually displayed to the user?
Have you tried that?
Yes, here is working. After remove the notification attribute you can use the plugin flutter_local_notifications to show a big picture notification in place, for example. But I haven't tested this on iOS.
Are you calling flutter_local_notifications in firebase_messaging's onBackgroundMessage?
If so, from my previous experience with it there are many problems with it, so I'm a bit hesitant.
If not, how do you use flutter_local_notifications when the app is terminated?
Also, shouldn't firebase_messaging just work on its own out of the box? I feel like it shouldn't be this complicated to receive push notifications.
Here is my files:
NotificationsHandler.dart
import 'dart:async';
import 'dart:io';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
import 'package:http/http.dart';
import 'package:rxdart/rxdart.dart';
import 'package:path_provider/path_provider.dart';
// Streams are created so that app can respond to notification-related events since the plugin is initialised in the `main` function
final BehaviorSubject<ReceivedNotification> didReceiveLocalNotificationSubject =
BehaviorSubject<ReceivedNotification>();
final BehaviorSubject<String> selectNotificationSubject =
BehaviorSubject<String>();
class ReceivedNotification {
final int id;
final String title;
final String body;
final String payload;
ReceivedNotification({
@required this.id,
@required this.title,
@required this.body,
@required this.payload,
});
}
class SecondScreen extends StatefulWidget {
SecondScreen(this.payload);
final String payload;
@override
State<StatefulWidget> createState() => SecondScreenState();
}
class SecondScreenState extends State<SecondScreen> {
String _payload;
@override
void initState() {
super.initState();
_payload = widget.payload;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('test')),
body: Center(
child: RaisedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text('${(_payload ?? '')} Go back!'),
),
),
);
}
}
class NotificationsHandler {
void _configureDidReceiveLocalNotificationSubject(BuildContext context) {
didReceiveLocalNotificationSubject.stream
.listen((ReceivedNotification receivedNotification) async {
await showDialog(
context: context,
builder: (BuildContext contex2) => AlertDialog(
title: receivedNotification.title != null
? Text(receivedNotification.title)
: null,
content: receivedNotification.body != null
? Text(receivedNotification.body)
: null,
actions: [
FlatButton(
child: Text('Ok'),
onPressed: () async {
Navigator.of(context, rootNavigator: true).pop();
await Navigator.push(
context,
MaterialPageRoute(
builder: (context2) =>
SecondScreen(receivedNotification.payload),
),
);
},
)
],
),
);
});
}
void _configureSelectNotificationSubject(BuildContext context) {
selectNotificationSubject.stream.listen((String payload) async {
await Navigator.push(
context,
MaterialPageRoute(builder: (context2) => SecondScreen(payload)),
);
});
}
NotificationAppLaunchDetails notificationAppLaunchDetails;
FirebaseMessaging fcm = FirebaseMessaging();
StreamSubscription iosSubscription;
NotificationsHandler();
initializeFcmNotification(BuildContext context) async {
_configureDidReceiveLocalNotificationSubject(context);
_configureSelectNotificationSubject(context);
fcm.configure(
onMessage: (Map<String, dynamic> message) async {
debugPrint("[initializeFcmNotification] onMessage: $message");
message['data']['callback'] = 'onMessage';
_showBigTextNotification(message);
},
onBackgroundMessage: Platform.isIOS ? null : _myBackgroundMessageHandler,
onLaunch: (Map<String, dynamic> message) async {
debugPrint("[initializeFcmNotification] onLaunch: $message");
await Navigator.push(
HERE_I_USED_A_STATIC_BUILDCONTEXT_VAR,
MaterialPageRoute(builder: (context2) => SecondScreen('onLaunch')),
);
},
onResume: (Map<String, dynamic> message) async {
debugPrint("[initializeFcmNotification] onResume: $message");
await Navigator.push(
HERE_I_USED_A_STATIC_BUILDCONTEXT_VAR,
MaterialPageRoute(builder: (context2) => SecondScreen('onResume')),
);
},
);
var initializationSettingsAndroid = AndroidInitializationSettings('ic_launcher_foreground');
// Note: permissions aren't requested here just to demonstrate that can be done later using the `requestPermissions()` method
// of the `IOSFlutterLocalNotificationsPlugin` class
var initializationSettingsIOS = IOSInitializationSettings(
onDidReceiveLocalNotification:
(int id, String title, String body, String payload) async {
didReceiveLocalNotificationSubject.add(ReceivedNotification(
id: id, title: title, body: body, payload: payload));
});
var initializationSettings = InitializationSettings(
initializationSettingsAndroid, initializationSettingsIOS);
await FlutterLocalNotificationsPlugin().initialize(initializationSettings,
onSelectNotification: (String payload) async {
if (payload != null) {
debugPrint('notification payload: ' + payload);
}
selectNotificationSubject.add(payload);
});
if (Platform.isIOS) {
iosSubscription = fcm.onIosSettingsRegistered.listen((data) {
// save the token OR subscribe to a topic here
});
fcm.requestNotificationPermissions(IosNotificationSettings());
} else {
_saveDeviceToken();
}
}
static Future<dynamic> _myBackgroundMessageHandler(Map<String, dynamic> message) async {
debugPrint("[myBackgroundMessageHandler] onBackgroundMessage: $message");
message['data']['callback'] = 'onBackgroundMessage';
_showBigTextNotification(message);
// Or do other work.
return Future<void>.value();
}
static Future<String> _downloadAndSaveFile(String url, String fileName) async {
Directory directory = await getTemporaryDirectory();
var filePath = '${directory.path}/$fileName';
var response = await get(url);
var file = File(filePath);
await file.writeAsBytes(response.bodyBytes);
return filePath;
}
static Future<void> _showBigTextNotification(Map<String, dynamic> message) async {
var largeIconPath = await _downloadAndSaveFile(
message['data']['image'], 'largeIcon');
var bigTextStyleInformation = BigTextStyleInformation(
'${message['data']['body']}',
htmlFormatBigText: true,
contentTitle: '${message['data']['title']}',
htmlFormatContentTitle: true,
//summaryText: '$summary',
);
var androidPlatformChannelSpecifics = AndroidNotificationDetails(
'0',
'${message['data']['title']}',
'${message['data']['body']}',
enableLights: true,
color: Color(int.parse(message['data']['mainColor'], radix: 16) + 0xFF000000),
largeIcon: FilePathAndroidBitmap(largeIconPath),
ledOnMs: 1000,
ledOffMs: 500,
importance: Importance.High,
priority: Priority.High,
ledColor: Color(int.parse(message['data']['secondaryColor'], radix: 16)),
ticker: 'ticker',
styleInformation: bigTextStyleInformation,
);
var iOSPlatformChannelSpecifics =
IOSNotificationDetails(attachments: [IOSNotificationAttachment(largeIconPath)]);
var platformChannelSpecifics =
NotificationDetails(androidPlatformChannelSpecifics, iOSPlatformChannelSpecifics);
await FlutterLocalNotificationsPlugin().show(
0, '${message['data']['title']}', '${message['data']['body']}', platformChannelSpecifics, payload: message['data']['callback']);
}
/// Get the token, save it to the database for current user
_saveDeviceToken() async {
debugPrint("[_saveDeviceToken] FCM_TOKEN: ${await fcm.getToken()}");
}
Future<void> onDidReceiveLocalNotification(
int id, String title, String body, String payload) async {
// display a dialog with the notification details, tap ok to go to another page
}
}
Application.java
package PACKAGE_NAME;
import io.flutter.app.FlutterApplication;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugin.common.PluginRegistry.PluginRegistrantCallback;
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) {
FirebaseCloudMessagingPluginRegistrant.registerWith(registry);
}
}
FirebaseCloudMessagingPluginRegistrant.java
package PACKAGE_NAME;
import io.flutter.plugin.common.PluginRegistry;
import io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin;
import io.flutter.plugins.pathprovider.PathProviderPlugin;
import com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin;
public final class FirebaseCloudMessagingPluginRegistrant{
public static void registerWith(PluginRegistry registry) {
if (alreadyRegisteredWith(registry)) {
return;
}
io.flutter.plugins.pathprovider.PathProviderPlugin.registerWith(registry.registrarFor("io.flutter.plugins.pathprovider.PathProviderPlugin"));
com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin.registerWith(registry.registrarFor("com.dexterous.flutterlocalnotifications.FlutterLocalNotificationsPlugin"));
FirebaseMessagingPlugin.registerWith(registry.registrarFor("io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin"));
}
private static boolean alreadyRegisteredWith(PluginRegistry registry) {
final String key = FirebaseCloudMessagingPluginRegistrant.class.getCanonicalName();
if (registry.hasPlugin(key)) {
return true;
}
registry.registrarFor(key);
return false;
}
}
Got it. So yeah, you're doing exactly that :) You're calling flutter_local_notifications in firebase_messaging's onBackgroundMessage.
I suppose it wouldn't even work on IOS due to the simple fact that onBackgroundMessage is not supported on IOS. Let's even pretend for a moment that it doesn't have issues on Android.
Any update?
Still researching and testing this to no avail. I'm hoping one of the plugin creators / moderators will step in at some point.
Any update from the team, please?
Push notifications without this feature is almost nothing.
having the same issue. I also tried pushing notifications from firebase console(FCM) but cannot get the notifications when the app is terminated.
On android you have to make sure you're setting up notification channels on the device and then sending push notifications to those channels, either from your backend or frontend (though frontend is not a good practice).
firebase_messaging package for flutter doesn't take care of that for you.
I personally decided to move the whole project to OneSignal, it's free and it handles everything for me without any headaches, plus normal customer support.
Since I moved to OneSignal I no longer have any issues with push notifications.
Feels like I'm writing an ad, but I guess they deserve it, I'm a satisfied customer.
moving the whole project now could be very difficult for me. On the tutorials i never seen anything about setting up notification channels on the device. I believe its something with my code.
The migration was actually very easy.
Well, that's a big part of the problem, I had to dig deep in order to understand what was wrong.
Maybe something is wrong with your code as you say, but there's a good chance that your code is okay and you're just missing this piece of the puzzle, which is hardly mentioned anywhere for some reason.
Anyway, these are my 2 cents as someone who's been struggling with this for a long time :)
When app is in foreground, and background i receive the notifications perfectly. But when the app is completely terminated i don't.
Cannot be with data or notification because i am trying using the Firebase Console: Cloud Messaging, Compose notification, but only when the app is foreground or in stacks not terminated.
I followed all instructions from the firebase read me and some tutorials.
Android Manifest:
`
<meta-data android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="@string/default_notification_channel_id"/>`
android/app/build.gradle
implementation 'com.google.firebase:firebase-messaging:20.2.4'
android/build.gradle
classpath 'com.android.tools.build:gradle:3.5.3' classpath 'com.google.gms:google-services:4.3.3'
Pubs
firebase_messaging: ^6.0.16
When i push the notification when the app is in background (not terminated but in stack).
I get a message:
Missing Default Notification Channel metadata in AndroidManifest. Default value will be used
Flutter doctor:
Run flutter doctor and paste the output below:
[✓] Flutter (Channel stable, v1.17.5, on Mac OS X 10.14.6 18G103, locale en-TZ)
• Flutter version 1.17.5 at /Users/mac/Documents/FlutterSDK/flutter
• Framework revision 8af6b2f038 (5 weeks ago), 2020-06-30 12:53:55 -0700
• Engine revision ee76268252
• Dart version 2.8.4
[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
• Android SDK at /Users/mac/Library/Android/sdk
• Platform android-29, build-tools 29.0.3
• Java binary at: /Applications/Android Studio.app/Contents/jre/jdk/Contents/Home/bin/java
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 11.3.1)
• Xcode at /Applications/Xcode.app/Contents/Developer
• Xcode 11.3.1, Build version 11C505
• CocoaPods version 1.8.4
[✓] Android Studio (version 3.5)
• Android Studio at /Applications/Android Studio.app/Contents
• Flutter plugin version 43.0.1
• Dart plugin version 191.8593
• Java version OpenJDK Runtime Environment (build 1.8.0_202-release-1483-b49-5587405)
[✓] VS Code (version 1.46.1)
• VS Code at /Applications/Visual Studio Code.app/Contents
• Flutter extension version 3.12.2
[✓] Connected device (1 available)
• TECNO KB7j • 044033396I137857 • android-arm • Android 9 (API 28)
• No issues found!
@braysonjohn148 I'm having exactly the same issue. Did you manage to solve your issue? If so, i'd be really eager to know how if you mind sharing!
Hi all,
I managed to solve the issue with no exceptions in the devices I tried it on.
The problem related to Android is that I had a device that doesn't allow notifications to work in the background, and it's solved by turning on some options in the device itself. the option is Allow running in background.
The problems related to iOS is that for some reason I needed to add rows to ios/Runner.xcodeproj/project.pbxproj file related to Runner.entitlements manually because I don't have macOS.
Up to now, everything works fine. but this doesn't mean I solved the issue for all devices because, as you know, I don't have all available devices to test on.
I hope it gets fixed for you guys.
Thanks
The problem related to Android is that I had a device that doesn't allow notifications to work in the background, and it's solved by turning on some options in the device itself. the option is Allow running in background.
That's great, thank you for sharing! :)
But....
going the Allow running in background does mean your app will consume (much more) battery as it keeps running. So perhaps this route is not advisable.
Yea, it's true.
But the phone doesn't receive any notification neither from my app nor from other apps.
I'd like to know if there is any other possible solution.
same issue here !
any update ?
Guys, I'm ashamed to say this, but for me, my test Droid device was running under "no disturb mode", so everything was just going to control center, no sound, no vibration, no pop ups.
As soon as I turned it off, all started working as expected.
🤦
This worked for me! :
AndroidManifest.xml
<application
android:name=".App" //ADD THIS LINE
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name">
App.kt
package com.leher
import io.flutter.app.FlutterApplication
///This is used in AndroidManifest.xml
class App : FlutterApplication() {
override fun onCreate() {
super.onCreate()
//XYZ
}
}
Any luck?
Not sure if this is the same but throwing this in to help others who have the same issue , for me I had the notification shows onMessage and onResume, however the onLaunch only shows notification in control, tapping on that opens the app only when terminated,
the issue for me was the app needs time to run with the splash screen which prevented the app from running the notification correctly in app:
this helped me:
import 'package:flutter/scheduler.dart';
// call back on background message
onBackgroundMessage:
Platform.isAndroid ? myBackgroundMessageHandler : null,
onLaunch: (Map<String, dynamic> msg) async {
// give time for splashscreen to run and finish before it's done.
SchedulerBinding.instance
.addPostFrameCallback((_) => _showNotification(msg));
},
same issue here !
any update ? some workaround ?
Finally, I found a workaround for notification when the app is killed or terminated
1). I just added a new file called App.java inside the folder java/[com]/[yourdomain]
package [com].[yourdomain];
import io.flutter.app.FlutterApplication;
public class App extends FlutterApplication {
@Override
public void onCreate() {
super.onCreate();
}
}
2) Then, I added the android:name=".App" inside my AndroidManifest.xml file.
<application
android:name=".App"
...
>
Run the application again and the notifications working correctly with the app terminated or killed
I hope this can help you too.
OneSignal
I also implemented that. But still got the problem of not receiving notification when app was killed completely
Issue still appearing on firebase_messaging 8.0.0-dev.8. Only on Android though.
I am also experiencing the same issue on Android. When the app is in the foreground, notifications are handled in the
onMessagehandler. When the app is in the background, notifications appear in the system tray. But when the app is killed/terminated, nothing happens.
any update???
Finally, I found a workaround for notification when the app is killed or terminated
1). I just added a new file called
App.javainside the folderjava/[com]/[yourdomain]package [com].[yourdomain]; import io.flutter.app.FlutterApplication; public class App extends FlutterApplication { @Override public void onCreate() { super.onCreate(); } }
- Then, I added the
android:name=".App"inside myAndroidManifest.xmlfile.<application android:name=".App" ... >Run the application again and the notifications working correctly with the app terminated or killed
I hope this can help you too.
I Really can't see how this could solve anything here.
So after 1year of continuous searching for the solution to that problem, researched al lot, talked to many developers. It has NO solution eventually. It totally depends on the manufacturer of mobile phone.
How ever if any one knows how telegram, facebook and whatsapp is doing to send notifications please let us know. Thank you.
I found the solution for my problem, which was: notifications appear silently ON ANDROID when the app is in the background or terminated.
The problem appeared on every phone (==2) I had and the fix solves the issue for both phones.
Beware that I use firebase_messaging: 8.0.0-dev.11.
The key solution can be found here.
I don't know why I didn't try that before, maybe is this a new documentation page, but I never came across this section in any tutorial/fix. In any case I don't see why this is burred under "advance usage" while I think displaying the incoming notifications when the app is in the background or terminated should be the default behaviour.
I will copy the instructions and a small reproducible example here in case the link brakes.
Instructions
The main idea is the following: > On Android, notification messages are sent to Notification Channels which are used to control how a notification is delivered. **The default FCM channel** used is hidden from users, however **provides a "default" importance level**. **Heads up notifications require a "max" importance level**. So we need to create a high importance channel through the [flutter_local_notifications](url) package. To do so we: 1. Add the flutter_local_notifications package to your local project. 2. Create a new AndroidNotificationChannel instance:
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
'This channel is used for important notifications.', // description
importance: Importance.max,
);
3. Create the channel on the device (if a channel with an id already exists, it will be updated):
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
Once created, we can now update FCM to use our own channel rather than the default FCM one. To do this, open the android/app/src/main/AndroidManifest.xml file for your FlutterProject project. Add the following meta-data schema within the application component:
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="high_importance_channel" />
Reproductible example
**main.dart**
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
FirebaseMessaging messaging = FirebaseMessaging.instance;
print(await messaging.getToken());
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
'This channel is used for important notifications.', // description
importance: Importance.max,
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print('Got a message whilst in the foreground!');
print('Message data: ${message.data}');
if (message.notification != null) {
print('Message also contained a notification: ${message.notification}');
}
});
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
}
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
print("Handling a background message: ${message.messageId}");
}
Future selectNotification(String payload) {
print("selectNotification. payload: $payload");
}
Future onDidReceiveLocalNotification(int id, String title, String body, String payload) {
print("onDidReceiveLocalNotification. payload: $payload");
}
class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;
void _incrementCounter() {
setState(() {
_counter++;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Title'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'You have pushed the button this many times:',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.headline4,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}
pubspec.yaml
name: flutter_test_fcm
description: A new Flutter application.
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
version: 1.0.0+1
environment:
sdk: ">=2.7.0 <3.0.0"
dependencies:
flutter:
sdk: flutter
firebase_core: "^0.5.3"
firebase_messaging: "^8.0.0-dev.11"
flutter_local_notifications: ^3.0.2
dev_dependencies:
flutter_test:
sdk: flutter
flutter:
uses-material-design: true
**AndroidManifest.xml**
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="lulupointu.flutter_test_fcm">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<application
android:name="io.flutter.app.FlutterApplication"
android:label="flutter_test_fcm"
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">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<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>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
<meta-data
android:name="com.google.firebase.messaging.default_notification_channel_id"
android:value="high_importance_channel" />
</application>
</manifest>
Beware that you also need to initialize firebase and place the google-services.json in Hopes this helps you as much as this helped me, I was searching for a solution for 6 month!
Most helpful comment
Any update from the team, please?
Push notifications without this feature is almost nothing.