I use SharedPreferences to stay logged in, and it works, but when I use it with Firebase the code doesn't work, I don't know if with firebase shared preferences doesn't work for staying logged in, or what I should do, I'm new with android studio and I search in youtube but I can't find how to stay logged in with firebase using Kotlin
Added code sample
For Firebase:
logInButton.setOnClickListener {
if(emailEditText.text.isNotEmpty() && passwordEditText.text.isNotEmpty()){
FirebaseAuth.getInstance()
.signInWithEmailAndPassword(emailEditText.text.toString()
,passwordEditText.text.toString()).addOnCompleteListener {
if(it.isSuccessful){
showHome(it.result?.user?.email?:"",ProviderType.BASIC)
}else{
showAlert()
}
}
}
}
private fun showAlert(){
val builder= AlertDialog.Builder(this)
builder.setTitle("Error")
builder.setMessage("Error")
builder.setPositiveButton("Accept",null)
val dialog:AlertDialog=builder.create()
dialog.show()
}
private fun showHome(email:String,provider:ProviderType){
val homeIntent= Intent(this,Menu::class.java).apply{
putExtra("email",email)
putExtra("provider",provider.name)
}
startActivity(homeIntent)
}
For shared preferences
private lateinit var sharedPreferences: SharedPreferences
var isRemember=false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sharedPreferences = getSharedPreferences("SHARED_PREF", Context.MODE_PRIVATE)
isRemember=sharedPreferences.getBoolean("CHECKBOX",false )
if (isRemember){
val intent= Intent(this,Menu::class.java)
startActivity(intent)
finish()
}
fun checkUserValues(){
}
logInButton.setOnClickListener {
val email: String =emailEditText.text.toString()
val password: String = passwordEditText.text.toString()
val checked:Boolean = check_remember.isChecked
val editor : SharedPreferences.Editor = sharedPreferences.edit()
editor.putString("EMAIL",email)
editor.putString("PASSWORD",password)
editor.putBoolean("CHECKBOX",checked)
editor.apply()
Toast.makeText(this, "Logged in save",Toast.LENGTH_LONG).show()
val intent=Intent(this,Menu::class.java)
startActivity(intent)
finish()
}
}
Much appreciated.
I use shared preferences to stay logged in,
Firebase already stores the user credentials and restores them when the user restarts the app. There is no code you need to write for this, as saving the data happens automatically when the user first signs in, and the information is then restored, when the user starts the app again.
I recommend removing the code where you persist the credentials to shared preferences, and leave that to Firebase.
Related
I am doing a college project where students and teachers are using school data. I want teachers and students to have access to different data. I want teachers to send to home activity while students to main Activity. The user has already entered his type while Signing up. I want users to get specific activity based on user type. I am getting user-type data but not able to use it for other work.
Here is my code:
override fun onStart() {
super.onStart()
var usertype: String? = null
if (FirebaseAuth.getInstance().currentUser != null) {
var currentUser: String = FirebaseAuth.getInstance().currentUser.uid
val DataBaseReference = FirebaseDatabase.getInstance().getReference().child("Users")
DataBaseReference.addValueEventListener(object : ValueEventListener {
override fun onDataChange(datasnapshot: DataSnapshot) {
usertype = datasnapshot.child(currentUser).child("type").getValue(String::class.java)
usertype?.let { Log.d("usertype", it) }
}
override fun onCancelled(error: DatabaseError) {
}
})
val utype = usertype.toString()
Log.i("utype", utype)
if (utype == "Student"){
val intent = Intent(this, MainActivity::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
finish()
}
else {
val intent = Intent(this, home::class.java)
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK)
startActivity(intent)
finish()
}
}
}
The Log result of user-type is a student but utype Log result is null. Now I want to get data of usertype from onDatachange to other function.
I am getting user-type data but not able to use it for other work.
This is happening because you are using the following if statement:
val utype = usertype.toString()
Log.i("utype", utype)
if (utype == "Student"){ ...}
Outside the callback. Firebase API is asynchronous. Any code that needs data from an asynchronous operation needs to be inside the "onDataChange()" method, or be called from there. So the simplest solution, in this case, is to move all the logic related to the above lines of code, in the "onDataChange()" method, inside the scope of let:
usertype = datasnapshot.child(currentUser).child("type").getValue(String::class.java)
usertype?.let {
Log.d("usertype", it)
//Use your logic
}
}
I'm still new to Kotlin and Android and developing a project that uses shared preferences.
I have multiple Activities and a user must be logged in to use all functions of the Main Activity.
The Main Acitivity has a menu drawer with few menu items. The first one is redirecting user to Login Activity. The rest of the menu items are hidden until user is logged in.
The process is as follows:
Start with Main Activity -> The application checks if the user is logged in -> If not you must log in -> Go to Login Activity -> Logging in -> Then go back to Main Activity.
However, the main activity does not refresh at all. I mean, I don't even know how to do it. I want my main activity to refresh when I return from login activity.
So far, it only works when I close the app and reopen it. The session is likely cached in Shared preferences.
I tried to start and finish Activites by clicking certain buttons (eg After clicking login button when user passed all credentials) but it didn't work.
The following code checks that the user is logged in when the main activity starts
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val menu: Menu = navView.menu
val target2: MenuItem = menu.findItem(R.id.miItem2)
val target3: MenuItem = menu.findItem(R.id.miItem3)
//region user session
try{
if(!SharedPrefManager.getInstance(this)!!.isLoggedIn()){
target2.isVisible = false
target3.isVisible = false
Toast.makeText(applicationContext, "nie zalogowany", Toast.LENGTH_LONG).show()
}
else{
target2.isVisible = true
target3.isVisible = true
Toast.makeText(applicationContext, "zalogowany", Toast.LENGTH_LONG).show()
}
}catch (e: NullPointerException){
}
//endregion
And there is function isLoggedIn():
fun isLoggedIn(): Boolean{
val sharedPreferences: SharedPreferences = mCtx.getSharedPreferences(SHARED_PREF_NAME, Context.MODE_PRIVATE)
if(sharedPreferences.getString(KEY_USER_EMAIL, null) != null){
return true
}
return false
}
This code below takes me to the Login Activity
val btnLogInActivity : Button = findViewById(R.id.logButton)
btnLogInActivity.setOnClickListener {
val intent = Intent(this, LoginActivity::class.java)
startActivity(intent)
}
And this is the code in Login Activity (userLogin function is not important in this context):
buttonLogin.setOnClickListener {
userLogin()
newMainActivity()
}
private fun newMainActivity(){
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
}
Ps. If you need more code to fix the problem, let me know
You just have to add finish() in your code. Update your methods with the code below:
btnLogInActivity.setOnClickListener {
val intent = Intent(this, LoginActivity::class.java)
startActivity(intent)
finish()
}
And after login:
private fun newMainActivity(){
val intent = Intent(this, MainActivity::class.java)
startActivity(intent)
finish()
}
For my app's structure, I think it would be very clean if I had one Kotlin file, DBQuery(), for anything related to Firebase/Firestore and then initialize this object on every activity (if this is a horrible idea, let me know). So on each activity I need to make sure that the user is still logged in (and later make sure that the user isn't banned, etc). The docs recommend to use the code below to check the current login state.
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
I can't figure out how to modify this code to fit in my DBQuery class.
class DBQuery {
private val firebaseAuth: FirebaseAuth = FirebaseAuth.getInstance()
private val firebaseFirestore: FirebaseFirestore = FirebaseFirestore.getInstance()
private val collUsers: String = "users"
private val collRelationships: String = "relationships"
private val tag: String = "DBQuery"
fun checkLoginState() {
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
// User is signed in.
} else {
// No user is signed in.
}
});
}
}
Hey Guys Im trying to push the user data in kotlin to firebase but when i click the create account button nothing happends here is the code for Create account class
class CreateAccount : AppCompatActivity() {
var mAuth:FirebaseAuth?=null
var mdata:DatabaseReference?=null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_create_account)
mAuth= FirebaseAuth.getInstance()
Createacc.setOnClickListener{
var email=acemail.text.toString().trim()
var pass=acpass.text.toString().trim()
var name=acname.text.toString().trim()
if(!TextUtils.isEmpty(email)||!TextUtils.isEmpty(name)||!TextUtils.isEmpty(pass)){
createAccount(email,pass,name)
}
else{
Toast.makeText(this,"Please fill all the details",Toast.LENGTH_LONG).show()
}
}
}
fun createAccount(email: String,password:String,dispname:String){
mAuth!!.createUserWithEmailAndPassword(email,password).addOnCompleteListener(this,{
task: Task<AuthResult> ->
if(task.isSuccessful){
var curruser=mAuth!!.currentUser
var userid=curruser!!.uid
Toast.makeText(this,"Building user wait",Toast.LENGTH_LONG).show()
var uobject=HashMap<String,String>()
uobject.put("Display_name",dispname)
uobject.put("Status","Hi I'm New")
uobject.put("image","default")
uobject.put("thumb image","default")
mdata=FirebaseDatabase.getInstance().reference.child("Users").child(userid)
mdata!!.setValue(uobject).addOnCompleteListener{
task:Task<Void> ->
if(task.isSuccessful){
Toast.makeText(this,"User Created",Toast.LENGTH_LONG).show()
}
else{
Toast.makeText(this,"OOPS!! User not Created",Toast.LENGTH_LONG).show()
}
}
}
})
}
}
Main problem is in create account function ,it is being called correctly but right after the createUserWithEmailAndPassword function the task is not successfull hence the if loop does not run. There nothing is printed in the toast Neither "User created " nor "OOPS not created" i dont know whats going on.
I have installed the firebase dependency and my app is connected to a firebase database.
So I setup email/password register and login.
That is working. I thought Firebase took care of this but apparently not.
I want, after the user closes the app, to be logged in already next time they open the app.
What is missing?
class LoginActivity : AppCompatActivity(){
lateinit var auth: FirebaseAuth
lateinit var user: FirebaseAuth
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
auth = FirebaseAuth.getInstance()
}
fun loginLoginClicked(view: View) {
// Perform login
val email = loginEmailTxt.text.toString()
val password = loginPasswordTxt.text.toString()
auth.signInWithEmailAndPassword(email, password)
.addOnSuccessListener {
finish()
}
.addOnFailureListener { exception ->
Log.e("Exception", "Could not sign in user - ${exception.localizedMessage}")
}
val loginIntent = Intent(this, MainActivity::class.java)
startActivity(loginIntent)
}
fun loginCreateClicked(view: View) {
// segue to the create user activity
val createIntent = Intent(this, SignUpActivity::class.java)
startActivity(createIntent)
}}
}
Firebase Authentication does automatically remember authentication state, so the user will still be authenticated when the app is restarted.
However, if your LoginActivity is the launcher activity, you'll still land on this activity, so you'll need to check whether the user is authenticated in onCreate(), and then redirect them to your MainActivity if they are already logged in, something like:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_login);
auth = FirebaseAuth.getInstance();
if (auth.getCurrentUser() != null) {
// User is signed in (getCurrentUser() will be null if not signed in)
val intent = Intent(this, MainActivity::class.java);
startActivity(intent);
finish();
}
}
This makes use of the FirebaseAuth#getCurrentUser() method that will return a FirebaseUser object if the user is logged in, or null if they are not logged in.
Alternatively, you could swap it around so that the MainActivity is the launcher activity and then only show your LoginActivity if the user is not logged in.
....
If anyone landing up here for achieving same thing using Java then use following code (credit to Grimthorr's answer for the Kotlin version that this is a port of)
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
auth = FirebaseAuth.getInstance();
if (auth.getCurrentUser() != null) {
// User is signed in (getCurrentUser() will be null if not signed in)
Intent intent = Intent(this, MainActivity.class);
startActivity(intent);
finish();
// or do some other stuff that you want to do
}