I want to update the UI when I receive background notification from Firebase.
I have a backgroundMessage handler
`
#pragma('vm:entry-point')
Future<void> handleBackgroundNotification(RemoteMessage remoteMessage) async {
try {
final SendPort send = IsolateNameServer.lookupPortByName('port_firebase');
send.send(remoteMessage.notification.body);
} catch (e) {
log(e.toString());
throw e;
}
}
And I am registering my Receive port and background handler insideinitState`.
bool res = IsolateNameServer.registerPortWithName(
_port.sendPort, 'port_firebase');
log('status $res');
if (res) {
log('port created successfuly');
_port.listen((dynamic data) {
log('port ' + data.toString());
}, onError: (e) {
log('error is ${e.toString()}');
});
}
FirebaseMessaging.onBackgroundMessage(handleBackgroundNotification);
It registers the port successfully but whenever I receive background notification. It gives me error
NoSuchMethodError: The method 'send' was called on null.
Receiver: null
Tried calling: send("Welocme to FCM")
Does anyone have solution to this problem.
Add await in this line
final SendPort send = await IsolateNameServer.lookupPortByName('port_firebase');
Related
Why is my catch block not called in this code when there is exception
Future registerWithCredentials() async {
if(state.status == RegisterStatus.loading) return;
emit(state.copyWith(status: RegisterStatus.loading));
try{
await _authRepository.register(email: state.email, password: state.password);
emit(state.copyWith(status: RegisterStatus.success));
}catch (e) {
//catch errors
debugPrint('except: "there is an error"');
emit(state.copyWith(status: RegisterStatus.error));
}
}
I have also tried like this:
try {
await _authRepository.register(email: state.email, password: state.password);
emit(state.copyWith(status: RegisterStatus.success));
} on FirebaseAuthException catch (e) {
debugPrint('except: "there is an error"');
emit(state.copyWith(status: RegisterStatus.error));
}
Repository -> register
Future<void> register({
required String email,
required String password,
}) async {
try {
await _firebaseAuth.createUserWithEmailAndPassword(email: email,
password: password);
} catch(_) {
//the catch here works but I need to send the error to cubit above and
also send to UI... how to do that
}
}
This what I want to do -> Send the error from repository to cubit to ui and display in widget/ui
If you catch the exception in the repository, then you have "used" (handled) the exception. If you want to catch the same exception in the bloc, you'll have to rethrow it. So, either re-throw the exception, or remove the try catch in the repository.
I'm having an issue dealing with Firebase push notifications when the App is KILLED.
What's happening:
First of all, push notifications should work like this. When you tap, you are redirected to a Move-Type Job or an Event-Type Job.
When app is in BACKGROUND MODE, push notification shows as it should,
and it redirects to the page that it should.
When App is KILLED, push notifications still shows, but when you tap on them you are not redirected, you are just opening the App.
Future initialize() async {
await getConnectivity();
if (hasInternet) {
try {
await configurePushNotificationHandlers();
} catch (e) {
hasApiConnection = false;
}
}
}
Future configurePushNotificationHandlers() async {
await navigationService.navigateReplacementWithParams(ErrorPage());
await _firebaseMessaging.requestPermission(
alert: true,
badge: true,
provisional: false,
sound: true,
);
String fbToken = await _firebaseMessaging.getToken();
FirebaseMessaging.onMessage.listen((RemoteMessage message) async {
if (message.data != null && message.data.containsKey('showInPageNotification')) {
numberOfNotifications++;
}
notifyListeners();
});
FirebaseMessaging.onMessageOpenedApp.listen((RemoteMessage message) async {
print('A new onMessageOpenedApp event was published!');
if (message.data != null && message.data.containsKey('job_id')) {
String jobId = message.data['job_id'];
String jobType = message.data['job_type'];
jobType = jobType.toLowerCase();
if (jobType == 'move') {
await goToJobDetail(jobId);
} else {
await goToEventDetail(jobId);
}
}
});
Anyone has a clue of why does this happens? Push notifications are working fine, it's the redirection the current ISSUE. Thanks!
Use FirebaseMessaging.instance.getInitialMessage() method to get messages
If App is Closed/Killed
FirebaseMessaging.instance
.getInitialMessage()
.then((RemoteMessage message) {
print("FirebaseMessaging.getInitialMessage $message");
});
Try this and let me know.
so i have this function which detect if there is connection or not . if yes the var activeConnection is true else false . So if the connection is working i'm going to call a method sendEmail() which work with the plugin mailer . My problem is when i activated the WIFI it can send the email then if i turn it off an exception is shown
E/flutter ( 5347): [ERROR:flutter/lib/ui/ui_dart_state.cc(209)]
Unhandled Exception: SocketException: Failed host lookup:
'smtp.gmail.com' (OS Error: No address associated with hostname, errno
= 7)
in this case activeConnection is true but when it try to send the email it can't find the connection . if i turn off the wifi and wait for a moment before i send the email it can detect that there is no wifi so i tried to add a sleep function before it check the connection but i'm facing the same problem .
this is the code :
Future checkUserConnection() async {
try {
//sleep(const Duration(seconds: 10));
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
setState(() {
activeConnection = true;
print(activeConnection);
});
}
} on SocketException catch (_) {
setState(() {
activeConnection = false;
print(activeConnection);
});
}
//print(activeConnection);
}
and this is where i call my function
onTap: () {
checkUserConnection();
print(activeConnection);
if (activeConnection) {
sendEmail();
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
false, "email sended ", Icons.error_outline));
} else {
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
true,
"check your internet connection !!!",
Icons.error_outline));
}
print("hello");
},
You have to make async function like this:
Future<bool> checkUserConnection() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
} on SocketException catch (_) {
return false;
}
}
After that onTap() you have to code like this:
onTap: () {
checkUserConnection().then((activeConnection){
if (activeConnection) {
sendEmail();
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
false, "email sended ", Icons.error_outline));
} else {
ScaffoldMessenger.of(context).showSnackBar(showSnackBar(
true, "check your internet connection !!!",
Icons.error_outline));
}
});
}
I have problem in receiving data in flutter serial bluetooth no error in code its connected and disconnected successfully but the problem is receiving data
void listenToBluetooth() async{ // this method called in initState
try {
BluetoothConnection connection = await BluetoothConnection.toAddress(widget.address);
print('Connected to the device form listenToBluetooth method');
connection.input!.listen((Uint8List data) {
print('Data incoming: ${ascii.decode(data)}');
connection.output.add(data); // Sending data
//
// if (ascii.decode(data).contains('!')) {
// connection.finish(); // Closing connection
// print('Disconnecting by local host');
// }
}).onDone(() {
print('Disconnected by remote request');
});
}
catch (exception) {
print('Cannot connect, exception occurred');
}
}
I am working on my first app in Flutter, I have a bit of experience with Java and js, but I never worked with flutter before so sorry if my question will seem ridiculous to you.
The app is the voice assistant chatbot, and it is supposed to perform text to speech on each new message that customer receives, my problem is that since I am using firebase messaging all of the requests that I receive are in the asynchronous call, but I need to synchronize the access to the text to speech service otherwise I run into problem of having one text interrupt another.
This is what my code looks like at the moment:
Firebase messaging:
onMessage: (Map<String, dynamic> message) {
return this.handleBotMessage(appState, message);
},
Method that desides how to handle each particular message:
Future handleBotMessage(
Store<AppState> store,
Map<String, dynamic> dataJson,
) {
#logic that convert the message into json and extracts the message type
if (type == MessageType.CHAT_MESSAGE) {
return handleChatMessage(store, subtype, messageMap);
}
}
The method that handles text messages:
Future<dynamic> handleChatMessage(
Store<AppState> store,
MessageSubtype subtype,
Map<String, dynamic> message,
) {
#Text to speach is build as a singleton and this always returns the same instance
TextToSpeech tts = TextToSpeech();
if (subtype == MessageSubtype.TEXT) {
TextMessage textMessage = TextMessage.fromJson(message);
return tts
.speak(textMessage.text)
.then((result) => store.dispatch(NewBotMessageAction(textMessage)));
} else if (subtype == MessageSubtype.QUICK_REPLY) {
QuickReplyMessage qrMessage = QuickReplyMessage.fromJson(message);
return tts
.speak(qrMessage.text)
.then((result) => store.dispatch(NewQrOptionsAction(qrMessage)));
} else {
throw new Exception('Unexpected message subtype!');
}
}
The method that actually performs the text to speech
Future<dynamic> speak(String text) async {
return flutterTts.speak(text).then((resp) {
ttsRunning = false;
print(resp);
return resp;
}, onError: (obj, st) {
ttsRunning = false;
print(obj);
print(st.toString());
});
}
Text to speech initialization
Future init() async {
await flutterTts.setLanguage("en-US");
var res = await flutterTts.isLanguageAvailable("en-US");
print(res);
return res;
}
https://pub.dev/packages/flutter_tts
Ok, I have found the solution, the issue was as frank06 pointed out with the fact that flutter tts completes the future immediately rather than after the whole phrase was spoken.
So here is my solution, it is not perfect, but it works:
Completer completer;
Future<dynamic> speak(String text) {
print('Started speeking');
print(new DateTime.now().toIso8601String());
if (TextToSpeech.lastRequest == null) {
lastRequest = _executeSpeech(text);
} else {
lastRequest = lastRequest.then((resp) {
return _executeSpeech(text);
});
}
return lastRequest;
}
Future<dynamic> _executeSpeech(String text) {
completer = Completer();
flutterTts.speak(text).then((resp) {
ttsRunning = false;
print(resp);
return resp;
}, onError: (obj, st) {
ttsRunning = false;
print(obj);
print(st.toString());
});
return completer.future;
}
flutterTts.setCompletionHandler(() {
print('Finished speeking');
print(new DateTime.now().toIso8601String());
ttsState = TtsState.stopped;
completer.complete(ttsState);
});
flutterTts.setErrorHandler((msg) {
ttsState = TtsState.stopped;
completer.complete(ttsState);
});
If you don't want new messages interrupting those being spoken, you can queue them up. This way the new messages will wait for the current message to finish. Check out this approach:
Queue of Future in dart