我正在开发一个 Flutter 应用程序,其中使用 Firebase 身份验证进行电子邮件和密码登录。该应用程序的流程是,用户首先在登录屏幕上输入电子邮件。单击“继续”后,应用程序会检查电子邮件是否已在 Firebase 中注册。如果未注册,他们会收到一条消息,要求他们创建一个帐户。如果电子邮件已注册,他们将进入第二个屏幕,可以在其中输入密码。
我面临的问题是,即使我输入在 Firebase 中注册的电子邮件(我可以在 Firebase 控制台中看到它),它仍然返回消息“电子邮件未注册。”
这是电子邮件屏幕的相关代码,第一个是我创建的用于检查电子邮件是否已验证的函数:
Future<void> checkEmail() async {
String email = emailController.text.trim();
setState(() {
isLoading = true;
});
try {
// Attempt to fetch sign-in methods for the email
List<String> signInMethods =
await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
if (signInMethods.isEmpty) {
// Email is not registered
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Email is not registered. Please create an account.'),
),
);
} else {
// Email is registered, proceed to password screen
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SigninScreenPassword(
email: email,
),
),
);
}
} catch (e) {
// Handle errors
print('Error fetching sign-in methods: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('An error occurred: $e'),
),
);
} finally {
setState(() {
isLoading = false;
});
}
}
您可以在下面看到上下文屏幕的完整代码,包括我调用该函数的位置:
// ignore_for_file: deprecated_member_use
import 'package:cloture/screens/authentication/create_account_screen.dart';
import 'package:cloture/screens/authentication/sign_in_screen_password.dart';
import 'package:cloture/utilities/buttons.dart';
import 'package:cloture/utilities/colors.dart';
import 'package:cloture/utilities/text.dart';
import 'package:cloture/utilities/textfield.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:cloture/gen/assets.gen.dart';
class SigninScreenEmail extends StatefulWidget {
const SigninScreenEmail({super.key});
@override
State<SigninScreenEmail> createState() => _SigninScreenEmailState();
}
class _SigninScreenEmailState extends State<SigninScreenEmail> {
TextEditingController emailController = TextEditingController();
final _formKey = GlobalKey<FormState>();
bool isLoading = false;
Future<void> checkEmail() async {
String email = emailController.text.trim();
setState(() {
isLoading = true;
});
try {
// Fetch sign-in methods for the email
List<String> signInMethods =
await FirebaseAuth.instance.fetchSignInMethodsForEmail(email);
if (signInMethods.isEmpty) {
// Email is not registered
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Email is not registered. Please create an account.'),
),
);
} else {
// Debugging: Print the sign-in methods
print("Sign-in methods for email: $signInMethods");
// Email is registered, proceed to password screen
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => SigninScreenPassword(
email: email,
),
),
);
}
} catch (e) {
// Check for Firebase-specific errors
print('Error fetching sign-in methods: $e');
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('An error occurred: $e'),
),
);
} finally {
setState(() {
isLoading = false;
});
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: white100,
body: SingleChildScrollView(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 27, vertical: 123),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
reusableText(
'Sign in',
32.sp,
FontWeight.bold,
black100,
-0.41,
TextAlign.left,
),
SizedBox(height: 32.h),
Form(
key: _formKey,
child: authTextField(
hintText: 'Email Address',
controller: emailController,
keyboardType: TextInputType.emailAddress,
textInputAction: TextInputAction.done,
validator: (value) {
if (value == null || value.isEmpty) {
return 'Please enter your email';
} else if (!RegExp(r'^[^@]+@[^@]+\.[^@]+')
.hasMatch(value)) {
return 'Please enter a valid email address';
}
return null;
}),
),
SizedBox(
height: 16.h,
),
appButton(
'Continue',
primary200,
white100,
47.h,
344.w,
100.r,
16.sp,
FontWeight.w500,
Colors.transparent,
-0.5,
() {
if (_formKey.currentState!.validate()) {
checkEmail();
}
},
),
SizedBox(
height: 16.h,
),
Row(
mainAxisAlignment: MainAxisAlignment.start,
children: [
reusableText(
'Don\'t have an account?',
12.sp,
FontWeight.w500,
black100,
-0.5,
TextAlign.left,
),
SizedBox(
width: 8.w,
),
GestureDetector(
onTap: () {
Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => const CreateAccountScreen(),
),
);
},
child: reusableText(
'Create One',
12.sp,
FontWeight.bold,
primary200,
-0.5,
TextAlign.left,
),
),
],
),
SizedBox(
height: 71.h,
),
authButton(
'Continue with Apple',
Assets.images.appleSvg.image(height: 24.h),
() {},
),
SizedBox(
height: 12.h,
),
authButton(
'Continue with Google',
Assets.images.googlePng0.image(height: 24.h),
() {},
),
SizedBox(
height: 12.h,
),
authButton(
'Continue with Facebook',
Assets.images.facebookPng0.image(height: 24.h),
() {},
),
SizedBox(
height: 71.h,
),
],
),
),
),
);
}
}
我尝试过的: 已验证 Firebase 项目设置是否正确,因为我可以在 Firebase 控制台中看到注册的电子邮件。 检查输入的电子邮件是否有效并且与 Firebase 中的电子邮件匹配。 在将电子邮件发送到
fetchSignInMethodsForEmail()
之前尝试修剪电子邮件以删除任何前导或尾随空格。
预期行为: 如果 Firebase 中存在电子邮件,应用程序应导航至密码屏幕。 如果电子邮件不存在,它应该显示一条消息,要求用户创建帐户。 实际行为: 即使我输入 Firebase 中存在的电子邮件,我也会收到消息“电子邮件未注册。”
问题: 即使 Firebase 中存在电子邮件,但电子邮件未被识别为已注册的问题,可能是什么原因导致的?我该如何解决这个问题,以便应用程序正确识别注册的电子邮件?
在假设电子邮件未注册之前,请确保您正在检查所有可能的登录方法(Google、Facebook、密码等)。
if (signInMethods.contains('password')) {
// Proceed to password screen
} else if (signInMethods.isNotEmpty) {
// Email registered with another provider (Google, Facebook, etc.)
// Prompt the user to use their associated sign-in method
} else {
// Email is not registered
}
在使用 Firebase 检查之前将电子邮件转换为小写。 进行适当的错误处理。
} catch (e) {
if (e is FirebaseAuthException) {
print('FirebaseAuthException: ${e.message}');
} else {
print('Error: $e');
}
}