I am trying to make an app with a login function and I want to keep the user logged in.
I'm using Firebase auth and android studio.
This is what I tried:
auth.signInWithEmailAndPassword(txt_email, txt_password)
.addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()){
Intent intent = new Intent(login.this, sendForm.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
finish();
}
else {
Toast.makeText(login.this, "cant sing in", Toast.LENGTH_SHORT).show();
}
}
});
First you need to check if the user exists when you log in to the app from second time. If the user exists you directly take him to the MainActivity else you'll take him to the LoginActivity.
So, your launchActivity should be something that is other then Login/Main activities. Typically, it would be a splash screen. So, let's say you're launch activity is SplashActivity.
Now, in your SplashActivity.java onCreate() do this:
FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
if (Objects.nonNull(currentUser)) {
// This means that user has already logged into the app once.
// So you can redirect to MainActivity.java
startActivity(new Intent(this, MainActivity.class));
} else {
// This means no user logged into the app before.
// So you can redirect to LoginActivity.java
startActivity(new Intent(this, LoginActivity.class));
}
If you don't want to use a SplashScreen, you can check for the user existence in LoginActivity.java using FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser(); and redirect him to MainActivity if currentUser is nonNull.
I want to keep the user logged in.
This is happening by default. There is nothing special that you need to do in order to keep your users logged in. They will be logged in until they explicitly sign out. Here is the official documentation for Android:
https://firebase.google.com/docs/auth/android/start/
If you want to keep track of the auth state, then please check my answer from the following post:
One time login in app - FirebaseAuth
Besides that, please also note that the state of being "signed in" doesn't depend on internet connectivity but on the user token currently in use, which is present locally and has not expired after one hour since the last refresh.
Related
I have implemented Sign In the method using Google Accounts, my problem is the logout function doesn't behave what I want. I don't receive any error, it's just the code doesn't work properly.
Can someone tell me what's wrong with this code?
Options Fragment:
Preference logoutPreference = findPreference(getString(R.string.pref_key_logout));
logoutPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
public boolean onPreferenceClick(Preference preference) {
FirebaseAuth.getInstance().signOut();
Intent broadcastIntent = new Intent();
broadcastIntent.setAction("com.example.budgetapp.ACTION_LOGOUT");
getActivity().sendBroadcast(broadcastIntent);
getActivity().startActivity(new Intent(getActivity(), SignInActivity.class));
getActivity().finish();
return true;
}
});
Main Activity:
#Override
protected void onResume() {
super.onResume();
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("com.example.budgetapp.ACTION_LOGOUT");
receiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
finish();
}
};
registerReceiver(receiver, intentFilter);
}
Why is the code not working? I'm using Firebase Realtime Database
Whenever I click Logout the app redirects me to Sign In Activity (which is good) but when I try to Sign In, it automatically signs in to the previous Google Account.
When you are using the following line of code:
FirebaseAuth.getInstance().signOut();
It means that you are signing out only from Firebase.
Whenever I click Logout the app redirects me to Sign In Activity (which is good) but when I try to Sign In, it automatically signs in to the previous Google Account.
As I understand, you are using the Google Provider for authentication. Signing out from Firebase doesn't mean that you are automatically signed out from Google. To sign out from Google you have to explicitly add a call to GoogleSignInClient#signOut() method:
googleSignInClient.signOut();
Don't also forget that the sign-out operation is asynchronous, meaning that you have to wait until the operation completes. Since this method returns an object of type Task<Void>, you can use addOnCompleteListener(OnCompleteListener listener) method, to know when you are completely signed out.
i want to make a swiggy type app. i have integrated gmail login in my login screen and it changes to dashboard activity on success but when i click on account tab it goes back to dashboard screen instead of account activity. pls help......
login screen
dashboard
if you want any portion of code just comment and i will update
//login screen part
//check if already signed in using google
account = GoogleSignIn.getLastSignedInAccount(this);
if(account!=null) {
finish();
Intent intent = new Intent(this, DashboardActivity.class);
startActivity(intent);
return;
}
//onclicklistener added
//method
private void googleSignin() {
Intent signInIntent = mGoogleSignInClient.getSignInIntent();
startActivityForResult(signInIntent, RC_SIGN_IN);
}
onActivity result(//params provided){
if(googleLogin){
// Result returned from launching the Intent from GoogleSignInClient.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
// The Task returned from this call is always completed, no need to attach
// a listener.
googleLogin = false; //set to false so that it can be set true again if login is actually successful
Task<GoogleSignInAccount> task = GoogleSignIn.getSignedInAccountFromIntent(data);
handleSignInResult(task);
}
}
}
private void handleSignInResult(Task<GoogleSignInAccount> completedTask) {
try {
GoogleSignInAccount account = completedTask.getResult(ApiException.class);
// Signed in successfully, show authenticated UI.
sessionManager.setLogin(true);
googleLogin = true;
Intent intent = new Intent(this,DashboardActivity.class);
intent.putExtra("googleLogin", googleLogin);
startActivity(intent);
finish();
}
//Dashboard part
Intent i = new Intent(DashboardActivity.this ,MyAccountActivity.class);
i.putExtra("googleLogin", googleLogin);
startActivity(i);
//myaccount part
if(googleLogin){
GoogleSignInAccount acct = GoogleSignIn.getLastSignedInAccount(this);
if (acct != null) {
String personName = acct.getDisplayName();
//System.out.println(personName); working fine
account_name.setText(personName);
String personEmail = acct.getEmail();
//System.out.println(personEmail); fine
account_email.setText(personEmail);
account_mobile.setText("+91 1234567890");
// System.out.println(googleLogin);
// System.out.println(fbLogin);
}
}
solved this problem.
the issue was gmail was not able to provide account details for use when i tried to display them in MY ACCOUNT activity that i integrated in my app, thats why it kept on getting crashed. the code was correct thats why it wasnt giving any error i even tried logging it. there it showed correct details but still it wasnt displaying the result in text views.
so what i did was use shared preferences. everytime the user logs in using gmail, the details are stored in them and i retrieve it in MY ACCOUNT activity and yes it displayed the results correctly.
let me know if you need any more help.
private void startUpTasks() {
Boolean isFirstRun = getSharedPreferences("PREFERENCE", MODE_PRIVATE).getBoolean("isFirstRun", true);
// If the activity has never started before...
if (isFirstRun) {
// Launch app intro
Intent i = new Intent(LoginActivity.this, EnterInfoActivity.class);
startActivity(i);
getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit()
.putBoolean("isFirstRun", false).apply();
initializeUserInfo();
} else {
getUserInfo();
Intent myIntent = new Intent(LoginActivity.this, SplashScreen.class);
LoginActivity.this.startActivity(myIntent);
}
}
Basically I have it narrowed down that the check goes straight to the else statement which doesn't allow a user to register for the first time. I'm using Firebase Auth to register a new user and store them in Firebase's Database.
Any ideas on how to fix this?
Okay look I will try to help you understand what you should do:
I assume that you want the user to go to EnterInfoActivity only if they didn't register before, and you are using sharedPreferences to do so. If that is the case:
This code:
getSharedPreferences("PREFERENCE", MODE_PRIVATE).edit()
.putBoolean("isFirstRun", false).apply();
Must be added after the user registered the details in the EnterInfoActivity
Other than that
If you want to test the functionality again, you must uninstall the app to clear shared preferences data and run the app again to test again as if you are a new user that installed the app, this way if-statement must run instead of else.
I have a SignInActivity with Firebase AuthStateListener.
final FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
final FirebaseAuth.AuthStateListener firebaseAuthListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(FirebaseAuth auth) {
FirebaseUser user = auth.getCurrentUser();
if (user != null && user.isEmailVerified()) {
firebaseAuth.removeAuthStateListener(this);
startActivity(new Intent(LoginActivity.this, MainActivity.class));
}
}
};
firebaseAuth.addAuthStateListener(firebaseAuthListener);
When I successfully registered a new Account, I setVisibity(View.Visible) a verify page with EditTextEmail & VerifyButton inside the activity (in case someone wants to resend the email verification).
What I want to do is when I verify my email from my email account, I want the page to automatically start my MainActivity instead of just staying idle in my LoginActivity, like SMS verification, when verification code received in SMS, the app reads the SMS and navigate to MainActivity. Is it possible to achieve this with email verification? Because the FirebaseAuthState never changed even after I click on verification link on my email.
I need something like OnFirebaseAuthUserEmailVerifiedListener
I'm new to firebase, please kindly give me advice on how to achieve this or if it is not possible.
This link is really useful.
Because the FirebaseAuthState never changed even after I click on verification link on my email.
That's because the user is cached, and you need to reload the user:
Do note that the FirebaseUser object is cached within an app session, so if you want to check on the verification state of a user, it's a good idea to call .getCurrentUser().reload() for an update.
You need something like this
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user.isEmailVerified())
{
// user is verified, so you can finish this activity or send user to activity which you want.
finish();
Toast.makeText(LoginActivity.this, "Successfully logged in", Toast.LENGTH_SHORT).show();
}
else
{
// email is not verified, so just prompt the message to the user and restart this activity.
sendVerificationEmail();
}
}
And method to get emailVerification
private void sendVerificationEmail(){
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.sendEmailVerification()
.addOnCompleteListener(new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
if (task.isSuccessful()) {
// email sent
// after email is sent just logout the user and finish this activity
FirebaseAuth.getInstance().signOut();
startActivity(new Intent(SignupActivity.this, LoginActivity.class));
finish();
}
else{
// email not sent, so display message and restart the activity or do whatever you wish to do
}
}
});
}
Hope this helps you.
When I call mFirebaseAuth.signOut() or mFirebaseUser.delete() my FirebaseAuth.AuthStateListener() works correctly and returns null as FirebaseUser instance in onAuthStateChanged, I refresh UI and show "Sign in with Google" button.
But when I want to log in again, I don't see the dialog with users (I have 2 users on my device, attached the image). The app shows this dialog only in first sign in, after that it uses the same user. If I clear app's data on the settings screen I will be able to see this dialog again.
My question is how to show this dialog after every sign out.
I run this code when press Sign In button:
// in onCreate()
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
mGoogleApiClient = new GoogleApiClient.Builder(this)
.enableAutoManage(this /* FragmentActivity */, this /* OnConnectionFailedListener */)
.addApi(Auth.GOOGLE_SIGN_IN_API, gso)
.build();
// in OnClickListener
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, FirebaseActivity.REQUEST_SIGN_IN);
In onActivityResult(), I get an instance of GoogleSignInResult so everything I need happens after I call startActivityForResult().
In the Firebase Auth Quickstart sample code, the sign-out for Google provider includes these steps. Are you calling GoogleSignInClient.signOut() when you sign-out?
private void signOut() {
// Firebase sign out
mAuth.signOut();
// Google sign out
mGoogleSignInClient.signOut().addOnCompleteListener(this,
new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
updateUI(null);
}
});
}
Another option is to use the FirebaseUI library. It simplifies sign in and sign out operations in a sense that it will do all the heavy lifting for you.
Kotlin
AuthUI.getInstance().signOut(this).addOnCompleteListener {
// do something here
}
Java
AuthUI.getInstance()
.signOut(ActivityMainOld.this)
.addOnCompleteListener(new OnCompleteListener<Void>(){
#Override
public void onComplete(#NonNull Task<Void> task) {
// do something here
}
});
Hope this helps
I was confused since all of the solutions required having a reference to the GoogleSignInClient, but it is actually not required for you to hold a reference to it, you can simply create a new instance and call signOut() on it.
GoogleSignIn.getClient(
getContext(),
new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build()
).signOut();
For anyone else who wants this result (as in getting the google account options back) on a different activity.
public static void signOut() {
// Firebase sign out
mAuth.signOut();
// Google sign out
Auth.GoogleSignInApi.signOut(mGoogleApiClient);
}
Add this on the sign in page, and before you pass to the next activity, just call SignOut().
// everything ok...
signOut();
startActivity(new Intent(SignIn.this,NextOne.class));
and then, in your other class you can call
FirebaseAuth.getInstance().signOut();
startActivity(new Intent(NextClass.this, SignIn.class));
It's easy, and it will work. Cheers!
You can also define something like this:
private void signOut() {
mAuth.signOut();
mGoogleSignInClient.signOut().addOnCompleteListener(this,
new OnCompleteListener<Void>() {
#Override
public void onComplete(#NonNull Task<Void> task) {
Intent intent = new Intent(YourActivity.this, NextActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
}
});
}
None of the above did fix the issue for me,
accepted answer requires access to mGoogleApiClient defined in login view (normally log out button is in settings view)
another answer was suggesting to logout in the login view (after successful login and just before launching to the main view). This was addressing the mGoogleApiClient accessibility issue, but the issue with this approach is every time user opens the app it ends up in login view and requires to log in every time which is not ideal.
So here is what I ended up doing and it is kind of all-round fix that support all the third-party log out options (in my case Facebook and Google)
logOutButton.setOnSingleClickListener {
FirebaseAuth.getInstance().currentUser?.getIdToken(false)?.addOnSuccessListener {
result ->
when (result.signInProvider){
"facebook.com" -> {
LoginManager.getInstance().logOut()
signOutFromApp()
}
"google.com" -> {
GoogleSignIn.getClient(
this,
GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN).build()
).signOut()
signOutFromApp()
}
else -> {
signOutFromApp()
}
}
}
}
private fun signOutFromApp() {
FirebaseAuth.getInstance().signOut()
LauncherActivity.start(this) //starts login view
finish() //finish settigs view
}
private void sendToLogin() { //funtion
GoogleSignInClient mGoogleSignInClient ;
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
mGoogleSignInClient = GoogleSignIn.getClient(getBaseContext(), gso);
mGoogleSignInClient.signOut().addOnCompleteListener(/*CURRENT CLASS */.this,
new OnCompleteListener<Void>() { //signout Google
#Override
public void onComplete(#NonNull Task<Void> task) {
FirebaseAuth.getInstance().signOut(); //signout firebase
Intent setupIntent = new Intent(getBaseContext(), /*To ur activity calss*/);
Toast.makeText(getBaseContext(), "Logged Out", Toast.LENGTH_LONG).show(); //if u want to show some text
setupIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(setupIntent);
finish();
}
});
}
this code is written to work as copy past just read COMMENTS in code to customize it to ur needs, i prefer to send user to login
I did mGoogleSignInClient.signOut()
this is working as expected.
you can set a custom parameter for the GoogleAuthProvider to force user to re authenticate via google.
var provider = new Firebase.auth.GoogleAuthProvider();
provider.setCustomParameters({
prompt: 'select_account'
});
Use same instances of Firebase Auth and GoogleSignInClient,
for example, If we declared and instantiated a Firebase Auth called mAuth in LoginActivity,
Then if we declare a new mAuth in other activity and try to call mAuth.login, it will not work properly.
Make Firebase Auth and GoogleSignInClient variables public and static and use the same from the other activities
For flutter use,
await GoogleSignIn().signOut();
await _auth.signOut();