[Flutter/dart] When Firebase Messaging notification is tapped with the app is in the background
Overview
In many cases, you'll send a message with Firebase Messaging and take some action when the notification is tapped (eg to go to a specific page).
It's easy if the app is in the foreground state (that is, the app is open) when the notification is tapped, but if the app is in the background state, some ingenuity is required.
Method
Is FirebaseMessaging.onBackgroundMessage () useless?
Firebase Messaging provides a method called onBackgroundMessage (). You might think that you can pass the method you want to execute when tapping the notification to this argument (hereinafter referred to as onBackGround)? However, there are the following problems.(reference)
onBackgroundMessage () runs when the notification comes, not when a user taps the notification. In other words, when onBackGround () is executed, the app is not open yet, so you cannot do something like screen transition.
onBackGround () needs to be a top-level function. That is, you cannot perform any action based on the state of a particular instance.
onBackGround () is executed by another isolate. Since dart doesn't share memory between isolates, you can't directly rewrite the main isolate variable.
Solution
Take the following actions.
Add the variable "resumeState" to the top level that represents the state when the application is restarted. Set the value to 0 at initialization. Set resumeState to 1 in onBackGround () (*).
Determine the value of resumeState when the app is restarted. If 1, the desired process is executed.
In the (*) part, change the value of the variable resumeState of another isolate using port.
This will solve all of the above issues.
We will look at the details below.
1 Add the variable "resumeState" to the top level that represents the state when the application is restarted
For dart, variables can be defined not only in the class but also at the top level.
void main() async{
runApp(MyApp());
}
int resumeState=NOMAL_RESUME;
const NOMAL_RESUME=0;
const ON_NOTIFICATION_TAP=1;
2 Determine the value of resumeState when the app is restarted. If 1, the desired process is executed.
The procedure to perform some action when restarting the application in dart is as follows.
Implement WidgetsBindingObserver with any widget (or state)
Override didChangeAppLifecycleState().This method is called when the life cycle of the app changes.
Since the argument "state" is AppLifecycleState.resumed when the application is restarted , the desired process is executed in this case (corresponding to onResume () on Android).
class basePageState extends State<basePage> with WidgetsBindingObserver{
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
if (state==AppLifecycleState.resumed){
if (resumeState==ON_NOTIFICATION_TAP) {
//Write the desired process here!
resumeState=NOMAL_RESUME;
}
}
}
}
3 change the value of the variable resumeState of another isolate using port
As mentioned above, since onBackGround is executed in another isolate, resumeState defined in main isolate cannot be directly rewritten. Use port to exchange information between isolates. (reference)
Specifically, do as follows.
Send an appropriate string from SendPort indicating that onBackGround () was called.
If the above string is received by ReceivePort, change resumeState to 1.
static const String BG_PORT_NAME="bg_port";
static const String BG_MESSAGE="bg_message";
Future<void> onBackGround(RemoteMessage message)async{
final port=IsolateNameServer.lookupPortByName(BG_PORT_NAME);
port.send(BG_MESSAGE);
}
void setBackGroundHandling(){
ReceivePort backgroundMessagePort=ReceivePort();
IsolateNameServer.registerPortWithName(
backgroundMessagePort.sendPort, BG_PORT_NAME);
backgroundMessagePort.listen((message) {
if (message.toString()==BG_MESSAGE){
resumeState=ON_NOTIFICATION_TAP;
}
});
}
void main() async{
//・・・
FirebaseMessaging.onBackgroundMessage(onBackGround);
setBackGroundHandling();
runApp(MyApp());
}
With the above support, you will be able to execute the operation when tapping the notification even when the application is in the background state.
Recent Posts
See AllWhat want to do I want to create an input form using TextField. For example, if the input content is a monetary amount, I would like to...
What want to do There is a variable that remain unchanged once the initial value is determined. However, it cannot be determined yet when...
What want to do As the title suggests. Place two widgets in one line on the screen One in the center of the screen and the other on the...
Comments