Flutter Bloc Unhandled Exception - flutter

I am getting this error when I launch any kind of auth condition, is something related to emit states on bloc any help will be appreciated:
This is my code:
class SignInFormBloc extends Bloc<SignInFormEvent, SignInFormState> {
final IAuthFacade authFacade;
SignInFormBloc({required this.authFacade}) : super(SignInFormState.initial()) {
on<SignInFormEvent>((event, emit) {
event.map(
emailChanged: ((value) => emit(state.copyWith(
emailAddress: EmailAddress(value.emailStr),
authFailureOrSuccessOption: none(),
))),
passwordChanged: ((value) =>
emit(state.copyWith(password: Password(value.passwordStr), authFailureOrSuccessOption: none()))),
// Register with email and password
signUpWithEmailAndPasswordPressed: ((value) async =>
await _performActionOnAuthFacadeWithEmailAndPassword(emit, authFacade.signUpWithEmailAndPassword)),
// Login with email and password
signInWithEmailAndPasswordPressed: ((value) async =>
await _performActionOnAuthFacadeWithEmailAndPassword(emit, authFacade.signInWithEmailAndPassword)),
// login with google
signInWithGooglePressed: ((value) async {
emit(state.copyWith(isSubmitting: true, authFailureOrSuccessOption: none()));
final failureOrSuccess = await authFacade.signInWithGoogle();
emit(state.copyWith(isSubmitting: false, authFailureOrSuccessOption: some(failureOrSuccess)));
}));
});
}
Future<void> _performActionOnAuthFacadeWithEmailAndPassword(
Emitter<SignInFormState> emit,
Future<Either<AuthFailure, Unit>> Function({required EmailAddress emailAddress, required Password password})
forwardedCalled) async {
Either<AuthFailure, Unit>? failureOrSuccess;
final isValidEmail = state.emailAddress.isValid();
final isValidPassword = state.password.isValid();
if (isValidEmail && isValidPassword) {
emit(state.copyWith(isSubmitting: true, authFailureOrSuccessOption: none()));
failureOrSuccess = await forwardedCalled(emailAddress: state.emailAddress, password: state.password);
emit(state.copyWith(
isSubmitting: false,
showErrorMessages: true,
authFailureOrSuccessOption: optionOf(failureOrSuccess),
));
}
}
}
I am read a lot about this error but i can not get fixed with any possible solution
Flutter Doctor:

Related

While creating user getting user as null

(Flutter) User is always getting null and unable to create user in realtime database
Future validateform() async {
FormState? formState = _formKey.currentState;
if(formState!.validate()) {
formState.reset();
User? user = firebaseAuth.currentUser;
// String? useruid = user!.uid;
print(user);
if(user == null ) {
print(_emailTextController.text);
print(_nameTextController.text);
print('UserID: '+'{$user}');
print(gender);
firebaseAuth
.createUserWithEmailAndPassword(
email: _emailTextController.text,
password: _passwordTextController.text)
.then((user) => {
_userServices.createUser(
{
"username": _nameTextController.text,
"email": _emailTextController.text,
// "userId": useruid,
"userId": user.user!.uid,
// "userId": "5as564d65as4d65as4d65as4d64",
"gender": gender,
})
}).catchError((err) => {print(err.toString())});
// });
print(user);
if (user!=null) {
Navigator.pushReplacement(
context,
MaterialPageRoute(builder: (context) => HomePage()),
);
}
}
}
}
I was expecting it to creaete in REALTIME DATABASE as user details, but user is always null.

The client_secret Provided does not match any associated PaymentIntent on this account

I'm trying to use flutter_stripe for a stripe connect account, But I always get the
same error: The client_secret provided doesn't match the client_secret associated with the PaymentIntend.
I've completed all steps according to flutter_stripe but I still face this error.
Below is my code Please check this and help me.
inde.js
const functions = require("firebase-functions");
const stripe = require("stripe")("secret_key");
exports.stripePaymentIntentRequest = functions.https.onRequest(async (req, res) => {
try {
let customerId;
//Gets the customer who's email id matches the one sent by the client
const customerList = await stripe.customers.list({
email: req.body.email,
limit: 1
});
//Checks the if the customer exists, if not creates a new customer
if (customerList.data.length !== 0) {
customerId = customerList.data[0].id;
}
else {
const customer = await stripe.customers.create({
email: req.body.email
});
customerId = customer.data.id;
}
//Creates a temporary secret key linked with the customer
const ephemeralKey = await stripe.ephemeralKeys.create(
{ customer: customerId },
{ apiVersion: '2020-08-27' }
);
//Creates a new payment intent with amount passed in from the client
const paymentIntent = await stripe.paymentIntents.create({
amount: parseInt(req.body.amount),
currency: 'usd',
customer: customerId,
})
res.status(200).send({
clientSecret: paymentIntent.client_secret,
paymentIntent: paymentIntent,
ephemeralKey: ephemeralKey.secret,
customer: customerId,
success: true,
})
} catch (error) {
res.status(404).send({ success: false, error: error.message })
}
});
PaymentService.dart
Future<void> initPaymentSheet(
{required BuildContext context, required String email, required int amount}) async {
try {
// 1. create payment intent on the server
final response = await http.post(
Uri.parse(
'Firebase api link of Functions'),
body: {
'email': email,
'amount': amount.toString(),
});
Map<String, dynamic> paymentIntentBody = jsonDecode(response.body);
log(paymentIntentBody.toString());
//2. initialize the payment sheet
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: paymentIntentBody["clientSecret"],
merchantDisplayName: 'Flutter Stripe Store Demo',
customerId: paymentIntentBody['customer'],
customerEphemeralKeySecret: paymentIntentBody['ephemeralKey'],
style: ThemeMode.light,
testEnv: true,
merchantCountryCode: 'US',
),
);
await Stripe.instance.presentPaymentSheet();
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Payment completed!')),
);
} catch (e) {
if (e is StripeException) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('Error from Stripe: ${e.error.localizedMessage}'),
),
);
} else {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error the Stripe of : $e')),
);
}
}
}
The log error print on my console is :
> [log] {paymentIntent:
> pi_3LI2acCTAUDjRNFV1Ra3dahz_secret_Fcqw73pWrE4avKRyuDVzRBitG,
> ephemeralKey:
> ek_test_YWNjdF8xSlQ3amtDVEFVRGpSTkZWLDl1OE5Vdm1jTGY4T1RpaVhHOTB3NTRVSkQ5UGl4azA_00j32OYG9n,
> customer: cus_LHG2YpQP9Cgwuy, success: true}
The following code is from a previous Stripe evaluation stage. But it worked. Slim it down to your needs.
Remember to publish your secret key to the server, so the server can talk to Stripe.
code.dart
Future<bool> payWithPaymentSheet(
ProductModel productModel, PriceModel priceModel,
{String merchantCountryCode = 'DE'}) async {
if (kIsWeb) {
throw 'Implementation not availabe on Flutter-WEB!';
}
String uid = AuthService.instance.currentUser().uid;
String email = AuthService.instance.currentUser().email ?? '';
HttpsCallableResult response;
try {
response = await FirebaseFunctions
.httpsCallable('createPaymentIntent')
.call(<String, dynamic>{
'amount': priceModel.unitAmount,
'currency': priceModel.currency,
'receipt_email': email,
'metadata': {
'product_id': productModel.id,
'user_id': uid,
"valid_until": productModel.getUntilDateTime().toIso8601String(),
'product_name': productModel.name.tr,
},
'testEnv': kDebugMode,
});
} on FirebaseFunctionsException catch (error) {
log(error.code);
log(error.details);
log(error.message ?? '(no message)');
Get.snackbar(
error.code,
error.message ?? '(no message)',
icon: const Icon(Icons.error_outline),
);
return false;
}
Map<String, dynamic> paymentIntentBody = response.data;
await Stripe.instance.initPaymentSheet(
paymentSheetParameters: SetupPaymentSheetParameters(
paymentIntentClientSecret: paymentIntentBody["clientSecret"],
currencyCode: priceModel.currency,
applePay: false,
googlePay: false,
merchantCountryCode: merchantCountryCode,
merchantDisplayName: Strings.appName,
testEnv: kDebugMode,
customerId: paymentIntentBody['customer'],
customerEphemeralKeySecret: paymentIntentBody['ephemeralKey'],
));
try {
await Stripe.instance.presentPaymentSheet();
return true;
} on StripeException catch (e) {
log(e.error.code.name);
log(e.error.message ?? '(no message)');
log(e.error.localizedMessage ?? '(no message)');
Get.snackbar(e.error.code.name, e.error.message ?? '',
icon: const Icon(Icons.error_outline));
} catch (e) {
Get.snackbar('An unforseen error occured', e.toString(),
icon: const Icon(Icons.error_outline));
}
return false;
}
index.ts
// SETTING SECRET KEY ON SERVER:
// cd functions
// firebase functions:config:set stripe.secret_key="sk_live_51L...Noe"
// firebase deploy --only functions
let stripe = require("stripe")(functions.config().stripe.secret_key);
exports.createPaymentIntent = functions
.https.onCall((data, context) => {
// if (!context.auth) {
// return { "access": false };
// }
return new Promise(function (resolve, reject) {
stripe.paymentIntents.create({
amount: data.amount,
currency: data.currency,
receipt_email: decodeURIComponent(data.receipt_email),
metadata: data.metadata,
}, function (err, paymentIntent) {
if (err != null) {
functions.logger.error("Error paymentIntent: ", err);
reject(err);
}
else {
resolve({
clientSecret: paymentIntent.client_secret,
paymentIntentData: paymentIntent,
});
}
});
});
});

How to receive FCM push notification data in flutter web and redirect user to received link in notification?

I am trying to redirect user to specific page in flutter web on click of notification, till now I am receiving notification, the last open page is displayed in browser on click of notification, but I want user to redirect to specific page like specific post using unique post id, but I found no other ways, This thing happens in Android build, but doesn't happen on web build.
just take a look at ServiceWorker.js
in serviceworker.js even console.log() in not executing on receiving notification.
messaging.setBackgroundMessageHandler(function (payload) {
console.log(payload);
const promiseChain = clients
.matchAll({
type: "window",
includeUncontrolled: true
})
.then(windowClients => {
for (let i = 0; i < windowClients.length; i++) {
const windowClient = windowClients[i];
windowClient.postMessage(payload);
}
})
.then(() => {
const title = payload.notification.title;
const options = {
body: payload.notification.body
};
return registration.showNotification(title, options);
});
return promiseChain;
});
self.addEventListener('notificationclick', function (event) {
console.log('notification received: ', event)
});
now the logic for sending FCM Push Notification:
#required String message,
#required String fcmToken,
#required String title,
String type,
String typeId,
}) async {
await http
.post(
Uri.parse('https://fcm.googleapis.com/fcm/send'),
headers: <String, String>{
'Content-Type': 'application/json',
'Authorization': 'key=$serverToken',
},
body: jsonEncode(
<String, dynamic>{
'notification': <String, dynamic>{
"click_action": 'FLUTTER_NOTIFICATION_CLICK',
'body': message,
'title': '$title',
'sound': 'default'
},
'priority': 'high',
'data': <String, dynamic>{
'click_action': 'FLUTTER_NOTIFICATION_CLICK',
'id': '1',
'status': 'done',
'type': type ?? "",
'typeId': typeId ?? "",
},
'to': fcmToken.toString().trim(),
},
),
)
.then((value) {
print("Notification Sent");
});
final Completer<Map<String, dynamic>> completer =
Completer<Map<String, dynamic>>();
// firebaseMessaging.configure(
// onMessage: (Map<String, dynamic> message) async {
// completer.complete(message);
// },
// );
return completer.future;
}
Now the way I am handling Notification Receive:
print("in setup interacted message");
const AndroidNotificationChannel channel = AndroidNotificationChannel(
'high_importance_channel', // id
'High Importance Notifications', // title
'This channel is used for important notifications.', // description
importance: Importance.max,
);
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
await flutterLocalNotificationsPlugin
.resolvePlatformSpecificImplementation<
AndroidFlutterLocalNotificationsPlugin>()
?.createNotificationChannel(channel);
NotificationSettings notifSettings =
await FirebaseMessaging.instance.requestPermission(
alert: true,
announcement: true,
badge: true,
carPlay: true,
criticalAlert: true,
provisional: true,
sound: true,
);
if (notifSettings.authorizationStatus == AuthorizationStatus.authorized) {
// Get any messages which caused the application to open from
// a terminated state.
try {
RemoteMessage initialMessage =
await FirebaseMessaging.instance.getInitialMessage();
// If the message also contains a data property with a "type" of "post",
// navigate to a post screen
if (initialMessage != null && initialMessage.data['type'] == 'post') {
await Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) => IndividualPostPage(
postObjectId: initialMessage.data['typeId'],
),
),
);
print(initialMessage.data);
initialMessage = null;
}
// Also handle any interaction when the app is in the background via a
// Stream listener
FirebaseMessaging.onMessageOpenedApp
.listen((RemoteMessage message) async {
print("here");
if (message != null && message.data['type'] == 'post') {
if (message.data['type'] == 'post') {
await Navigator.push(
context,
new MaterialPageRoute(
builder: (BuildContext context) => IndividualPostPage(
postObjectId: message.data['typeId'],
),
),
);
}
print(message.data);
message = null;
}
});
} catch (e) {
print("Error $e");
}
}
}
messaging.setBackgroundMessageHandler(function (payload) {
console.log(payload);
const promiseChain = clients
.matchAll({
type: "window",
includeUncontrolled: true
})
.then(windowClients => {
for (let i = 0; i < windowClients.length; i++) {
const windowClient = windowClients[i];
windowClient.postMessage(payload);
}
})
.then(() => {
const title = payload.notification.title;
var click_action =payload.data.ui_route;//ui route is ur route
const options = {
body: payload.notification.body ,
data: {
click_action,
}
};
return registration.showNotification(title, options);
});
return promiseChain;
});
// Notification click event listener
self.addEventListener('notificationclick', e => {
data=e.notification.data.obj;
// Close the notification popout
e.notification.close();
// Get all the Window clients
e.waitUntil(clients.matchAll({ type: 'window' }).then(clientsArr => {
// If a Window tab matching the targeted URL already exists, focus that;
const hadWindowToFocus = clientsArr.some(windowClient => windowClient.url === e.notification.data.click_action ? (windowClient.focus(), true) : false);
// Otherwise, open a new tab to the applicable URL and focus it.
if (!hadWindowToFocus) clients.openWindow(e.notification.data.click_action).then(windowClient => windowClient ? windowClient.focus() : null);
}));
});

E/FlutterFcmService( 6350): Fatal: failed to find callback Flutter

I got this error log when I build app on a Emulator.
even the app start regularly this Fatal Error appears right when main.dart is executed:
E/FlutterFcmService( 6350): Fatal: failed to find callback
the question is that no notifications is executed because this error appears right when I start the app without pushing any notifications.
any input?
what I use:
firebase_messaging: ^7.0.3
flutter_local_notifications: ^4.0.1
this is the code which handle the notifications, but the error is before it will executed:
final FirebaseMessaging firebaseMessaging = FirebaseMessaging();
final FlutterLocalNotificationsPlugin flutterLocalNotificationsPlugin =
FlutterLocalNotificationsPlugin();
#override
void initState() {
super.initState();
registerNotification();
configLocalNotification();
}
void registerNotification() {
firebaseMessaging.requestNotificationPermissions();
firebaseMessaging.configure(onMessage: (Map<String, dynamic> message) {
print('onMessage: $message');
Platform.isAndroid
? showNotification(message['notification'])
: showNotification(message['aps']['alert']);
return ;
}, onResume: (Map<String, dynamic> message) {
print('onResume: $message');
return Navigator.push(
context,
MaterialPageRoute(
builder: (context) => NotificationsScreen()));
}, onLaunch: (Map<String, dynamic> message) {
print('onLaunch: $message');
return;
},
onBackgroundMessage: myBackgroundMessageHandler
);
firebaseMessaging.getToken().then((token) {
print('token: $token');
FirebaseFirestore.instance
.collection('Consultant')
.doc(firebaseUser.uid)
.update({'deviceToken': token});
}).catchError((err) {
//Fluttertoast.showToast(msg: err.message.toString());
});
}
Future selectNotification(String payload) async {
if (payload != null) {
debugPrint('notification payload: $payload');
}
await Navigator.push(
context,
MaterialPageRoute<void>(builder: (context) => NotificationsScreen(payload: payload,)),
);
}
void showNotification(message) async {
var androidPlatformChannelSpecifics = new AndroidNotificationDetails(
Platform.isAndroid
? 'it.wytex.vibeland_pro_app'
: 'it.wytex.vibeland_pro_app',
'Vibeland Pro',
'Vibeland Pro',
playSound: true,
enableVibration: true,
importance: Importance.max,
priority: Priority.high,
icon: '#drawable/ic_stat_vibeland_pro'
);
var iOSPlatformChannelSpecifics = new IOSNotificationDetails();
var platformChannelSpecifics = new NotificationDetails(
android: androidPlatformChannelSpecifics, iOS: iOSPlatformChannelSpecifics);
print(message);
print(message['body'].toString());
print(json.encode(message));
// await flutterLocalNotificationsPlugin.show(2, message['title'].toString(),
// message['body'].toString(), platformChannelSpecifics,
// payload: json.encode(message));
await flutterLocalNotificationsPlugin.show(
3, '📩 Hai ricevuto un messaggio 📩 ', 'Controlla subito le Tue notifiche 🔔🔔', platformChannelSpecifics,
payload: '#drawable/ic_stat_vibeland_pro',
);
}
void configLocalNotification() {
var initializationSettingsAndroid =
new AndroidInitializationSettings('#drawable/ic_stat_vibeland_pro');
var initializationSettingsIOS = new IOSInitializationSettings(
requestAlertPermission: true,
requestBadgePermission: true,
requestSoundPermission: true,
);
var initializationSettings = new InitializationSettings(
android: initializationSettingsAndroid, iOS: initializationSettingsIOS);
flutterLocalNotificationsPlugin.initialize(initializationSettings);
}
and background messagge are handle externally of the class:
Future<void> myBackgroundMessageHandler(message) async {
print("Handling a background message: ${message}");
}
this below the function added to Firebase
const functions = require("firebase-functions");
const admin = require("firebase-admin");
admin.initializeApp(functions.config().firebase);
const fcm = admin.messaging();
exports.sendNotification = functions.firestore
.document("Notifications/{id}")
.onCreate((snapshot) => {
const name = snapshot.get("name");
const subject = snapshot.get("subject");
const token = snapshot.get("token");
const payload = {
notification: {
title: "" + name,
body: "" + subject,
sound: "default",
icon: "#drawable/ic_stat_vibeland_pro",
},
data: {
click_action: "FLUTTER_NOTIFICATION_CLICK",
},
};
return fcm.sendToDevice(token, payload);
});
not the error I get is before we call these functions...

How to use Flutter Bloc with Firebase Phone Auth

I'm trying to implement Firebase phone authorization using Flutter Bloc pattern.
I have the following code
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:firebase_auth/firebase_auth.dart';
import './bloc.dart';
class AuthBloc extends Bloc<AuthEvent, AuthState> {
final FirebaseAuth _auth = FirebaseAuth.instance;
#override
AuthState get initialState => AuthNotStarted();
#override
Stream<AuthState> mapEventToState(
AuthEvent event,
) async* {
if (event is VerifyPhone) {
yield* _mapVerifyPhoneToState(event);
}
}
Stream<AuthState> _mapVerifyPhoneToState(VerifyPhone event) async* {
yield AuthStarted();
_auth.verifyPhoneNumber(
phoneNumber: "+" + event.phoneNumber,
timeout: Duration(seconds: 60),
verificationCompleted: (AuthCredential authCredential) {
print("verification completed: auth credential");
},
verificationFailed: (AuthException authException) {
print("verification failed: auth exception");
print(authException.message);
},
codeSent: (String verificationId, [int forceResendingToken]) {
print("code sent verification id" + verificationId);
},
codeAutoRetrievalTimeout: (String verificationId) {
print("auto time" + verificationId);
});
}
}
But i can't use yield inside verifyPhoneNumber callbacks.
The question is how to yield different states inside of callback functions?
You can add an event from your callback. For example, in verificationCompleted, you can do:
verificationCompleted: (AuthCredential authCredential) {
print("verification completed: auth credential");
add(AuthCompleted());
},
And you can handle the AuthCompleted() event on mapEventToState:
#override
Stream<AuthState> mapEventToState(
AuthEvent event,
) async* {
if (event is VerifyPhone) {
yield* _mapVerifyPhoneToState(event);
}
if (event is AuthCompleted){
//Here you can use yield and whathever you want
}
}
PhoneAuthenticationBloc
class PhoneAuthenticationBloc
extends Bloc<PhoneAuthenticationEvent, PhoneAuthenticationState> {
final AuthRepository _authRepository;
final AuthBloc _authBloc;
#override
Stream<PhoneAuthenticationState> mapEventToState(
PhoneAuthenticationEvent event,
) async* {
if (event is PhoneLoadingEvent) {
yield PhoneLoadingState();
} else if (event is PhoneVerificationFailedEvent) {
yield PhoneOTPFailureState(event.failure);
} else if (event is PhoneSmsCodeSentEvent) {
yield PhoneSmsCodeSentState(
verificationId: event.verificationId, resendCode: event.resendId);
} else if (event is PhoneVerifiedOtpEvent) {
yield* _mapToVerifyOtp(event.smsCode, event.verificationId);
}
}
void verifyPhoneNumber(String phoneNumber) async {
try {
add(PhoneLoadingEvent());
await _authRepository.verifyPhoneNumber(phoneNumber,
onRetrieval: (String retrievalCode) {
print("Time Out Retrieval Code: $retrievalCode");
}, onFailed: (Failure f) {
print("OnFailed: ${f.message}");
add(PhoneVerificationFailedEvent(f));
}, onCompleted: (Map<String, dynamic> data) {
print("verificationCompleted: $data");
}, onCodeSent: (String verificationId, int resendCode) {
print("verificationId:$verificationId & resendCode: $resendCode");
add(PhoneSmsCodeSentEvent(
verificationId: verificationId, resendId: resendCode));
});
} catch (e) {
add(PhoneVerificationFailedEvent(Failure(message: e.toString())));
}
}}
UI Screen
builder: (context, state) {
return AppButton(
isLoading: state is PhoneLoadingState,
onPressed: () async {
if (_formKey.currentState.validate()) {
BlocProvider.of<PhoneAuthenticationBloc>(context)
.verifyPhoneNumber(_phoneController.text);
}
},
title: "Continue",
textColor: Colors.white,
);
}