Flutter Drive tests crashes on OS pop-ip (e.g. notification consent) - flutter

I am using Flutter Drive for integration tests. The tests works well until app shows push notification consent. It seems Flutter Drive doesn't recognise the pop-up by iOS and crashes it there.
takeScreenshot(driver,"screenshots/01.login_screen_initial.png");
await driver.tap(tfUserId);
await driver.enterText('100111');
await driver.tap(tfPassword);
await driver.enterText('abc');
takeScreenshot(driver,"screenshots/02.login_screen_before_button_tap.png");
await driver.tap(loginButton);
After this button tap, the app asks for push notification consent. And the following code never gets executed.
takeScreenshot(driver,"screenshots/03.login_screen_just_after_button_tap.png");
await driver.waitForAbsent(btnHRDirectory,timeout: Duration(seconds: 360));
takeScreenshot(driver,"screenshots/04.dashboard_screen.png");
I get error as :
[VERBOSE-2:rasterizer.cc(307)] Last layer tree was null when screenshotting.
Detailed error is here.

The issue was somewhere in the script. driver.WaitFor along with timeout duration helps. No problem for the pop-up as Flutter Drive waits for the pop-up to vanish.

Related

Flutter Local notifications - notification click is not working while the app in background

When application killed then notification click not working account to onSelectNotification and also big picture image notification not working when app in background.
flutterLocalNotificationsPlugin.initialize(initializationSettings,
onSelectNotification: (action) {})
Handle background messages by registering a onBackgroundMessage handler. When messages are received, an isolate is spawned (Android only, iOS/macOS does not require a separate isolate) allowing you to handle messages even when your application is not running. try this:
#pragma('vm:entry-point')
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
// If you're going to use other Firebase services in the background, such as Firestore,
// make sure you call `initializeApp` before using other Firebase services.
await Firebase.initializeApp();
print("Handling a background message: ${message.messageId}");
}
void main() {
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
runApp(MyApp());
}
follow full documentation here: https://firebase.google.com/docs/cloud-messaging/flutter/receive
There is no such thing as "in the background" with mobile devices. Mobile devices run one foreground app. When you "put it in the background" it is closed and a screenshot is kept to make you think it's "in the background". It's not. It's closed.
So it does not work when it's closed. That's normal. Because the app isn't running, it cannot execute code.
The app has first to be started again. To find out, whether your app was started by tapping a notification, you can use this line in your start up code:
final NotificationAppLaunchDetails notificationAppLaunchDetails =
await flutterLocalNotificationsPlugin.getNotificationAppLaunchDetails();
Source: Documentation
This way you can find out if your app was started from your notification and then act accordingly (for example by navigating to a different route depending on those details).

FirebaseMessaging getInitialMessage keeps old behavior despite changing the code

I am testing how my Flutter app handles notification using my Samsung Android 12 phone and Firebase Messaging campaign.
I have gotten this code (simplified) to work for a month and notification is handled properly.
FirebaseMessaging.instance.getInitialMessage().then((message) {
if (message != null) {
String? routeName = message.data["route"];
if (routeName != null) {
Navigator.of(context).pushNamed(routeName);
}
}
});
However, today when I wanted to change how handling notification works, I found out that the changes I made to this code are not reflected in the app when debugging through Flutter. Opening the app from a terminated state through the notification still behaves according to the old code above.
I have tried many things:
Uninstalling the app on Android
Removing all code related to Firebase Messaging
Clearing all app cache and data
But the app still keeps the behavior of the old code. Is there anything I can do to reset the behavior of FirebaseMessaging.instance.getInitialMessage() ?

How to wait for a Flutter app to open before navigating to a particular page by clicking a scheduled notification?

I'm working on a Flutter project where I had to set a scheduled local notification that would fire everyday at 10 am. And, the user should be taken to a certain page of the app upon clicking the notification.
I've completed this part and the functionality works fine when the app is open and the user clicks on the notification.
But the problem arises when the app is closed and the notification is fired and the user clicks on the notification. It doesn't take the user to that certain page. I tried to modify the click handling function by making it an async function. But it doesn't work accordingly.
Can someone suggest me what to do now?
Create a notification handler.
Initialize your notification channel with high importance
Just before your app runs, before runApp(yourApp), create call a foregroundMessageHandler that you have initialized before the void main(){}
the foregroundMessageHandler should be a *TopMost initialization.
in the foregroundMessageHandler function, define the navigation behaviour
I don't know which library you are using for local notifcations. but if you are using flutter_local_notifications library check the link: https://pub.dev/packages/flutter_local_notifications
, you can check the data recived in selectNotification method and redirect the user to required page
void selectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
await Navigator.push(
context,
MaterialPageRoute<void>(builder: (context) => SecondScreen(payload)),
);
}
other libraries should have same functionality.

Flutter firebase messaging v9.0.0 - Not firing events

I have an app that was using firebase messaging 7.0.3 and all worked perfectly. But when I migrated to firebase messaging 9.0.0, the push notifications are not being handled.
I know that the app is correctly linked to firebase and cloud messaging because in background I see the push notification comming, the problem is when I click that notification the app don't handle this event. Also, when the app is in foreground, the event of receiving the notification is not being triggered.
Specifically, the functions FirebaseMessaging.onMessage and FirebaseMessaging.onMessageOpenedApp are not working. My code is:
FirebaseMessaging.onMessage.listen((RemoteMessage message) {
print("notification: message");
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) {
print("notification: resume");
});
The prints are never called, and if I put some more code inside isn't executed too.
I also call FirebaseMessaging.getToken and I can get the token, plus when the app is in background I get the push notification, so is not a link problem with firebase. In the logs, when I receive the push I can see a message saying: Broadcast received for message. So I assumed that the push is arriving in all the occasions, and I am doing something wrong in the code.
I tested all cases in Android and iOS physical devices.
Someone know why this occurs?
I came across this exact same issue after migrating and upgrading to 9.0.0.
There is a minor issue with 9.0.0 plugin.
The fix can be found here:
https://github.com/FirebaseExtended/flutterfire/issues/4949
To cut a long story short, if you navigate to the definition of the factory
RemoteMessage.fromMap() Using Cmd+Click or Ctrl+Click while hovering over the RemoteMessage class with the mouse), in the return statement, change contentAvailable: map['contentAvailable'], to contentAvailable: map['contentAvailable']??false.
Notifications are now working for me again now.
This should work for you until the plugin is fixed.

Why is onTokenRefresh not firing?

I'm new to firebase messaging and flutter. According to the flutter firebase_messaging package docs, onTokenRefresh is fired when a new FCM token is generated. And according to Google's firebase docs there are two scenarios that triggers token generation:
When a new token is generated on initial app startup
Whenever an existing token is changed
Here is a simplified version of the main function of my application. After each execution, I delete the app from the emulator and the displayed token does indeed change. Despite this, onTokenRefresh is never fired and it should if my understanding of the documentation is correct.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await Firebase.initializeApp();
FirebaseMessaging.instance.onTokenRefresh.listen((String token) {
print("New token: $token");
});
String token = await FirebaseMessaging.instance.getToken();
print("Token: $token");
//runApp(MyApp());
}
As I said, I'm new to flutter, dart and firebase messaging, is there something I'm fundamentally misunderstanding? Thanks.
So I think I figured it out. I noticed that sometimes, the onTokenRefresh does indeed fire. And I was wondering if it had something to do with how the flutter application is launched onto the emulator, in the sense that there is a race condition between when the token is generated and the listener attached.
To get the app to appear to start for the first time, I wiped the app data. Unfortunately this causes the flutter to automatically disconnect from the app which means I won't see the output of the print statement. So instead of trying to print when the token generation occurs, I assigned a value from the onTokenRefresh listener to a variable. I then updated a text widget with the value of the variable. And onTokenRefresh does indeed fire each time at start up if the app data has previously been wiped.