Flutter await for try catch [duplicate] - flutter

This question already has answers here:
How to Async/await in List.forEach() in Dart
(7 answers)
Closed 2 years ago.
I'm using firebase cloud firestore
inside a Future function I have this
try {
categories.forEach((element) async {
await FirebaseFirestore.instance.collection('Categories').add({
'name': element[0],
'imageUrl': element[1],
});
print('done');
});
print('complete');
} catch (e) {
CoolAlert.show(
context: context,
type: CoolAlertType.error,
content: Text(e),
text: "Upload Failed",
onConfirmBtnTap: () {
Navigator.pop(context);
Navigator.pop(context);
});
}
'completed' printed before 'done'
how to make it the opposite?
how to await for the forEach function to end first then proceed
and even if I moved print('complete'); after the whole try catch block it doesn't work either
so is there a way to wait try catch block?

You can use Future.foreach OR Future.doWhile
Future.doWhile :
int index = 0;
try {
Future.doWhile(() {
if (index < categories.length) {
await FirebaseFirestore.instance.collection('Categories').add({
'name': categories[index][0],
'imageUrl': categories[index][1],
});
print('done');
index++;
return true;
} else {
print('complete');
return false;
}
});
} catch (e) {
CoolAlert.show(
context: context,
type: CoolAlertType.error,
content: Text(e),
text: "Upload Failed",
onConfirmBtnTap: () {
Navigator.pop(context);
Navigator.pop(context);
});
}
Future.foreach:
try {
Future.forEach(categories,(element) async {
await FirebaseFirestore.instance.collection('Categories').add({
'name': element[0],
'imageUrl': element[1],
});
print('done');
});
print('complete');
} catch (e) {
CoolAlert.show(
context: context,
type: CoolAlertType.error,
content: Text(e),
text: "Upload Failed",
onConfirmBtnTap: () {
Navigator.pop(context);
Navigator.pop(context);
});
}

Related

FlutterFire Auth verifyPhoneNumber method isn't being waited on

I'm trying to create an auth service and I want to return the verificationId from the custom method. However, calling this method throws the null check exception because it doesn't wait for the Future to complete before returning.
Future<String> sendPhoneVerification({
required String phoneNumber,
}) async {
String? result;
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: '+1$phoneNumber',
verificationCompleted: (
PhoneAuthCredential credential,
) {
result = credential.verificationId;
},
verificationFailed: (e) {
if (e.code == 'invalid-phone-number') {
throw InvalidPhoneNumberAuthException();
} else if (e.code == 'too-many-requests') {
throw TooManyRequestsAuthException();
} else {
throw GenericAuthException();
}
},
codeSent: (verificationId, resendToken) {
print('ver_id $verificationId');
result = verificationId;
},
codeAutoRetrievalTimeout: (_) {},
);
print('This is the result $result');
return result!;
}
Here is the output in the terminal.
flutter: This is the result null
flutter: ver_id <ver_id>
Please add this property timeout: const Duration(seconds: 60), in the verifyPhoneNumber() method
I figured out the solution. I found out the verifyPhoneNumber method returns a future but the implementation doesn't await that async call. I used a [completer][1] to return a future.
Future<String> sendPhoneVerification({required String phoneNumber}) async {
Completer<String> result = Completer();
await FirebaseAuth.instance.verifyPhoneNumber(
phoneNumber: '+1$phoneNumber',
verificationCompleted: (
PhoneAuthCredential credential,
) {
result.complete(credential.verificationId);
},
verificationFailed: (e) {
if (e.code == 'invalid-phone-number') {
result.completeError(InvalidPhoneNumberAuthException());
} else if (e.code == 'too-many-requests') {
result.completeError(TooManyRequestsAuthException());
} else {
result.completeError(GenericAuthException());
}
},
codeSent: (verificationId, resendToken) {
result.complete(verificationId);
},
codeAutoRetrievalTimeout: (_) {},
);
return result.future;
}

how to wait till firebase function get all necessary values

i wanted to wait till firebase auth retrive verification_id and then return function
but in current code variable value newVerificationId is getting return first as error without updating from firebase
Future<String> phoneAuthontication(
phoneNumberController,
) async {
String newVerificationId = "error";
try {
await auth.verifyPhoneNumber(
phoneNumber: phoneNumberController.text,
verificationCompleted: (_) {},
verificationFailed: (e) {
print(e);
},
codeSent: (String verificationId, int? token) {
print("====" + verificationId);
newVerificationId = verificationId;
},
codeAutoRetrievalTimeout: (e) {
print(e);
});
} catch (e) {
print(e);
}
print("---" + newVerificationId);
return newVerificationId;
}

Black Screen agora remote view flutter

I am trying to implement the flutter Agora SDK Livestream with agora and I'm getting a black screen on remote view, local view works fine.
Please what am I doing wrongly?
What I tried:
double-check if all permissions are enabled
recreate a new application In agora.io
switch devices
check internet connectivity
This is the code for the implementation:
void initEngine() async {
_engine = await RtcEngine.create(agoraKey);
addListeners();
_engine.enableVideo();
_engine.startPreview();
_engine.enableAudio();
_engine.setChannelProfile(ChannelProfile.LiveBroadcasting);
print(widget.isBroadcaster);
if (("${widget.userData.uid}${widget.userData.name}" == widget.channeId)) {
_engine.setClientRole(ClientRole.Broadcaster);
print('broadcaster');
} else {
_engine.setClientRole(ClientRole.Audience);
print('audience');
}
_joinChannel();
}
_renderVideo(
user,
isScreenSharing,
) {
return AspectRatio(
aspectRatio: 16 / 9,
child: "${user.uid}${user.name}" == widget.channeId
? isScreenSharing
? kIsWeb
? const RtcLocalView.SurfaceView.screenShare()
: const RtcLocalView.TextureView.screenShare()
: const RtcLocalView.SurfaceView(
zOrderMediaOverlay: true,
zOrderOnTop: true,
)
: isScreenSharing
? kIsWeb
? const RtcLocalView.SurfaceView.screenShare()
: const RtcLocalView.TextureView.screenShare()
: isRendered
? RtcRemoteView.TextureView(
uid: _remoteUids[0],
channelId: widget.channeId,
)
: Center(
child: Text(
'No Video',
style: GoogleFonts.balooPaaji2(
fontSize: 15,
),
),
),
);
}
void addListeners() {
_engine.setEventHandler(RtcEngineEventHandler(
joinChannelSuccess: (channel, uid, elapsed) async {
debugPrint('joinChannelSuccess $channel $uid $elapsed');
print(
'joinChannelSuccess ======================================================> $uid');
},
leaveChannel: (stats) {
debugPrint('leaveChannel $stats');
setState(() {
_remoteUids.clear();
});
},
userJoined: (uid, elapsed) {
debugPrint('userJoined $uid $elapsed');
setState(() {
print('userJoined=====================>:$_remoteUids');
_remoteUids.add(uid);
setState(() {
isRendered = true;
});
print('=======>====>$_remoteUids');
});
},
userOffline: (uid, reason) {
debugPrint('userOffline=====================> $uid $reason');
setState(() {
_remoteUids.remove(uid);
});
},
userMuteAudio: (uid, muted) {
debugPrint('userMuteAudio $uid $muted');
},
userMuteVideo: (uid, muted) {
debugPrint('userMuteVideo $uid $muted');
},
userEnableVideo: (uid, enabled) {
debugPrint('userEnableVideo $uid $enabled');
},
error: (error) {
debugPrint('error $error');
},
));
print('=====.$_remoteUids========');
}
void _joinChannel() async {
//leave the current channel
if (defaultTargetPlatform == TargetPlatform.iOS) {
await [Permission.microphone, Permission.camera].request();
await _engine.joinChannel(
tempToken, 'testing_channel', widget.channeId, 0);
debugPrint('joinChannelWithUserAccount ${widget.channeId} ');
} else {
await [Permission.microphone, Permission.camera].request();
await _engine.joinChannel(
tempToken, 'testing_channel', widget.channeId, 0);
debugPrint('joinChannelWithUserAccount ${widget.channeId} ');
}
}
}
Make sure the Uid in Rtc remote view is the same with the user went live and the user joined to live
RtcRemoteView.SurfaceView(
uid: ,
channelId:,
)

How to use conditional if statement in flutter for ontap ()

How do i use conditional ontap() on flutter, when i press the button the app checks if im singed in then if not it goes to the other function.
onTap: () if (appStore.isLoggedIn) {
async {
await userService.getUser(
email: widget.providerData.email.validate()).then((
value) {
widget.providerData.uid = value.uid;
}).catchError((e) {
log(e.toString());
});
UserChatScreen(receiverUser: widget.providerData).launch(
context);
}
else {
SignInScreen().launch(context);
}
},
).expand(),
onTap: () {
if(conditions) {
...
}
},

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,
});
}
});
});
});