Issue
I am having a hard time navigating to a screen when a background FCM message receives. Currently, I am sending an FCM message with some data and when it gets received by a device then it calls this package that shows a calling notification, and when the user clicks on accept call option then I want to open my app and navigate to the desired screen. I use GetX for navigation and when I try to go to another screen it gives this exception:
I have tried almost everything to work this out but I am still unable to solve this problem.
my FirebaseMessaging.onBackgroundMessage Background handler which receives the notification also listens to user feedback on whether the call is accepted or rejected:
Future<void> firebaseMessagingBackgroundHandler(RemoteMessage message) async {
var incoming = <String, dynamic>{
'id': message.data['callerID'],
'nameCaller': message.data['callerName'],
'appName': 'Callkit',
'avatar': message.data['callerImage'],
'handle': '',
'type': 0,
'duration': 30000,
'extra': <String, dynamic>{'userId': '1a2b3c4d'},
'headers': <String, dynamic>{'apiKey': 'Abc@123!', 'platform': 'flutter'},
'android': <String, dynamic>{
'isCustomNotification': true,
'isShowLogo': false,
'ringtonePath': 'ringtone_default',
'backgroundColor': '#0955fa',
//'backgroundUrl': 'https://i.pravatar.cc/500',
'actionColor': '#4CAF50'
}};
await FlutterCallkitIncoming.showCallkitIncoming(incoming);
try {
FlutterCallkitIncoming.onEvent.listen((event) {
switch (event!.name) {
case CallEvent.ACTION_CALL_INCOMING:
print('INCOMING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
break;
case CallEvent.ACTION_CALL_START:
// TODO: started an outgoing call
// TODO: show screen calling in Flutter
break;
case CallEvent.ACTION_CALL_ACCEPT:
print('accepted');
Get.offAll(()=> Incoming(
userName: null,
userImage: null,
userID: null,
userUsername: null));
break;
case CallEvent.ACTION_CALL_DECLINE:
print('rejected');
break;
case CallEvent.ACTION_CALL_ENDED:
// TODO: ended an incoming/outgoing call
break;
case CallEvent.ACTION_CALL_TIMEOUT:
// TODO: missed an incoming call
break;
case CallEvent.ACTION_CALL_CALLBACK:
// TODO: only Android - click action `Call back` from missed call notification
break;
case CallEvent.ACTION_CALL_TOGGLE_HOLD:
// TODO: only iOS
break;
case CallEvent.ACTION_CALL_TOGGLE_MUTE:
// TODO: only iOS
break;
case CallEvent.ACTION_CALL_TOGGLE_DMTF:
// TODO: only iOS
break;
case CallEvent.ACTION_CALL_TOGGLE_GROUP:
// TODO: only iOS
break;
case CallEvent.ACTION_CALL_TOGGLE_AUDIO_SESSION:
// TODO: only iOS
break;
}
print("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");
});
} on Exception {}
}
Solution
Similar to the answer that Peter Koltai gave, your background handler is isolated from your application's context and so it's not possible to route to screens (which require a context) directly from your handler.
One possible solution is to implement an Android service using native code that communicates with Flutter via a MethodChannel
and on the event that a call is accepted, you can navigate screens.
Answered By - Stéphan van Biljon
Answer Checked By - Pedro (JavaFixing Volunteer)