first time when i run my app and terminate it, my terminated notifications work good, but if i run it again and terminate, i got this error in my run terminal,
and my notification is not received. Is it flutter issue.
is this a flutter error or my api error?
Here is my terminated notification code
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
await Permission.notification.request();
await Permission.camera.request();
await Permission.microphone.request();
RemoteMessage? initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
await _messaging.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
I tried to reboot my computer, and restart my androidStudio, but it does not help.
Related
I am having issues with Flutter web when I use await statement,
void main() async {
//debugPaintSizeEnabled = true;
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
runApp(MyApp());
}
this will not display anything on the browser and throws and error:
ChromeProxyService: Failed to evaluate expression 'title': InternalError: Expression evaluation in async frames is not supported. No frame with index 39..
I am stuck :(
debugging testing nothing worked
Run flutter channel stable followed by flutter upgrade --force
When using Firebase, you need to initalize it with options for the specific platform that you are using. Here goes and example on how to configure it for Flutter Web:
import 'package:firebase_core/firebase_core.dart' show FirebaseOptions;
void main() async {
//debugPaintSizeEnabled = true;
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp(
options = FirebaseOptions(
apiKey: 'YOUR API KEY',
appId: 'YOUR APP ID',
messagingSenderId: 'YOUR MESSAGING SENDER ID',
projectId: 'YOUR PROJECT NAME',
authDomain: 'YOUR AUTH DOMAIN (IF YOU HAVE)',
databaseURL: 'YOUR DATABASE URL (IF YOU USE FIREBASEDATABASE)',
storageBucket: 'YOUR STORAGE BUCKET',
)
);
runApp(MyApp());
}
All this information is available on your Firebase Project Console, just search for it. Hope it helps!
In my flutter project, I already have notifications set up using firebase_messaging for Android and iOS. I am trying to add the same for Web. I had tried it before (mostly changing index.html with firebase-configs and initializing), but it had not worked then and I had left it. Now their document asks to use the new way, which asks only to configure it in the dart-files, and talks nothing about doing anything on index or other js files. So I have removed imports, and initialization from index.html, and not added any other file ( I have tried adding empty firebase-messaging-sw.js and removing it). This is the error I am getting:
[firebase_messaging/failed-service-worker-registration] Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker for scope ('http://localhost:44055/firebase-cloud-messaging-push-scope') with script ('http://localhost:44055/firebase-messaging-sw.js'): A bad HTTP response code (404) was received when fetching the script. .
What am I missing? Are those steps incomplete? I also tried the steps in this article , but still have the same issues.
Edit
These are all the code-parts related to firebase-messaging.
await Firebase.initializeApp(
options: DefaultFirebaseOptions.currentPlatform,
);
firebaseAnalytics = FirebaseAnalytics.instance;
firebaseMessaging = FirebaseMessaging.instance; //
final notificationSettings = await firebaseMessaging.requestPermission();
debugPrint('User granted permission: ${notificationSettings.authorizationStatus}');
if (!kIsWeb) {
FirebaseMessaging.onBackgroundMessage(
_firebaseMessagingBackgroundHandler);
channel = const AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
description: 'This channel is used for important notifications.',
// description
importance: Importance.max,
);
flutterLocalNotificationsPlugin = FlutterLocalNotificationsPlugin();
/// Create an Android Notification Channel.
///
/// We use this channel in the `AndroidManifest.xml` file to override the
/// default FCM channel to enable heads up notifications.
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
/// Update the iOS foreground notification presentation options to allow
/// heads up notifications.
await FirebaseMessaging.instance
.setForegroundNotificationPresentationOptions(
alert: true,
badge: true,
sound: true,
);
}
.
.
.
.
.
.
.
.
if (kIsWeb) {
// this is where the code throws error:
token = (await firebaseMessaging.getToken(
vapidKey: "BLn....pH8",
))!;
} else {
token = (await firebaseMessaging.getToken())!;
}
I have included Firebase Messaging in my app and I am getting the following error when I try to subscribe to topics.
FLTFirebaseMessaging: An error occurred while calling method Messaging#subscribeToTopic, errorOrNil => {
NSLocalizedFailureReason = "Invalid registration response :'Error=INVALID_PARAMETERS'. It is missing 'token' field.";
}
flutter: subscription error: [firebase_messaging/unknown] An unknown error has occurred.
As you can see it simply says "An unknown error has occurred", which is not very helpful to me.
Here is my code which is meant to obtain permissions for push notifications, then gets the token and subscribes to a list of topics...
Future<void> requestMessagingPermission() async {
FirebaseMessaging messaging = FirebaseMessaging.instance;
NotificationSettings settings = await messaging.requestPermission(
alert: true,
announcement: false,
badge: true,
carPlay: false,
criticalAlert: false,
provisional: false,
sound: true,
);
print('User granted permission: ${settings.authorizationStatus}');
if (settings.authorizationStatus == AuthorizationStatus.authorized) {
print('User granted notifiactions permission');
messaging.getToken().then((token) async {
print('Messaging token: $token');
//configure notification topics
//gets a list of strings (topic names) from provider and loops through them to subscribe to them all
GlobalProvider provider = context.read<GlobalProvider>();
if (provider.notificationTopicsSet == false) {
//subscribe to topics
for (var topic in provider.notificationTopics) {
print('topic subscribing... $topic');
try {
await messaging.subscribeToTopic(topic).then((value) => print('topic subscribed: $topic'));
} catch (e) {
print('subscription error: $e');
}
}
}
});
}
}
I am getting the same error in the console for every topic that is being looped through and subscribed to. The weird thing is that push notifications were working before, but now they don't seem to be.
I have tried updating Flutter to the latest version (3.3.7), I have tried updating both the Firebase Core package (2.1.1) and the Firebase messaging package to their latest versions (14.0.4) and I am still getting the error.
From pubspec.yaml:
firebase_core: ^2.1.1
firebase_messaging: ^14.0.4
What is this token that is missing? The subscribeToTopic() function only seems to take the topic name string. Am I missing something?
Thank you, any help will be greatly appreciated.
This ended up being only an issue with the iOS simulator. The error did not occur with the Android emulator and push notifications work fine on physical devices.
I'm working on a flutter delivery app and I want to integrate chat functionality and I found out that the StreamChat SDK is the best solution for that !
I already integrated the SDK and it's working , so to receive a notification when there is a new message I set up push notifications according to the docs in my flutter applications, when I test it up using stream CLI ,
I receive the notification and it also works when the app on the background but I don't receive anything when the app is closed and also nothing shows on the dashboard logs !
=====My code ========
await client.connectUser(
User(
id: sharedPreferences.getString('username'),
),
token,
);
var fcm = await FirebaseMessaging.instance.getToken();
await client.addDevice(fcm, PushProvider.firebase);
final channel = client.channel(
'messaging',
id: deliveryData['deliveryNumber'],
extraData: {
"name": deliveryData['title'],
},
);
final currentUserId = client.state.user.id;
client
.on(
EventType.messageNew,
EventType.notificationMessageNew,
)
.listen((event) async {
if (event.message?.user?.id == currentUserId) {
return;
}
final flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
final initializationSettingsAndroid =
AndroidInitializationSettings('launch_background');
final initializationSettings = InitializationSettings(
android: initializationSettingsAndroid,
);
await flutterLocalNotificationsPlugin
.initialize(initializationSettings);
await flutterLocalNotificationsPlugin.show(
event.message.id.hashCode,
'New message from : ' + event.message.user.name,
event.message.text,
NotificationDetails(
android: AndroidNotificationDetails(
'message channel',
'Message channel',
'Channel used for showing messages',
icon: '#drawable/notification',
priority: Priority.high,
importance: Importance.high,
),
),
);
});
I found the solution for that , the problem was that I used channel.watch(); instead, I should also add the user to the channel
channel.addMembers(["thierry", "josh"]); in order to receive push notifications as it is mentioned in the docs
Watchers vs Members
The concepts of watchers vs members can require a bit of clarification:
members: a permanent association between a user and a channel. If the
user is online and not watching the channel they will receive a
notification event, if they are offline they will receive a push
notification.
watchers: the list of watchers is temporary. It's anyone who is
currently watching the channel.
Being able to send messages, and otherwise engage with a channel as a non-member requires certain permissions. For example, we have pre-configured permissions on our livestream channel type to allow non-members to interact, but in the messaging channel type, only members of the channel can interact.
I do have a Snackbar with a SnackbarAction which should open the default email app with a default subject and body on tap. I am wondering if there is somehow the possibility to verify if this really happens with some unit tests.
My Snackbar code looks like this:
SnackBar get snackbar =>
SnackBar(
content: Text(message),
action: SnackBarAction(
key: const Key('ErrorSnackbarAction'),
label: AppLocalizations
.of(_context)
.report,
onPressed: () async => await launch('mailto:test#test.com?subject=TestSubject&body=TestBody')));
I am already verifying the appearance which works fine:
group('ErrorSnackbar', () {
testWidgets('appearance test', (WidgetTester tester) async {
await tester.pumpWidget(_generateSnackbarApp());
await _showSnackbar(tester);
expect(find.text(userMessage), findsOneWidget);
expect(find.byWidgetPredicate((Widget widget) =>
widget is SnackBarAction && widget.label == 'Report'), findsOneWidget);
});
testWidgets('error report test', (WidgetTester tester) async {
await tester.pumpWidget(_generateSnackbarApp());
await _showSnackbar(tester);
tester.tap(find.byKey(errorSnackbarAction));
await tester.pump();
// how to verify that the default email app was opened
// with expected subject and body?
});
});
Short answer: You can't.
The launch with mailto is handled by the OS of the device and is out of context of the flutter app.
As the flutter test package focuses on the flutter app, what happens on the OS is out of reach.
You can ensure that launchUrl is called and the expected parameters were passed. The url_launcher package should be tested. Therefore, we can expect that the email app opens, when we call launchUrl with the mailto: schema.
Here is a short introduction on how to test the url_launcher package:
Add plugin_platform_interface and url_launcher_platform_interface to your dev dependencies:
dev_dependencies:
flutter_test:
sdk: flutter
plugin_platform_interface: any
url_launcher_platform_interface: any
Copy the mock_url_launcher_platform.dart from the url_launcher package: https://github.com/flutter/plugins/blob/main/packages/url_launcher/url_launcher/test/mocks/mock_url_launcher_platform.dart
Now you can test the launchUrl calls like this:
void main() {
late MockUrlLauncher mock;
setUp(() {
mock = MockUrlLauncher();
UrlLauncherPlatform.instance = mock;
});
group('$Link', () {
testWidgets('calls url_launcher for external URLs with blank target',
(WidgetTester tester) async {
FollowLink? followLink;
await tester.pumpWidget(Link(
uri: Uri.parse('http://example.com/foobar'),
target: LinkTarget.blank,
builder: (BuildContext context, FollowLink? followLink2) {
followLink = followLink2;
return Container();
},
));
mock
..setLaunchExpectations(
url: 'http://example.com/foobar',
useSafariVC: false,
useWebView: false,
universalLinksOnly: false,
enableJavaScript: true,
enableDomStorage: true,
headers: <String, String>{},
webOnlyWindowName: null,
)
..setResponse(true);
await followLink!();
expect(mock.canLaunchCalled, isTrue);
expect(mock.launchCalled, isTrue);
});
});
}
Copied the test from https://github.com/flutter/plugins/blob/main/packages/url_launcher/url_launcher/test/link_test.dart
Unit test wise
I think the best way to test it is to wrap url launcher with your own class.
This way you can mock it and check that your logic calls your wrapper class function to launch the mail app. This should be enough.
As for the actual mail app or browser (in my case) you should trust the library todo what it supposed to so no need to unit test it really.