What is the best approach to localize the reason of FirebaseAuthWeakPasswordException in Flutter?
In the official documentation a getReason() method is mentioned, but I was not able to find something like a list of potential reasons that I need to catch and localize from that method. The only documented reason for a weak password is the minimum length of 6 characters (maybe this is the only reason?!).
I also was not able to find the source code of the FirebaseAuthWeakPasswordException class and/or the source code where it is used and also not the right file to put in an import statement to import FirebaseAuthWeakPasswordException and also Google search was not helpful. So, basically I do not know where to start (except for sending random weak passwords and checking the responses, which does not guarantee that I will cover every potential reason).
Are there any ideas / best practices how to solve the localization of the weak password exceptions of Firebase in Flutter? I would assume, I am not the only person who wants to explain to users why their password is not excepted.
Class description in docs:
Thrown when using a weak password (less than 6 chars) to create a new account or to update an existing account's password. Use getReason() to get a message with the reason the validation failed that you can display to your users.
The getReason() method just returns a string than reflects the essence of an exception. And the essence is specified in the class description. So, whenever you receive FirebaseAuthWeakPasswordException, you can be sure it happens because password length is less than 6 chars.
I'm not familiar with flutter, but the logic in this case should be like this
if exception class is FirebaseAuthWeakPasswordException then
show error with locale key = LocaleKey_ShortPassError
endif
just fellow this pattern... starting from
on FirebaseAuthException catch (e)
try {
if (_emailT.text.trim().isNotEmpty &&
_pasT.text.trim().isNotEmpty) {
progress!.show();
final _authenticatedUser =auth
.signInWithEmailAndPassword(
email: _emailT.text,
password: _pasT.text);
await _authenticatedUser.user!
.reload();
if (_authenticatedUser
.user!.emailVerified) {
await prefs.setBool(
'loggedIn', true);
progress.dismiss();
if (_remember) {
prefs.setBool('remember', true);
prefs.setString(
'shareEmail', _emailT.text);
prefs.setString(
'sharePass', _pasT.text);
}
Navigator.pushReplacement(
context,
MaterialPageRoute(
builder: (context) =>
VerifyStudent(),
),
);
} else {
progress.dismiss();
openCustomDialog(
context: context,
body:
'your email have not been veriftied',
heading: 'Verification');
}
} else {
progress!.dismiss();
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
backgroundColor: Colors.blue,
content: const Text(
'All filed must not be empty'),
duration:
const Duration(seconds: 2),
));
}
} on FirebaseAuthException catch (e) {
progress!.dismiss();
if (e.code == 'invalid-email') {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
backgroundColor: Colors.blue,
content:
const Text('invalid-email'),
duration:
const Duration(seconds: 2),
));
} else if (e.code ==
'user-disabled') {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
backgroundColor: Colors.blue,
content:
const Text('user-disabled'),
duration:
const Duration(seconds: 2),
));
} else if (e.code ==
'user-not-found') {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
backgroundColor: Colors.blue,
content:
const Text('user-not-found'),
duration:
const Duration(seconds: 2),
));
} else if (e.code ==
'wrong-password') {
ScaffoldMessenger.of(context)
.showSnackBar(SnackBar(
backgroundColor: Colors.blue,
content:
const Text('wrong-password'),
duration:
const Duration(seconds: 2),
));
}
} catch (e) {
progress!.dismiss();
print(e);
}
Related
I have a very tricky situation, which I've reproduced in a demo.
I have a Provider of a user, with this method of updating the listeners:
class User extends ChangeNotifier {
...
User({required this.uid}) {
Database().getUser(uid).listen(
(user) async {
displayName = user?.displayName;
email = user?.email;
phoneNumber = user?.phoneNumber;
photoURL = user?.photoURL;
did = user?.did;
interests = user?.interests;
notifyListeners();
},
onError: (e) => print(e),
);
}
...
}
My main.dart starts like this:
return MultiProvider(
providers: [
ChangeNotifierProvider<AuthState>.value(value: _authState),
ChangeNotifierProvider<ThemeModel>(create: (_) => ThemeModel())
],
child: Consumer<AuthState>(
builder: (context, auth, child) {
var user =
auth.authUser == null ? null : User(uid: auth.authUser!.uid);
return MultiProvider(
providers: [
ChangeNotifierProvider<ZUser?>.value(
value: zuser,
),
],
child: MaterialApp.router(...
This has been sufficient for my use case thus far.
Now, I wish to make an update to the interests field;
I have a DB widget that does:
Future updateUser(String uid, Map<String, Object?> data) async {
return userCollection.doc(uid).update(data);
}
Where the userCollection is my collection in Firestore.
I call this class from my view widget, as:
ZWideButton(
text: "Save",
onPressed: () async {
setState(() {
_localEdit = false;
_loading = true;
});
await user.saveInterests(_interests());
setState(() => _loading = false);
},
),
Where saveInterests is:
Future saveInterests(List<String> interests) async {
return _db.updateUser(uid, {"interests": interests});
}
None of this presents any problem at first -- I can update the interests and it works fine. That is, until I keep updating the interests, and it gets slower and slower each time (the browser says the download time gets longer and longer) and seemingly my computer is eating up more and more memory until the webpage ultimately crashes.
Something of a memory leak appears to be happening, but I'm unsure what about flutter web and firebase could be causing it. I believe it may have to do with the Provider package not disposing appropriately. It does not seem to be the provider as I don't see the Widget being rebuilt over and over. Looking for some thoughts.
For anyone looking; My issue is that my json deserializer was causing an infinite loop with the firebase listener
Im trying to understand what caching videos means and how exactly it works.
The problem that I had was a high bandwidth in my flutter /firebase application . I had like 19gb a day with 10-20 videos and like up to 10 users. So I could not figure out what the problem was. Therefore I contacted firebase support and they say
Looking at the graph, the high bandwidth comes from the storage bucket where the videos are stored. Even though it looks like there are few videos, your bandwidth will increase more and more if your application doesn't store the videos in cache.
Try to double check your applications and ensure that these ones download the information only once.
And I was like what the hak is chaching? And how to do it ?
And will this solve the problem of high bandwidth?
here's how my code looks like
class Videoplayeritem extends StatefulWidget {
final bool mute;
final int pickedvideo;
final int currentPageIndex;
final bool isPaused;
final int pageIndex;
final String videourl;
final String thumbnailUrl;
const Videoplayeritem({
Key key,
this.videourl,
this.currentPageIndex,
this.isPaused,
this.pageIndex,
this.thumbnailUrl,
this.pickedvideo,
this.mute,
}) : super(key: key);
#override
_VideoplayeritemState createState() => _VideoplayeritemState();
}
class _VideoplayeritemState extends State<Videoplayeritem> {
VideoPlayerController videoPlayerController;
bool initialized = false;
bool stopvideo = false;
#override
void initState() {
super.initState();
try {
videoPlayerController = VideoPlayerController.network(
widget.videourl,
videoPlayerOptions: VideoPlayerOptions(mixWithOthers: true),
)..initialize().then((value) {
if (this.mounted) setState(() {});
try {
videoPlayerController?.play();
videoPlayerController?.setLooping(true);
if (widget.mute) {
videoPlayerController?.setVolume(0);
} else if (!widget.mute) {
videoPlayerController?.setVolume(1);
}
} catch (e) {
print('error: $e');
}
});
} catch (e) {
print('error2: $e');
}
print('init');
}
#override
void dispose() {
try {
if (videoPlayerController.value.isPlaying) {
videoPlayerController?.pause();
}
videoPlayerController?.setVolume(0);
videoPlayerController?.dispose();
videoPlayerController = null;
} catch (e) {
print('error3: $e');
}
print('dispose');
super.dispose();
}
#override
Widget build(BuildContext context) {
if (widget.pageIndex == widget.currentPageIndex &&
!widget.isPaused &&
!stopvideo ||
widget.pageIndex == widget.pickedvideo &&
widget.currentPageIndex == null &&
!stopvideo) {
setState(() {
videoPlayerController?.play();
});
} else {
setState(() {
videoPlayerController?.pause();
});
}
if (widget.mute) {
videoPlayerController?.setVolume(0);
} else if (!widget.mute) {
videoPlayerController?.setVolume(1);
}
return Container(
color: Colors.black,
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: Center(
child: videoPlayerController.value.isInitialized
? GestureDetector(
onTap: () {
if (videoPlayerController.value.isPlaying) {
if (this.mounted) {
setState(() {
stopvideo = true;
videoPlayerController?.pause();
});
}
} else {
if (this.mounted) {
setState(() {
stopvideo = false;
videoPlayerController?.play();
videoPlayerController?.setLooping(true);
});
}
}
},
child: VisibilityDetector(
key: Key("unique keys"),
onVisibilityChanged: (VisibilityInfo info) {
debugPrint(
"${info.visibleFraction} of my widget is visible");
if (info.visibleFraction == 0) {
print("pause");
if (stopvideo == false) {
if (this.mounted) {
setState(() {
stopvideo = true;
});
}
}
videoPlayerController?.pause();
} else if (widget.pageIndex == widget.currentPageIndex ||
widget.pageIndex == widget.pickedvideo &&
widget.currentPageIndex == null) {
if (this.mounted) {
if (stopvideo == true) {
setState(() {
stopvideo = false;
});
}
}
videoPlayerController?.play();
} else {}
},
child: Stack(children: [
Center(
child: AspectRatio(
aspectRatio: videoPlayerController.value.aspectRatio,
child: VideoPlayer(videoPlayerController),
),
),
PlayPauseOverlay(
controller: videoPlayerController,
stopvideo: stopvideo,
)
]),
))
: Center(
child: Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
child: CachedNetworkImage(
errorWidget: (context, url, error) => Icon(Icons.error),
imageUrl: widget.thumbnailUrl,
fit: BoxFit.cover,
),
),
)),
);
}
}
My app is playing videos in Preloadpageview which are vertical scrollable like reels in instagram. The videos are loaded from stream .
Hope anyone can explain what chaching exactly mean and how it will affect my high bandwidth . Also how to used it in my case ?
The problem that I had was a high bandwidth in my flutter /firebase application . I had like 19gb a day with 10-20 videos and like up to 10 users.
There are two layers where caching can with this problem: initial video download, and subsequent video replay.
For initial video download, one option is to dedicate a server to act as an intermediary cache. It would download and stay in sync with the current videourl's content and then serve it. The videourls would then be pointed to this server so the client pulls videos from it.
This only moves the problem around though, and bandwidth isn't free. But you don't have to host this cache server, there are companies that will host for a fee.
The way caching can help for subsequent video replay is by keeping it in local temporary storage on the video playing client, and when returning to the video, retrieving it from local temporary storage and playing it - thereby avoiding asking it from the server again.
One possibly quick solution could be by using the better_player library. It allows many configurations, including using a cache. You can find it here
I might be a little late to answer the question, but if you or anybody else out there are still looking for the answer here's how I did it.
After trying every possible library out there I ended up making my own "video cacher". Note: This might not be the prettiest or the slickest solution, but it gets the job done.
On my main file:
Homepage.dart
body: FutureBuilder(
future: FetchPostData,
builder: (context, AsyncSnapshot snapshot) {
if (snapshot.hasData) {
return SizedBox(
child: ListView.builder(
shrinkWrap: true,
itemCount: snapshot.data!.docs.length,
itemBuilder: (context, index) {
return Container(
child: VideoCacher(snapshot.data!.docs[index].data()['VideoUrl'])))
I had a future builder using a cached future stream. Now the data I got form that stream I passed it into another file with a stateful widget called: VideoCacher.dart
VideoCacher.dart
#override
void initState() {
super.initState();
getMedia();
}
Future<void> getMedia() async {
String exp = r'(_.*\.(mp4))';
final RegExp regExp = RegExp(exp);
final String? fileName = regExp.stringMatch(widget._videoUrl);
final Directory tmpDir = Directory.systemTemp;
final File file = File('${tmpDir.path}/$fileName');
if (file.existsSync() == false) {
FirebaseStorage.instance
.ref()
.child('videos')
.child(fileName!)
.writeToFile(file);
setState(() {
_cachedFile = file;
});
} else {
setState(() {
_cachedFile = file;
});
}
}
#override
Widget build(BuildContext context) {
return PostVideoPlayer(_cachedFile);
}
}
In this file I created a tmp location on the system directory where I would download the film from the data I got in stream and pass it on to another file called: VideoPlayer.dart
VideoPlayer.dart
Here I would use the original video_player library provided by flutter team to output the video to my main file.
body: Stack(
alignment: Alignment.bottomCenter,
children: [
SizedBox.expand(
child: FittedBox(
fit: BoxFit.contain,
child: SizedBox(
width: _controller.value.size.width,
height: _controller.value.size.height,
child: VideoPlayer(_controller),
),
),
),
],
),
So the chain would be: Homepage.dart < return VideoCacher.dart <
return VideoPlayer.dart
Prior to this I had my bandwidth consumption at hitting the daily limit in just couple of minutes. Even though I only had 3 videos and total storage of about 2mb.
What I noticed was that anytime you put anything that even remotely relies on fetching data or dynamic data you are bound to run into problems as build method is called every time there is a change. So if you try to get video from storage it will send thousands of requests in succession until you run out of bandwidth.
After this method my bandwidth consumption was around couple mbs, before the video was downloaded and 0mb after it was cached.
Let me know if you found this helpful.
Good Luck.
I have been trying to set my user display name upon signup. All of the solution I have found in stackoverflow suggest to use updateProfile(). But it is deprecated, and flutter docs say to use updateDisplayName instead.
I have tried to implement it in this way,
void donorSignUp() async {
try {
showLoading();
await auth
.createUserWithEmailAndPassword(
email: email.text.trim(), password: password.text.trim())
.then((result) {
String _userId = result.user!.uid;
_addDonorToFirestore(_userId);
_clearSignUpControllers();
result.user?.updateDisplayName(donorModel.value.name);
});
} catch (e) {
debugPrint(e.toString());
Get.snackbar('Sign Up Failed', 'Try again');
}
}
However, when I try to show it in my Drawer, calling user?.displayName it doesn't show anything. I have also checked that donorModel.value.name consists a string value, I know its not null. What should I do?
the function donorSignUp() is called inside an elevatedbutton,
child: ElevatedButton(
child: Text(
'Register',
style: buttonFontSansita,
),
onPressed: () {
if (authController
.signupFormKey.currentState!
.validate()) {
authController.donorSignUp();
}
},
The recommended way to always have the real-time auth state is to use the authStateChanges listener:
FirebaseAuth.instance
.authStateChanges()
.listen((User? user) {
if (user == null) {
print('User is currently signed out!');
} else {
print('User is signed in!');
}
});
You can read more about it here. Ideally you can use a Provider to make the data available through the whole app.
I have released my first app to google play and opened it for several test users.
I am using Firebase Authentication service for managing users.
When my test users try to signup (by email and password), they get an unknown error.
Are there any special changes I need to do before releasing my app?
My functionality is quite simple so I really don't know why they get an error.
Thank you in advance.
Error:
"[firebase_auth/unknown] There was an error while initializing the connection to the GoogleApi: java.lang.NoSuchMethodError: No static method isAtLeastR()Z in class La/d/g/a; or its super classes (declaration of 'a.d.g.a' appears in /data/app/com.omertab.appname--WeJcqqlq_1NPgpgJc96JQ==/base.apk)"
Instance:
final _auth = FirebaseAuth.instance;
My functionality:
MaterialButton(
onPressed: () async {
_showSpinner = true;
try {
final newUser = await _auth.createUserWithEmailAndPassword(email: email, password: password);
if (newUser != null) {
await _fireStore.collection('users').add({
'email': email,
'uId': _auth.currentUser.uid
});
Navigator.pushNamed(context, HomePage.screenId);
_showSpinner = false;
}
} on FirebaseAuthException catch (e) {
_showSpinner = false;
print(e.code);
if(e.code == "invalid-email") {
print("INVALID EMAIL");
setState(() {
signupError = "Invalid mail";
});
} else if(e.code == "invalid-password") {
print("INVALID PASS");
setState(() {
signupError = "Invalid password";
});
} else if(e.code == "weak-password") {
setState(() {
signupError = "Please choose a stronger password";
});
} else if(e.code == "unknown") {
setState(() {
signupError = "Unknown error occurred";
});
}
}
},
minWidth: 200.0,
height: 42.0,
child: Text(
'Signup',
style: TextStyle(color: Colors.white),
),
Issue solved.
I implemented
implementation("com.google.android.gms:play-services-base:17.6.0"){ force = true }
to build.gradle
Not the problem described, but it might help someone. I was getting a different error:
[firebase_auth/unknown] com.google.firebase.FirebaseException: An internal error has occurred. [ CONFIGURATION_NOT_FOUND ]
I've solved it by activating the authentication service in the Firebase console.
I'm currently creating an app using Flutter.
The goal is to check to see if an account's email is verified before logging them in.
As it is now, a user signs in to their account using Auth.signInWithEmailAndPassword
At this point, Auth.isEmailVerified returns false
Afterwards, a verification email is sent, the user then clicks on the link to verify their account and a window popup appears stating that their account is now verified.
The user tries to login again, but Auth.isEmailVerified still returns false.
Any ideas?
This is the auth.dart class file I'm using.
https://github.com/AndriousSolutions/auth/blob/master/lib/auth.dart
And this is my code.
child: MaterialButton(
minWidth: 200.0,
height: 42.0,
onPressed: () async {
if (_formKey.currentState.validate()) {
Auth.signInWithEmailAndPassword(
email: emailAddressController.text,
password: passwordController.text)
.then((onSuccess) {
Auth.reload();
if ((onSuccess)) {
if (Auth.isEmailVerified) {
db.createUser(
emailAddress: Auth.email,
firstName: Tools.getFirstName(Auth.displayName),
googleAccount: false);
Navigator.of(context).pushReplacementNamed(HomePage.tag);
} else {
emailVerificationDialog(context);
Auth.sendEmailVerification();
}
}
}).catchError((e) {
print(" LSAHJDSAKHDSA " + e);
});
}
},
color: ThemeSettings.RaisedButtonColor,
child: Text('Log In', style: TextStyle(color: Colors.white)),
),
Thank you so so much!!
Looking at the library that you are using the Auth.reload call needs to be awaited. It should be
static Future<bool> reload() async {
await _user?.reload();
return _setUserFromFireBase(_user);
}
Since it is not awaiting on reload, the your code simply keeps on going and it checks isEmailVerified before it has a chance to complete the reload.
This issue is reporting it which I have shared this info.