This question already has answers here:
One time login in app - FirebaseAuth
(3 answers)
Closed 3 years ago.
I have an application there is user login screen sends to an activity if logging action is OK. But everytime I closed the application, app asks for email and password, I want to stay logged in like instagram or facebook. Have can I do that? And also how can I do that, do I have to change the code in signin activity or create another class for saving the current user, I am so much confused. There is my login code for firebase:
SignInActivity;
public class SignInActivity extends AppCompatActivity {
private EditText SignInMail, SignInPass;
private FirebaseAuth auth;
private Button SignInButton;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//Get Firebase auth instance
auth = FirebaseAuth.getInstance();
// set the view now
setContentView(R.layout.activity_signin);
SignInMail = (EditText) findViewById(R.id.SignInMail);
SignInPass = (EditText) findViewById(R.id.SignInPass);
SignInButton = (Button) findViewById(R.id.SignInButton);
//Get Firebase auth instance
auth = FirebaseAuth.getInstance();
SignInButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String email = SignInMail.getText().toString();
final String password = SignInPass.getText().toString();
if (TextUtils.isEmpty(email)) {
Toast.makeText(getApplicationContext(), "Mail", Toast.LENGTH_SHORT).show();
return;
}
if (TextUtils.isEmpty(password)) {
Toast.makeText(getApplicationContext(), "Password", Toast.LENGTH_SHORT).show();
return;
}
//authenticate user
auth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(SignInActivity.this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
// progressBar.setVisibility(View.GONE);
if (!task.isSuccessful()) {
// there was an error
if (password.length() < 8) {
Toast.makeText(getApplicationContext(),"pass min 8",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(getApplicationContext(),"error",Toast.LENGTH_SHORT).show();
}
} else {
Intent intent = new Intent(SignInActivity.this, CampaignActivity.class);
startActivity(intent);
finish();
}
}
});
}
});
}
public void NavigateSignUp(View v) {
Intent inent = new Intent(this, SignupActivity.class);
startActivity(inent);
}
public void NavigateForgetMyPassword(View v) {
Intent inent = new Intent(this, ResetPasswordActivity.class);
startActivity(inent);
}
}
In the onCreate function, you need to add this piece of code
FirebaseUser user=FirebaseAuth.getInstance().getCurrentUser();
This code will fetch you the currently logged in user if the user has previously signed in, else will return null.
Check this link for further understanding.
Get the currently signed-in user - Firebase Docs
I hope this solved your problem. If you feel this answer is correct, please accept the answer.
When a user logged in successfully store the LOGIN TYPE of User SharedPreferenceence and check that flag again when user restart app. If Shared Preference contains value then just take him to Main Screen.
Like this on each login update this value and check
PreferencesManager.getInstance().getString(ANNONYMOUS_SIGNUP_DATE, "")) && (PreferencesManager.getInstance().getInt(LOGIN_TYPE, 0) == LOGIN_TYPE_ANNONYMOUS)
Since you authenticated the user, then you can create a splash screen before your sign in activity, and write the following code:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null){
Intent i = new Intent(SplashActivity.this, HomeActivity.class);
} else{
Intent i = new Intent(SplashActivity.this, SignInActivity.class);
}
Here, you check if currently there is a logged in user and then navigate to the right activity according to the condition.
I would recommend you to use splash screen first and check it user is logged in by the following
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// User is signed in
// go to main page
} else {
// No user is signed in
// go to loging page
}
Related
This question already has answers here:
How to redirect multiple types of users to their respective Activities?
(3 answers)
Checking if a particular value exists in the Firebase database
(6 answers)
Closed 2 years ago.
First, I will tell the flow of my App.
Login Screen(SignInActivity.java) -> Enter details(MainActivity.java) ->Home Screen(HomeScreenActivity.java)
In my app, I have used Firebase Authentication and Firebase Database. When the user is new, then it should go to Main Activity from SignInActivity where user enters his name, a short description and his hobby. The details are stored in Firebase Database and then HomeScreenActivity opens where user details are shown in Recycler View.
But currently what happens is when same user does login again, it again asks user for details. I want to check if users Google Account already exists in Firebase Auth, then instead of asking details, it should directly go to HomeScreenActivity.
I checked many answers on StackOverflow, but nothing seems to work. One thing that i tried was additionalUserInfo.isNewUser but in this app crashes when user does login again, showing null error where I display user details in HomeScreenActivity.
SignInActivity.java
private void firebaseAuthWithGoogle(String idToken) {
AuthCredential credential = GoogleAuthProvider.getCredential(idToken, null);
mAuthIn.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
// Sign in success, update UI with the signed-in user's information
Log.d(TAG, "SignInWithCredential:success");
startActivity(new Intent(SignInActivity.this, MainActivity.class));
finish();
} else {
// If sign in fails, display a message to the user.
Toast.makeText(SignInActivity.this, "Authentication Failed", Toast.LENGTH_SHORT).show();
}
}
});
}
MainActivity.java
public void init() {
hobbiesContinueButton.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
String name=user.getText().toString().trim();
String desc=description.getText().toString().trim();
String hobby=spinner.getSelectedItem().toString();
String image="default";
String thumbnail="default";
if(!TextUtils.isEmpty(name))
{
FirebaseUser currentUser = FirebaseAuth.getInstance().getCurrentUser();
assert currentUser != null;
String userId=currentUser.getUid();
User user=new User(name,hobby,desc,image,thumbnail);
dbRef.child(userId).setValue(user);
startActivity(new Intent(getApplicationContext(), HomeScreenActivity.class));
finish();
}
else
{
Toast.makeText(getApplicationContext(), "Enter a name",Toast.LENGTH_SHORT).show();
}
}
});
}
HomeScreenActivity.java
dbRef.addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot snapshot) {
imgvw = headerView.findViewById(R.id.imageView);
imgvw.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
//to open gallery
Intent galleryIntent = new Intent();
galleryIntent.setType("image/*");
galleryIntent.setAction(Intent.ACTION_GET_CONTENT);
startActivityForResult(Intent.createChooser(galleryIntent, "SELECT IMAGE"), GALLERY_PICK);
}
});
TextView nameDrawer = findViewById(R.id.navName);
TextView descDrawer = findViewById(R.id.navDescription);
User change = snapshot.getValue(User.class);
assert change != null;
//This is where null error occurs
nameDrawer.setText(change.getUserName());
descDrawer.setText(change.getUserDesc());
//change profile picture
image= Objects.requireNonNull(snapshot.child("userImage").getValue()).toString();
Log.d(TAG, "onComplete: "+image);
if(!image.equals("default")){
Picasso.get().load(image).placeholder(R.drawable.avatar).into(imgvw);
}
}
The solution is to save your user details in shared preferences for the first time when the user sign in , then after the user signs out and sign it again , you get data from shared preferences and set them directly to your edittexts
Try this Code :
///save sharedpreferences
SharedPreferences sharedPreferences =
getSharedPreferences("prefs",Context.MODE_PRIVATE);
SharedPreferences.Editor editor = sharedPreferences.edit();
editor.putString("username","put here your username"); //
editor.putString("email","put your email here"); //you can add more details
editor.apply();
///get sharedpreferences
SharedPreferences sharedPreferences1 =
getSharedPreferences("prefs",Context.MODE_PRIVATE);
String username = sharedPreferences1.getString("username","");
String email = sharedPreferences1.getString("email","");
//then here set the valeus from sharedpreferences to your edittexts
I'm creating an app with where I want already signed up users to be redirected to their profile if their phone number is registered in the app, but if he is a new user then he will be redirected to the welcome page.
The problem is, I'm able to get the verification code for the phone number, but it is always redirecting to the welcome page irrespective of whether it is an existing user or a new user.
By far I've implemented Firebase phone authentication, and
private void verifyCode(String code) {
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential(verificationId, code);
signInWithCredentials(phoneAuthCredential);
}
private void signInWithCredentials(PhoneAuthCredential phoneAuthCredential) {
mAuth.signInWithCredential(phoneAuthCredential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
final String num = getIntent().getStringExtra("phoneNumber");
final Query query = FirebaseDatabase.getInstance().getReference("users").orderByChild("birthday").equalTo(num);
if (task.isSuccessful()) {
if (num.equals(query.toString())) {
Log.i("Method", "Inside if block");
Log.i("value", num + query.toString());
Intent intent = new Intent(VerifyPhoneActivity.this, WelcomeActivity.class);
startActivity(intent);
} else {
Log.i("Method", "Inside if block2");
Log.i("value", num + query.toString());
Intent intent = new Intent(VerifyPhoneActivity.this, ProfileActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
}
} else {
Toast.makeText(VerifyPhoneActivity.this, task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
I'm taking only the phone number of the user to log in/sign up, and there's no separate button for login and sign up. It should work in such a way that, once the OTP sent by the Firebase auth has been verified and if the phone number is already present in the database, it should directly fo the user's profile page instead of the welcome screen, however, if the phone number is new it should go to the welcome page instead of the user profile page.
The challenge I'm facing is I'm not able to check if the number entered is already present in the database in the user table(I've created a separate user table to store the details of the user when he signs up for the first time).
from what I understood you're able to register users but you're not able to redirect unregistered users to the login/signup screen, if that's the case then you can try to use
FirebaseAuth.getInstance().currentUser
in the on create view method in your welcome/home page it should be something like this
override fun onCreate(savedInstanceState: Bundle?) {
if (FirebaseAuth.getInstance().currentUser == null) {
startActivity(Intent(applicationContext, RegistrationActivity::class.java))
finish()
return
}
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
// do your other stuff
}
this code is written in kotlin it shouldn't be that different in java. hope it helps.
UPDATE------
you have a few mistakes with your code, try this
private void verifyCode(String code) {
PhoneAuthCredential phoneAuthCredential = PhoneAuthProvider.getCredential(verificationId, code);
FirebaseAuth.getInstance().signInWithCredential(phoneAuthCredential).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
final String num = getIntent().getStringExtra("phoneNumber");
FirebaseDatabase.getInstance().getReference("users").orderByChild("phoneNumber").equalTo(num).addListenerForSingleValueEvent(new ValueEventListener() {
#Override
public void onDataChange(#NonNull DataSnapshot dataSnapshot) {
if (dataSnapshot.exists()) {
Intent intent = new Intent(VerifyPhoneActivity.this, ProfileActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(intent);
} else {
FirebaseDatabase.getInstance().getReference("users").push().child("phoneNumber").setValue(num).addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid) {
Intent intent = new Intent(VerifyPhoneActivity.this, WelcomeActivity.class);
startActivity(intent);
}
});
}
}
#Override
public void onCancelled(#NonNull DatabaseError databaseError) {
}
});
} else {
Toast.makeText(VerifyPhoneActivity.this, task.getException().getMessage(), Toast.LENGTH_LONG).show();
}
}
});
}
first of all, you have to log in the user with the phone detail then you check if you have any user registered with that phone number if you do then that means that this user has already entered the app but if you didn't have any information of user with that phone number then you create his information and direct him to the welcome screen after creating his information, so if this user comes back again you will check if we have a record of user with that phone number (which we do) so this time he will be directed to the profile screen
This question already has answers here:
How to redirect multiple types of users to their respective Activities?
(3 answers)
Closed 3 years ago.
I have 3 types of user
parents, teacher, admin,
I have already made login activity
and for parent and they will provide email and password and when firebase authenticate it. and when successful it will go to parents activity
And i want to make activity for admin to add and register/signup parents
and they still provide email and pass to my login activity and will be directly to the new admin activity after authenticated by firebase
what changes will do to my login
public class Login extends AppCompatActivity implements View.OnClickListener {
private EditText editTextEmail;
private EditText editTextPassword;
private Button Login;
private ProgressDialog progressDialog;
private FirebaseAuth firebaseAuth;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
FirebaseApp.initializeApp(this);
firebaseAuth = FirebaseAuth.getInstance();
if (firebaseAuth.getCurrentUser() != null) {
// profile activity
finish();
startActivity(new Intent(getApplicationContext(), Parent_Home.class));
}
editTextEmail = findViewById(R.id.input_username);
editTextPassword = findViewById(R.id.input_password);
findViewById(R.id.btn_login).setOnClickListener(this);
progressDialog = new ProgressDialog(this);
}
#Override
public void onClick(View view) {
switch (view.getId()){
case R.id.btn_login: {
userLogin();
break;
}
}
}
private void userLogin() {
String email = editTextEmail.getText().toString().trim();
String password = editTextPassword.getText().toString().trim();
if (email.isEmpty()) {
editTextEmail.setError("Email is required");
editTextEmail.requestFocus();
return;
}
if (!Patterns.EMAIL_ADDRESS.matcher(email).matches()){
editTextEmail.setError("Please enter valid email");
editTextEmail.requestFocus();
return;
}
if (password.isEmpty()) {
editTextPassword.setError("Password is required");
editTextPassword.requestFocus();
return;
}
if (password.length()<6 ){
editTextPassword.setError("Minimum of length of password should be 6");
editTextPassword.requestFocus();
return;
}
//if the email&pass is not empty
//display dialog
progressDialog.setMessage("Please Wait...");
progressDialog.show();
firebaseAuth.signInWithEmailAndPassword(email, password)
.addOnCompleteListener(this, new
OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task) {
progressDialog.dismiss();
if (task.isSuccessful()) {
//start profile/ menu activity
finish();
SharedPrefs.saveSharedSetting(Login.this, "CaptainCode", "false");
startActivity(new Intent(getApplicationContext(), Parent_Home.class));
} else {
Toast.makeText(Login.this, "Error", Toast.LENGTH_SHORT).show();
}
}
});
}
}
//Todo: add back confirmation
In sign up process add additional object in your database for every user, for example you can call it a type. So when someone sign up to your app make him choose which type of account he is creating (or maybe you already have this), so object will contain info what account is created: parent or teacher or admin. For example: type: "teacher"
After login return data from database for user who just logged in and check what is the type of his account and according to type value (parent, teacher, admin) you will know who logged in in your app and you can start corresponding screen.
I'm working on an app that uses Firebase authentication to sign in users through phone number. I want to add a functionality such that there is only one-time login for the user, i.e. even if the user kills the app and starts it again, he should be logged in. Also, I don't want to add a logout feature. What can be done for this?
The simplest way to achieve this is to use a listener. Let's assume you have two activities, the LoginActivity and the MainActivity. The listener that can be created in the LoginActivity should look like this:
FirebaseAuth.AuthStateListener authStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
if (firebaseUser != null) {
Intent intent = new Intent(LoginActivity.this, MainActivity.class);
startActivity(intent);
finish();
}
}
};
This basically means that if the user is logged in, skip the LoginActivity and go to the MainActivity.
Instantiate the FirebaseAuth object:
FirebaseAuth firebaseAuth = FirebaseAuth.getInstance();
And start listening for changes in your onStart() method like this:
#Override
protected void onStart() {
super.onStart();
firebaseAuth.addAuthStateListener(authStateListener);
}
In the MainActivity, you should do the same thing:
FirebaseAuth.AuthStateListener authStateListener = new FirebaseAuth.AuthStateListener() {
#Override
public void onAuthStateChanged(#NonNull FirebaseAuth firebaseAuth) {
FirebaseUser firebaseUser = firebaseAuth.getCurrentUser();
if (firebaseUser == null) {
Intent intent = new Intent(MainActivity.this, LoginActivity.class);
startActivity(intent);
}
}
};
Which basically means that if the user is not logged in, skip the MainActivity and go to the LoginActivity. In this activity you should do the same thing as in the LoginActivity, you should start listening for changes in the onStart().
In both activities, don't forget to remove the listener in the moment in which is not needed anymore. So add the following line of code in your onStop() method:
#Override
protected void onStop() {
super.onStop();
firebaseAuth.removeAuthStateListener(authStateListener);
}
You can save user login session in shared Preference
Do this when your login got Login Success
SharedPreferences pref = getApplicationContext().getSharedPreferences("MyPref", Activity.MODE_PRIVATE);
Editor editor = pref.edit();
editor.putBoolean("key_name", true); // Storing boolean - true/false
editor.commit();
and When Your apps is Starts (like Splash or login Page) use this
SharedPreferences sp=this.getSharedPreferences("MyPref", Context.MODE_PRIVATE);
boolean b = sp.getBoolean("key_name", false);
if(b==true){
//User Already Logged in skip login page and continue to next process
}else{
//User is Not logged in, show login Form
}
It will works for you.
This is from my working code from logging class:
private void LoginUserAccount(String email, String password)
{
if (TextUtils.isEmpty(email))
{
Toast.makeText(ResponseStartPage.this, "Please write Your Email", Toast.LENGTH_SHORT).show();
}
if (TextUtils.isEmpty(password))
{
Toast.makeText(ResponseStartPage.this, "Please write Your password", Toast.LENGTH_SHORT).show();
}
else
{
loadingBar.setTitle("Login Account");
loadingBar.setMessage("Please wait for verification...");
loadingBar.show();
mAuth.signInWithEmailAndPassword(email, password).addOnCompleteListener(new OnCompleteListener<AuthResult>() {
#Override
public void onComplete(#NonNull Task<AuthResult> task)
{
if (task.isSuccessful())
{
String online_user_id = mAuth.getCurrentUser().getUid();
String DeviceToken = FirebaseInstanceId.getInstance().getToken();
usersReference.child(online_user_id).child("device_token").setValue(DeviceToken)
.addOnSuccessListener(new OnSuccessListener<Void>() {
#Override
public void onSuccess(Void aVoid)
{
Intent mainIntent = new Intent(ResponseStartPage.this, ResponseMainActivity.class);
mainIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(mainIntent);
finish();
}
});
}
else
{
Toast.makeText(ResponseStartPage.this, "Please Check your email and password", Toast.LENGTH_SHORT).show();
}
loadingBar.dismiss();
}
});
}
}
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.