I am using shared preferences to login and logout the user of the application. Once the user logs in, the login screen is not showed again after the application is killed and started again. But when I enter the application and go to the screen after the login page and press back button, it shows the login screen again. I don't want the login screen to be showed again even after the back button is pressed. I want it to go completely out of the aplication on pressing back button.
Here is my code for login :
val sp = getSharedPreferences("login",MODE_PRIVATE)
if (sp.getBoolean("logged", false))
{
login()
}
loginButton.setOnClickListener() {
login()
sp.edit().putBoolean("logged", true).apply()
Log.v("Login Msg", "Login button clicked")
getusername = findViewById(R.id.usernameEditText)
var username = usernameEditText.text
Log.v("username",username.toString())
getpass = findViewById(R.id.passEditText)
var pass = passEditText.text
Log.v("pass",pass.toString()) }
fun login() {
val i = Intent(this, HomeActivity::class.java)
startActivity(i)
}
Here is the code for logout:
logoutButton.setOnClickListener(){
logout()
val sp = getSharedPreferences("login",MODE_PRIVATE)
sp.edit().putBoolean("logged", false).apply()
Log.v("Logout msg", "Logout button clicked")
}
fun logout(){
val i = Intent(this, LogInActivity::class.java)
startActivity(i)
}
Actually we can override "Back Button" method in each activity.
Below I reuse your code to manage logout when back button is pressed, perhaps this is the one you are looking for
override fun onBackPressed() {
super.onBackPressed()
val sp = getSharedPreferences("login",MODE_PRIVATE)
sp.edit().putBoolean("logged", false).apply()
logout()
}
This is happening because the login activity is still there in the back stack after going to the HomeActivity. To achieve your requirement you must remove everything from the back stack before going to the HomeActivity.
Replace your login function with the below function.
fun login() {
val i = Intent(this, MainActivity::class.java)
i.run {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK)
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
}
startActivity(i)
}
Here we are basically adding a set of flags to the intent.
Intent.FLAG_ACTIVITY_CLEAR_TOP clears all the view underneath the current view
Intent.FLAG_ACTIVITY_CLEAR_TASK we are removing the existing tasks
Intent.FLAG_ACTIVITY_NEW_TASK we are creating a new task for the HomeActivity.
Intent.FLAG_ACTIVITY_CLEAR_TASK and Intent.FLAG_ACTIVITY_NEW_TASK should be used in conjunction with each other.
Related
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()
}
This question already has answers here:
Android: open activity without save into the stack
(11 answers)
Closed 2 years ago.
I have 3 activities, A: LoginAcitivty, B: SignupActivity, C: HomeActivity
and the flow is A -> B -> C.
and if I signup in the SignupActivity, then I go to HomeActivity.
but there is a problem. when I click the back button on my device. I can see the LoginActivity again.
So i thought first, when i click the sign-up button, i go back to LoginActivity
and then in the LoginActivity, i go to HomeActivity by using Intent for the HomeActivity. and also i wrote finish() in the LoginActivity.
this is my code.
<SignupActivity>
val intent = Intent(this, LoginActivity::class.java)
intent.putExtra("transfer", "transfer")
startActivity(intent)
finish()
<LoginActivity>
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_login)
if (intent.hasExtra("transfer")) {
val intent = Intent(this, HomeActivity::class.java)
startActivity(intent)
finish()
}
}
but it also doesn't work.
when i click the back button on my device in the HomeActivity, i expected that the app will end.
but i can still see the LoginActivity and i push back button again, then it's end.
plz help me.
This is the default behavior of Android activities as your default launch mode of each of the activities is standard.
We can fix it in two ways. I will explain one way which is not bothering about the launch mode thing.
LoginActivity -> You should start the SignupActivity as
activity.startActivityForResult(Intent(activity,SignupActivity::class.java), YOUR_REQUEST_CODE)
override fun onActivityResult(requestCode: Int, resultCode: Int,
data: Intent?) {
if (requestCode == YOUR_REQUEST_CODE && resultCode ==
RESULT_OK && data != null) {
// move to Home activity and `finish()` the current
//login screen
}
}
LoginActivity -> You should start the HomeActivity if login success and finish() the login screen.
When switching to the MainActivity from OnboardingSetupActivity i can pressed back and go back in OnboardingSetupActivity.
override fun showMainActivity() {
startActivity(Intent(this, MainActivity::class.java)
.apply { putExtra(KEY_SKIP_PIN, true) }
.apply { flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK })
}
Q: Why? How to disable the ability go back to OnboardingSetupActivity?
This will clear back task of application and when you press back button application will close. You need to add flags in Intent or you can use finish().
val intent = Intent(this, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
Why?
it's because by default when you click back button your activity calls super.onBackPressed() method.
How to disable?
override onBackPressed() and remove super.onBackPressed() from it
#Override
public void onBackPressed() {
super.onBackPressed(); // remove or comment this line
}
I've seen this question posed all over the place but I have not seen where anyone has been able to answer why the function doesn't get called.
I've run the app in debug mode with a break point set at the onBackPressed function and it completely ignores it. The compiler even recognizes and changes my red break point into a circle with a line through it.
I have a ContractSelectAdapter with a setOnClickListener passing a selected contract to ContractMenuActivity using putExtra(). Once in the ContractMenuActivity there is a button to open the activity below, UploadImageActivity and while in the activity I want a user to be able to hit the back button to reopen the ContractMenuActivity but within the onCreate function of ContractMenuActivity is a getStringExtra call that causing it to crash because there is no "extra". Which is why I'm trying to use the onBackPressed. In theory it should work perfectly.
I've tried putting a call to the onBackPressed function manually in the onCreate function of UploadImageActivity just to make sure it works and it does. It immediately opens ContractMenuActivity. So the function works it just never gets called for some reason. Extremely frustrating.
the onBackPressed function is at the very end of the UploadImageActivity class (first code excerpt)
Any help would be GREATLY appreciated.
class UploadImageActivity : AppCompatActivity() {
var prefs: Prefs? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_upload_image)
prefs = Prefs(this)
}
override fun onBackPressed()
{
super.onBackPressed()
val returnIntent = Intent(this, ContractMenuActivity::class.java)
returnIntent.putExtra(SELECTED_CONTRACT, prefs!!.rmsAppContractID)
startActivity(returnIntent)
}
}
class ContractMenuActivity : AppCompatActivity()
{
var selectedContract: String = ""
var prefs: Prefs? = null
override fun onCreate(savedInstanceState: Bundle?)
{
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_contract_menu)
prefs = Prefs(this)
val btnUploadImage = findViewById<Button>(R.id.btnUploadImage)
selectedContract = intent.getStringExtra(SELECTED_CONTRACT)
prefs!!.rmsAppContractID = this.selectedContract
var contractSelectMsg = "Contract ${prefs!!.rmsAppContractID} selected"
val duration = Toast.LENGTH_SHORT
Toast.makeText(this, contractSelectMsg, duration).show()
btnUploadImage.setOnClickListener {this.openUploadImage()}
}
public fun openUploadImage()
{
val registered = prefs!!.rmsAppRegistered
var message: String
if(registered)
{
val intent = Intent(this, UploadImageActivity::class.java)
startActivity(intent);
}
else
{
message = "You must Pair this device before you can upload an image."
val intent = Intent(this, PostResponseMessageActivity::class.java).apply {
putExtra(POST_RESPONSE_MESSAGE, message)
}
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
}
}
Parent name in manifest:
<activity
android:name=".ContractMenuActivity"
android:label="#string/contractMenuLabel"
android:parentActivityName=".ContractSelectActivity">
</activity>
<activity
android:name=".UploadImageActivity"
android:label="#string/uploadImageLabel"
android:parentActivityName=".ContractMenuActivity">
</activity>
super.onBackPressed()
Will finish the current activity. If you want to do some action after user press back button, You must to past your code to top of super.onBackPressed().
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
}