Handling asynchronous wifi check in Flutter application - asynchronous

I'm making a Flutter App where I want to check whether or not a user has wifi enabled before proceeding to a different action.
if (wifiEnabled) {
//Do stuff
}
else {
//Tell the user to turn on wifi
}
I have a code snippet that allows me to check whether a user has an internet connection from this post. Check whether there is an Internet connection available on Flutter app
void _checkWifi() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
_wifiEnabled = true;
}
} on SocketException catch (_) {
print('not connected');
_wifiEnabled = false;
}
}
The issue I am having though is that because the checkWifi function is asynchronous. If the user goes from having no wifi to having wifi the boolean isn't updated by the time the if(wifiEnabled) code is checked so according to the logic wifiEnabled will be false, despite the user having wifi.
If the user were to try again however they would have wifi as the wifiEnabled will be updated to true. I've tried using Timer and Future.delayed but I haven't been able to solve my issue so far.
Any advice for dealing with the issue or async calls in general would be very helpful. Thanks

Hope below code helps you to get the idea.
class YourWidget extends StatelessWidget {
#override
Widget build(BuildContext context) {
showWifiAlert();
return ...
}
void showWifiAlert() async {
var wifiEnabled = await getWifiStatus();
if (wifiEnabled) {
//Do stuff
}
else {
//Ask user to enable internet
}
}
Future<bool> getWifiStatus() async {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
print('connected');
return true;
}
} on SocketException catch (_) {
print('not connected');
return false;
}
}
}

Related

Not able to update the page if the user is logged in or not. FlutterFire

I was doing a project and I encounter a problem. I want the app changes page if the user is logged in or not even if it's starting the app. I came up with an idea to have a widget under the root called Wrapper that has a function to change each time the authentication state changes.
But it doesn't work...
Could you guys help me with that?
The Wrapper class:
class Wrapper extends StatelessWidget {
#override
Widget build(BuildContext context) {
if(updateUserStatus())
return Home();
else
return Authenticate();
}
bool updateUserStatus() {
bool isLogged = false;
FirebaseAuth.instance.authStateChanges().listen((User user) {
if (user == null) {
isLogged = false;
print("User Not logged");
} else {
isLogged = true;
print("User logged");
}
});
return isLogged;
}
}
The output on the Debug console is right but, the page doesn't change.
Sorry, brother for not answering in details. But I had encountered the same problem, to solve this issue I watched the following playlist in youtube, it gives solution to your problem, but you have to watch it till the end.This is a link https://www.youtube.com/watch?v=u_Lyx8KJWpg&list=PLNnAcB93JKV_NIGSneTazb9yMpILapEjo

Catch Socket Exception [duplicate]

This is probably a noob question, but how do I make my response throw an exception if the user does not have an internet connection or if it takes too long to fetch the data?
Future<TransactionModel> getDetailedTransaction(String crypto) async {
//TODO Make it return an error if there is no internet or takes too long!
http.Response response = await http.get(crypto);
return parsedJson(response);
}
You should surround it with try catch block, like so:
import 'package:http/http.dart' as http;
int timeout = 5;
try {
http.Response response = await http.get('someUrl').
timeout(Duration(seconds: timeout));
if (response.statusCode == 200) {
// do something
} else {
// handle it
}
} on TimeoutException catch (e) {
print('Timeout Error: $e');
} on SocketException catch (e) {
print('Socket Error: $e');
} on Error catch (e) {
print('General Error: $e');
}
Socket exception will be raised immediately if the phone is aware that there is no connectivity (like both WiFi and Data connection are turned off).
Timeout exception will be raised after the given timeout, like if the server takes too long to reply or users connection is very poor etc.
Also don't forget to handle the situation if the response code isn't = 200.
You don't need to use http to check the connectivity yourself, simply use connectivity library
You can use this plugin https://pub.dev/packages/data_connection_checker
So you can check prior if you have the connection, if not give a alert to the user that no internet connection. And if you have the internet connection then just proceed to your fetching part.
I will just link some resources below where it has been explained perfectly:
https://www.youtube.com/watch?v=u_Xyqo6lhFE
This is all things will be done prior to making an http call, but what if while making an http call the internet goes off then you can use the try catch block which #uros has mentioned.
Let me know if it works.
This is my approach to check internet connection to check internet connection throughout full app
i create a common class called "connectivity" & use it everywhere in app to check connectivity.i use connectivity package by flutter.
My connectivity class
Future<bool> check() async {
var connectivityResult = await (Connectivity().checkConnectivity());
if (connectivityResult == ConnectivityResult.mobile) {
return true;
} else if (connectivityResult == ConnectivityResult.wifi) {
return true;
}
return false;
}
then i use this class like this:
#override
void initState() {
super.initState();
checkInternetConnection().then((internet) {
if (internet != null && internet) {
// Internet Present Case
// do your task;
} else {
// No-Internet Case
showAlertDialog(context);
}
});
}

Best way to read a user on init

I have a problem, when I go to the view of the home in my app I have to instantiate a user from firebase, at the time of obtaining the name is null.
I do not know how to bring a user and expect it to load asynchronously because the initial state of the widget does not allow the asynchronous tag.
If I assign it to 'Then' it is also null
Thank you!
//Home Widget State
User currentUser = widget.userController.getCurrentUser(); //ERROR
//CONTROLLER
Future<User> getCurrentUser() async {
User user = await _db.collection('users').document(await getCurrentUserUID()).get().then((snapshot){
return User.fromJson(snapshot.data);
});
print(user.toString());
return user;
}
I'm assuming you're looking for something like this?
Map _userProfile;
#override
void initState() {
super.initState();
FirebaseAuth.instance.onAuthStateChanged.listen((user) {
if(user != null) _getUserProfile(user.uid);
});
}
void getUserProfile(String uid) {
_db.collection('users').document(uid).get().then((snapshot){
setState(() {
_userProfile = snapshot.data;
});
});
}

Changing phone number for Firebase Phone Auth creates a new user UID? [duplicate]

I am using Android Firebase Auth Ui for providing Phone Number based sign in option in an android app. I am trying to provide an additional option to signed in users to switch their signed in phone number to another number keeping the same user account.
But as per Firebase Docs for Phone number there are no options to change the signed in number.
There are options for linking different auth providers like email, google or Facebook login etc to same account. But there is no way mentioned about how to change the phone number or email id keeping the same user id.
Is there a workaround or method by which we can achieve this?
An API exists for updating the phone number of a current user: FirebaseUser#updatePhoneNumber(PhoneAuthCredential credential)
I also had this challenge to update user phone number and when I go on documentation I got something by using I have done this task.
you can go for documentation by click here
Now the method you can use : - for java android project.
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential( "+91-98298XXXX2", "OTP_CODE" );
// Update Mobile Number...
firebaseAuth.getCurrentUser().updatePhoneNumber(phoneAuthCredential)
.addOnCompleteListener(new OnCompleteListener <Void>() {
#Override
public void onComplete(#NonNull Task <Void> task) {
if (task.isSuccessful()) {
// Update Successfully
} else {
// Failed
}
}
}
);
val options = PhoneAuthOptions.newBuilder(FirebaseAuth.getInstance())
.setPhoneNumber(phoneNumber) // Phone number to verify
.setTimeout(100L, TimeUnit.SECONDS) // Timeout and unit
.setActivity(activity) // Activity (for callback binding)
.setCallbacks(returnCallBack()) // OnVerificationStateChangedCallbacks
.build()
PhoneAuthProvider.verifyPhoneNumber(options)
private fun returnCallBack() = object : PhoneAuthProvider
.OnVerificationStateChangedCallbacks() {
override fun onVerificationCompleted(credential: PhoneAuthCredential) {
FirebaseAuth.getCurrentUser()?.updatePhoneNumber(credential)
}
override fun onVerificationFailed(e: FirebaseException) {
// This callback is invoked in an invalid request for verification is made,
// for instance if the the phone number format is not valid.
Log.e("phone", e.toString())
}
override fun onCodeSent(verificationId: String, token: PhoneAuthProvider.ForceResendingToken) {
//You need this to pass as a parameter for the update method call.
vericationSent = verificationId
}
}
fun confirmChange(code: String, context: Context?) {
if(code.contains(Regex(onlyNumber))) {
Log.d("codeSent" , "Right code : $code")
FirebaseAuth.getCurrentUser()
?.updatePhoneNumber(PhoneAuthProvider.getCredential(vericationSent, code))
?.addOnCompleteListener {task ->
//it worked if you reach here.
}?.addOnFailureListener {
//Show the error to user
}
}
vericationSent = EMPTY
} else {
Log.d("codeSent" , "wrong code : $code")
}
}
Try this
//Send otp to phone number
String verificationId;
private void startLoginFirebase(){
PhoneAuthProvider.getInstance(firebaseAuth).verifyPhoneNumber(phone, 90L, TimeUnit.SECONDS, PhoneAuthActivity.this, new PhoneAuthProvider.OnVerificationStateChangedCallbacks() {
#Override
public void onCodeSent(#NonNull String s, #NonNull PhoneAuthProvider.ForceResendingToken forceResendingToken) {
super.onCodeSent(s, forceResendingToken);
verificationId = s;
updatePhoneNum();
}
#Override
public void onCodeAutoRetrievalTimeOut(#NonNull String s) {
super.onCodeAutoRetrievalTimeOut(s);
}
#Override
public void onVerificationCompleted(#NonNull PhoneAuthCredential phoneAuthCredential) {
}
#Override
public void onVerificationFailed(#NonNull FirebaseException e) {
processFurther(e.getLocalizedMessage().toString(), 0);
}
});
}
//Verify Otp
private void updatePhoneNum(){
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential(verificationId, otp);
firebaseAuth.getCurrentUser().updatePhoneNumber(phoneAuthCredential).addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
}
});
}
Apparently - according to the project maintainers - FirebaseUI-Android doesn't support this feature, and it looks like they have no plans of doing it any time soon :(

Firebase AuthUI Smartlock Cleanup

In Firebase, I am using AuthUI for Sign In. I tried FirebaseAuth.getInstance.signout() to remove the current user credentials, but I think maybe for Google SmartLock credentials, it's not signing out. Help me out.
My Code:
mAuthStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null){
if (user.getEmail().equals("example#gmail.com")){
//Codes to implement
} else {
FirebaseAuth.getInstance().signOut();
}
} else {
startActivityForResult(
AuthUI.getInstance()
.createSignInIntentBuilder()
.setIsSmartLockEnabled(false)
.setProviders(Arrays.asList(
new AuthUI.IdpConfig.Builder(AuthUI.GOOGLE_PROVIDER).build()))
.build(), RC_SIGN_IN
);
}
}
};
}
For me the fix was;
AuthUI.getInstance().setIsSmartLockEnabled(false)...
When logging in, and then;
AuthUI.signOut(context)
When Signing out

Resources