I have to send an object from the request. Although it works on Swagger, I cannot send it from my flutter code. When I was trying it, it always gave me Http status error 400 This problem is coming my wrong request. I examined the code of the Internet. I thought I implemented it correctly but It still does not work. Please, could you help me to solve it? Here is my interested code areas:
my api side =>
Future changePassword(id, password) async {
try {
var prefs = await SharedPreferences.getInstance();
// User sendingData = User(
// id: id,
// );
// final dataSend = sendingData.toJson();
final response = await dio.post('http://192.168.1.108:2308/api/Account/ChangePassword',
data: jsonEncode({
"id": "$id",
"password": "$password"
}),
options: Options(headers: {
HttpHeaders.acceptHeader: '*/*',
HttpHeaders.contentTypeHeader: 'application/json',
}));
if (response.statusCode != 200) {
// debugPrint('burası-------------------------' + response.statusCode.toString());
}
prefs.remove('password');
return response;
}
catch (e) {
debugPrint(e.toString());
}
}
this is my screen side that I called it =>
onPressed: () async {
var prefs = await SharedPreferences.getInstance();
var pwd = prefs.getString('password');
var email = prefs.getString('email');
final usrId = prefs.getInt('userId');
pwdFormKey.currentState!.save();
if (pwdFormKey.currentState!
.validate()) {
try {
if(oldPwdController.text==pwd){
if(newPwdController.text==newPwdController2.text) {
await api.changePassword(usrId, newPwdController.text);
Navigator.pop(context);
Fluttertoast.showToast(
msg: "Şifreniz başarıyla değiştirilmiştir.",
toastLength: Toast
.LENGTH_SHORT,
gravity: ToastGravity
.BOTTOM,
backgroundColor: CupertinoColors
.activeGreen,
textColor: CupertinoColors
.black,
fontSize: 16.0);
}
// }
// }
else {
Fluttertoast.showToast(
msg: "Yeni girdiğiniz şifreler aynı değil, lütfen kontrol ediniz.",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: CupertinoColors.systemRed,
textColor: CupertinoColors.black,
fontSize: 16.0);
}
}
else{
Fluttertoast.showToast(
msg: "Eski Şifreniz Hatalıdır.",
toastLength: Toast.LENGTH_SHORT,
gravity: ToastGravity.BOTTOM,
backgroundColor: CupertinoColors.systemRed,
textColor: CupertinoColors.black,
fontSize: 16.0);
}
} catch (e) {
return showDialog(
context: context,
builder: (BuildContext
context) {
return AlertDialog(
title: Text(
"Hatalı Deneme"),
content:
SingleChildScrollView(
child: ListBody(
children: [
Text(
"Hatalı şifre değiştirme işleminde bulundunuz. Lütfen tekrar deneyiniz.")
],
),
),
actions: [
TextButton(
child: const Text(
'Tamam'),
onPressed: () {
Navigator.of(
context)
.pop();
},
),
],
);
});
}
}
},
In post method there are 2 diff values. One is data and another one is queryParameters. You can try in this way.
Map<String, dynamic>? param = {"userName": "name"};
return await (_dio.post(
"http://192.168.1.108:2308/api/Account/ChangePassword",
data: data, //Optional
queryParameters: params,
)).catchError((e) {
if (!checkSessionExpire(e, context)) {
throw e;
}
});
Related
I am trying to implement OTP sign up and sign in on my app. However I am experiencing an issue with.
Everything works fine except app still directs the user to the home page even when the put the wrong OTP.
My code can see that it is the wrong OTP but still signs in the user.
Auto sign in does not take place even if otp has verification is successful.
Main.dart code:
home: StreamBuilder(
stream: FirebaseAuth.instance.authStateChanges(),
builder: (BuildContext context, userSnapshot) {
if (userSnapshot.hasData) {
if (kDebugMode) {
print("DATA FOUND");
}
return const HomeScreen();
} else if (userSnapshot.hasError) {
if (kDebugMode) {
print("ERROR OCCURED");
}
return const SizedBox();
} else {
if (kDebugMode) {
print("DATA NOT FOUND");
}
return const OnboardingScreen();
}
}),
Send OTP Code:
Future _verifyNumber(BuildContext context) async {
// verify phone number
try {
setState(() {
_isLoading = true;
});
FirebaseAuth.instance.verifyPhoneNumber(
// users phone number
phoneNumber: _userPhoneNumber.text,
// otp will br valid for the given duration
timeout: const Duration(seconds: 120),
// to-do if verificatiion is successful
verificationCompleted: (PhoneAuthCredential authCredential) {
if (kDebugMode) {
print("VERIFICATION SUCCESSFUL");
}
try {
setState(() async {
authStatus = "VS"; // VRS - Verification Successful
});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
duration: const Duration(seconds: 3),
backgroundColor: Colors.greenAccent,
content: Text(
"VERIFICATION SUCCESSFUL",
textAlign: TextAlign.center,
style: GoogleFonts.lato(
fontSize: 14,
),
),
));
} catch (e) {
if (kDebugMode) {
print("ERROR1 - ${e.toString()}");
}
}
},
// to-do if verificatiion is NOT successful
verificationFailed: (FirebaseAuthException authException) {
if (kDebugMode) {
print("VERIFICATION FAILED");
}
try {
setState(() {
authStatus = "VF"; // AF - Verification Failed
_isLoading = false;
_otpCode.clear();
});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
duration: const Duration(seconds: 3),
backgroundColor: Colors.redAccent,
content: Text(
"VERIFICATION FAILED",
textAlign: TextAlign.center,
style: GoogleFonts.lato(
fontSize: 14,
),
),
));
} catch (e) {
if (kDebugMode) {
print("ERROR2 - ${e.toString()}");
}
}
},
// to-do once otp is sent
codeSent: (String verId, [int? forceCodeReset]) {
setState(() {
verificationID = verId;
});
if (kDebugMode) {
print("CODE SENT");
}
try {
setState(() {
authStatus = "CS"; // CS - Code Sent
_isLoading = false;
// Once OTP has been sent, the dialog box shalql be opened
// otpDialogBox(context).then((value) {});
});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
duration: const Duration(seconds: 3),
backgroundColor: Colors.lime[800],
content: Text(
"OTP CODE SENT",
textAlign: TextAlign.center,
style: GoogleFonts.lato(
fontSize: 14,
),
),
));
} catch (e) {
if (kDebugMode) {
print("ERROR3 - ${e.toString()}");
}
}
},
// to-do if OTP was not recieved and there was a timeout.
codeAutoRetrievalTimeout: (String verId) {
setState(() {
verificationID = verId;
});
if (kDebugMode) {
print("TIMEOUT");
}
try {
setState(() {
authStatus = "TIMEOUT";
_isLoading = false;
_otpCode.clear();
});
ScaffoldMessenger.of(context).showSnackBar(SnackBar(
backgroundColor: Colors.redAccent,
duration: const Duration(seconds: 8),
content: Text(
"TIMEOUT",
textAlign: TextAlign.center,
style: GoogleFonts.lato(
fontSize: 14,
),
),
));
} catch (e) {
if (kDebugMode) {
print("ERROR4 - ${e.toString()}");
}
}
},
);
} catch (e) {
if (kDebugMode) {
print("ERROR5 - ${e.toString()}");
}
}
}
Sign In Code: This method is called to verify otp is correct and sign in user.
Future<void> _signIn(String otp, verificationID) async {
setState(() {
_isVerifying = true;
});
try {
await FirebaseAuth.instance
.signInWithCredential(PhoneAuthProvider.credential(
verificationId: verificationID,
smsCode: otp,
));
} catch (e) {
if (kDebugMode) {
setState(() {
authStatus = "WOC"; // WOC - Wrong OTP Code
_isVerifying = false;
_otpIsWrong = true;
_otpCode.clear();
});
print("Wrong OTP code");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: Colors.redAccent,
content: Text(
"Wrong OTP Code. Try again.",
style: GoogleFonts.lato(
fontSize: 14,
),
),
),
);
}
}
if (_otpIsWrong) {
null;
} else {
Navigator.popAndPushNamed(context, HomeScreen.idScreen); // WITHOUT THIS SIGN IN DOES NOT HAPPEN EVEN IF OTP IS CORRECT.
}
}
I try to figure out, how I can get my database request "signUpUser" to work again. Before I used null-safety my code worked fine, but now after using the dart migration tool I am getting the error:
Expected a value of type '(UserCredential) => FutureOr<UserCredential>', but got one of type '(dynamic) => Future<Null>'
How can I fix this error? I am really desperate, I don't understand this error and I need to have a working code. If I can't fix this error, then I must use a not null-safety code, so I hope you can help me.
The registration works fine, just the database request is throwing an error.
Database request:
Future<bool> signUpUser(String username, String email, String password,
String firstName, String lastName, String? birthday, String? gender) async {
try {
_status = Status.Authenticating;
notifyListeners(); //changing status
FirebaseApp secondaryApp = await Firebase.initializeApp(
name: 'Secondary',
options: Firebase.app().options,
);
try {
UserCredential credential = await FirebaseAuth.instanceFor(
app: secondaryApp)
.createUserWithEmailAndPassword(email: email, password: password)
.then((result) async {
//User user = result.user;
_userServices.createUser(
uid: result.user!.uid,
username: username,
email: email,
firstName: firstName,
lastName: lastName,
birthday: birthday,
gender: gender,
status: 'aktiv',
role: 'User',
);
}as FutureOr<UserCredential> Function(UserCredential));
if (credential.user == null) {
throw 'An error occured. Please try again.';
}
await credential.user!.sendEmailVerification();
} on FirebaseAuthException catch (e) {
print(e);
}
await secondaryApp.delete();
return true;
} catch (e) {
_status = Status.Unauthenticated;
notifyListeners();
print(e.toString());
return false;
}
}
registration:
InkWell(
onTap: () async {
final Formkey = _formKeys.currentState;
print('pw confirmed:' +
passwordConfirmedController.text.trim());
print('pw:' + passwordController.text.trim());
//password and passworconfirm check
if (passwordConfirmedController.text.trim() ==
passwordController.text.trim()) {
//checking if all textfields are not empty
if (usernameController.text.trim() != null &&
emailController.text.trim() != null &&
passwordController.text.trim() != null &&
passwordConfirmedController.text.trim() !=
null &&
firstNameController.text.trim() != null &&
lastNameController.text.trim() != null &&
isDateSelected != false &&
_genderSelected != null) {
// checking if all textfields are valid
if (Formkey!.validate()) {
print('validate okok');
// input is the authProvider.emailController, which provides the written email
// output are all the user informations in a Map<String, dynamic>
// used to check the status and role of the user
mapUserinformations =
await authProvider.getUserByEmail(
emailController.text.trim());
//when email exist, then check status
if (mapUserinformations!.isNotEmpty) {
print('email is already existing');
mapUsernameExist = await authProvider.UsernameExist(mapUserinformations!['username']);
//if username already exist, then print error otherwise it is free
if (mapUsernameExist!.isEmpty){
print('username is free');
//checking if status is deleted
if (mapUserinformations!['status'] ==
'gelöscht') {
print('email is deleted');
//recreate the deleted user
try {
//update user informations
await authProvider.updateUserSignup(
mapUserinformations!['uid'],
mapUserinformations!['username'],
mapUserinformations!['email'],
mapUserinformations!['firstName'],
mapUserinformations!['lastName'],
_birthDateInString,
_genderSelected,
'User');
//input: emailcontroller, output: send password reset link
try {
await FirebaseAuth.instance
.sendPasswordResetEmail(
email: emailController.text
.trim());
} on FirebaseAuthException catch (e) {
print(e);
showDialog(
context: context,
builder: (context) {
return AlertDialog(
content: Text(
e.message.toString()),
);
});
}
clearController();
isDateSelected = false;
_genderSelected = null;
// deleted user got recreated - now print a message that the registration process is completed
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Registration abgeschlossen.\nDein Account war gelöscht, daher wurde dir eine E-Mail zum zurücksetzen deines persönlichen Passworts zugesendet.\nNachdem du das Passwort abgeändert hast, kannst du "
"dich nun in unserer App einloggen.",
textAlign:
TextAlign.center),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context)
.pop();
},
)
],
);
});
} catch (e) {
print(e);
}
}
// email is already existing and the status is not deleted
else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Error: Es existiert schon ein Account mit dieser E-Mail Adresse."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context)
.pop();
},
)
],
);
});
}
}else{
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Error: Der Username wird bereits verwendet. Bitte benutze einen anderen."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
}
// email not existing in database -> mapUserinformations = null
else {
try {
print('email existiert noch nicht');
// sign up user in database with the birthday and gender + all controllers from authProvider
await authProvider.signUpUser(
usernameController.text.trim(),
emailController.text.trim(),
passwordController.text.trim(),
firstNameController.text.trim(),
lastNameController.text.trim(),
_birthDateInString,
_genderSelected);
clearController();
isDateSelected = false;
_genderSelected = null;
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Registration abgeschlossen. Du kannst dich nun in unserer App einloggen."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context)
.pop();
},
)
],
);
});
} catch (e) {
print(e);
}
}
} else {
print('validate email notgoodatall');
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Error: Bitte überprüfe, ob alle deine Eingaben ein gültiges Format aufweisen."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
}
// not all Textfields/Buttons are filled
else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Error: Registration gescheitert! Bitte alle Felder ausfüllen."),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
return;
}
} else {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text(
"Error: Passwort und Passwort wiederholen müssen gleich sein!"),
actions: [
TextButton(
child: Text("Ok"),
onPressed: () {
Navigator.of(context).pop();
},
)
],
);
});
}
},
child: Container(
decoration: BoxDecoration(
color: Colors.deepPurple,
borderRadius: BorderRadius.circular(20)),
alignment: Alignment.center,
width: double.maxFinite,
padding: EdgeInsets.symmetric(vertical: 16),
child: Text(
"Registrieren",
style: TextStyle(
color: Colors.white,
),
))),
#jamesdlin Answered my question. The edited database request looks like this:
Future<bool> signUp(
String username,String email,String password,String firstName,
String lastName,String? birthday,String? gender,String? role) async {
try {
FirebaseApp secondaryApp = await Firebase.initializeApp(
name: 'Secondary',
options: Firebase.app().options,
);
try {
UserCredential? credential = await FirebaseAuth.instanceFor(
app: secondaryApp)
.createUserWithEmailAndPassword(email: email, password: password);
_userServices.createUser(
uid: await credential.user!.uid,
username: username,
email: email,
firstName: firstName,
lastName: lastName,
birthday: birthday,
gender: gender,
status: 'aktiv',
role: role,
);
if (credential.user == null) {
throw 'An error occured. Please try again.';
}
await credential.user!.sendEmailVerification();
print('send verfication');
await secondaryApp.delete();
print('deleted instance');
} on FirebaseAuthException catch (e) {
print(e);
}
return true;
} catch (e) {
print(e.toString());
return false;
}
}
String fullPath;
bool isLoading = false;
#override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.white,
bottomNavigationBar: _bottomTab(),
appBar: AppBar(
title: Text('View'),),
body: Stack(
children: <Widget>[
Align(
alignment: Alignment.center,
child: Visibility(
visible: isLoading, child: CircularProgressIndicator()),
),
Align(
alignment: Alignment.center,
child: Container(
color: Colors.white,
height: MediaQuery.of(context).size.height / 1.5,
child: WebviewScaffold(
url: weburl,
displayZoomControls: true,
withJavascript: true,
scrollBar: true,
withZoom: true,
hidden: true,
),
),
),
],
),
);
}
void _onItemTapped(int index) {
setState(() {
switch (index) {
case 0:
break;
case 1:
_makingPhoneCall();
break;
case 2:
setState(() {
isLoading = true;
getPermission('download');
});
break;
case 3:
setState(() {
isLoading = true;
getPermission('share');
});
break;
}
});
}
void getPermission(String downOrShare) async {
try {
print("getPermission");
Map<Permission, PermissionStatus> permissions =
await [Permission.storage].request();
print(permissions[Permission.storage]);
String path = await ExtStorage.getExternalStoragePublicDirectory(
ExtStorage.DIRECTORY_DOWNLOADS);
fullPath = "$path/" + type + ".pdf";
download2(dio, pdfUrl, fullPath, downOrShare);
} catch (e) {
print(e);
}
}
void shareFile(File file) async {
try {
setState(() {
isLoading = false;
});
if (!await file.exists()) {
await file.create(recursive: true);
file.writeAsStringSync("test for share documents file");
}
ShareExtend.share(file.path, "file");
} catch (e) {
print(e);
}
}
Future download2(
Dio dio, String url, String savePath, String downOrShare) async {
try {
//get pdf from link
Response response = await dio.get(
url,
onReceiveProgress: showDownloadProgress,
//Received data with List<int>
options: Options(
responseType: ResponseType.bytes,
followRedirects: false,
validateStatus: (status) {
return status < 500;
}),
);
//write in download folder
File file = File(savePath);
var raf = file.openSync(mode: FileMode.write);
raf.writeFromSync(response.data);
await raf.close();
if (downOrShare == 'share') {
shareFile(file);
} else if (downOrShare == 'print') {
// printPdf(file);
} else {
isLoading = false;
Fluttertoast.showToast(
msg: type + "Downloaded in " + fullPath,
toastLength: Toast.LENGTH_SHORT,
// gravity: ToastGravity.CENTER,
timeInSecForIosWeb: 1,
backgroundColor: Colors.white,
textColor: Colors.black,
fontSize: 16.0);
}
} catch (e) {
print(e);
}
}
I am using webview and bottom navigation bar in my application. I have download, share option in bottom navigation. Whenever I click the download and share option I want to show CircularProgressIndicator(). Also I have given setState({}) to make visible true or false. Why is it not working?
Move your indicator widget to bottom of webview widget
I have a little question about QR Code Scanning in Flutter. How to open a URL website after successfully reading data from the QR Code?
I use this package for using QR Code, and this for open a URL and this is my function to checking the value of data from QR code is a URL or not and if it's a URL, then run the function to open the website.
checkingValue() {
if (_result != null || _result != "") {
if (_result.contains("https") || _result.contains("http")) {
return _launchURL(_result);
} else {
Toast.show("Invalide URL", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
}
} else {
return null;
}
}
_launchURL(String urlQRCode) async {
String url = urlQRCode;
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
The _result variable is a String to get a value from QR code data.
And this is the full of my code:
class _ScannerPageState extends State<ScannerPage> {
String _password;
String _result = "";
Future _scanQR() async {
try {
String qrResult = await BarcodeScanner.scan();
setState(() {
_result = qrResult;
});
} on PlatformException catch (ex) {
if (ex.code == BarcodeScanner.CameraAccessDenied) {
setState(() {
_result = "Camera permission was denied";
Toast.show(_result, context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
});
} else {
setState(() {
_result = "Unknown Error $ex";
Toast.show(_result, context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
});
}
} on FormatException {
setState(() {
_result = "You pressed the back button before scanning anything";
Toast.show(_result, context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
});
} catch (ex) {
setState(() {
_result = "Unknown Error $ex";
Toast.show(_result, context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
});
}
}
#override
Widget build(BuildContext context) {
return WillPopScope(
onWillPop: () {
return showDialog(
barrierDismissible: false,
context: context,
builder: (BuildContext context) {
return PopUp(
content: "Are you sure want to exit?",
cancelText: "No",
acceptText: "Yes",
onTapCancel: () => Navigator.of(context).pop(),
onTapAccept: () async {
await SessionManager().removeSession();//
await SystemNavigator.pop();
},
);
}
);
},
child: Scaffold(
appBar: AppBar(
title: Text(widget.title),
actions: <Widget>[
IconButton(
icon: Icon(Icons.lock),
onPressed: () {
Navigator.pushNamed(context, '/login');
},
),
],
),
body: Column(
children: <Widget>[
Text(_result.contains("https") || _result.contains("http") ? _result : "Invalid URL"),
],
),
floatingActionButton: FloatingActionButton.extended(
icon: Icon(Icons.camera_alt),
label: Text("Scan"),
onPressed: () => _scanQR(),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
),
);
}
checkingValue() {
if (_result != null || _result != "") {
if (_result.contains("https") || _result.contains("http")) {
return _launchURL(_result);
} else {
Toast.show("Invalide URL", context,
duration: Toast.LENGTH_LONG, gravity: Toast.BOTTOM);
}
} else {
return null;
}
}
_launchURL(String urlQRCode) async {
String url = urlQRCode;
if (await canLaunch(url)) {
await launch(url);
} else {
throw 'Could not launch $url';
}
}
}
So, where I put the checkingValue() function for running it after scanning the QR Code?
Pass qrResult to checkingValue method
Future _scanQR() async {
try {
String qrResult = await BarcodeScanner.scan();
checkingValue(qrResult);
//....
}
checkingValue method
checkingValue(String url) {
//...
}
or call checkingValue() after
setState(() {_result = qrResult;});
checkingValue();
//...
When login button is pressed, I want to show a toast that displays user details in successful or "not found" message otherwise.
new RaisedButton(
onPressed: () {
Future<User> user = _sendToServer();
if (user != null) {
Toast.show("You have logged as ${user.toString()}", context,
duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
} else {
Toast.show("Not found", context,
duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
}
},
child: new Text('log in'),
),
I know that I receive the right response but just unable to display it using toast.
Future<User> _sendToServer() async {
DatabaseHelper helper = DatabaseHelper.instance;
if (_key.currentState.validate()) {
// No any error in validation
_key.currentState.save();
User user = await helper.getLogin(email, password);
print("login user ${user.email}");
return user;
} else {
// validation error
setState(() {
_validate = true;
});
return null;
}
}
RaisedButton(
onPressed: () async{ // mark it async
User user = await _sendToServer(); // await to get user
if (user != null) {
Toast.show("You have logged as ${user.toString()}", context,
duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
} else {
Toast.show("Not found", context,
duration: Toast.LENGTH_SHORT, gravity: Toast.BOTTOM);
}
},
child: new Text('log in'),
)
You should make the onPressed as async and call your function with await or use it like a promise.
For exa -
yourFunctiomWithFuture().then((value) {
// Run code here
}, onError: (error) {
print(error);
});