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
}
Related
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.
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()
}
I have HomeScreen and LoginScr activity and I would like to move from HomeScreen to LoginScr activity. I do it in such way:
val thread = Thread(Runnable {
try {
val client = APICallRequests.client
client.dispatcher.executorService.shutdown()
client.connectionPool.evictAll()
} catch (e: java.lang.Exception) {
e.printStackTrace()
}
})
thread.start()
val intent = Intent(this, LoginScr::class.java)
startActivity(intent)
finishAfterTransition()
As you can see I try to close okHttp3 client, because maybe it keeps HomeScr activity alive. Also I use finishAfterTransition(). Then when I move from LoginScr to HomeScr I do it in such way:
private fun moveToNextScreen(){
val goToMain = Intent(this, HomeScreen::class.java)
startActivity(goToMain
.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
)
finishAfterTransition()
overridePendingTransition(0, 0)
}
As I see I create two activity instances instead one. How I did it - added log to onCreate() fun. I totally don't understand why does it happen. Similar problem can be met after onBackPressed():
override fun onBackPressed() {
val startMain = Intent(Intent.ACTION_MAIN)
startMain.addCategory(Intent.CATEGORY_HOME)
startMain.flags = Intent.FLAG_ACTIVITY_NO_ANIMATION
startActivity(startMain)
finish()
super.onBackPressed()
}
I tried a lot of variants but my HomeScreen can stay alone. I also tried such ways at manifest:
android:launchMode="singleTask"
android:noHistory="true"
Maybe someone know how to solve this problem?
I think this answer can help you
https://stackoverflow.com/a/10862977/13221053
Further, if you want to keep your app active in background then you can use services for that purpose, here is the documentation
https://developer.android.com/guide/components/services
I'd like to show a custom dialog when a user clicks back button in Kotlin.
I tried this code but it doesn't work, when I click the back button the custom dialog shows and then disappears
override fun onBackPressed() {
super.onBackPressed()
onPause()
creatAlertDialog()
}
fun creatAlertDialog() {
var dialogs = Dialog(this#MainActivity)
dialogs.requestWindowFeature(Window.FEATURE_NO_TITLE)
dialogs.setCancelable(false)
dialogs.setContentView(R.layout.back_press)
dialogs.btn_yes.setOnClickListener {
finish()
}
dialogs.btn_no.setOnClickListener {
dialogs.dismiss()
}
dialogs.show()
}
Delete super.onBackPressed() from your onBackPressed() callback. This way you'll avoid your super class to call its onBackPressed() method and your activity will not be destroyed.
override fun onBackPressed() {
creatAlertDialog()
// whatever you want here
}
I have a particular case where I need to ask something to the user when he starts a printer service.
So from the onStartPrinterDiscovery (so a service), I start an activity to display the dialog and when the action is done, I send a new intent which calls finish() nd so I see that onDestoy() is called.
Unfortunately when I hit the apps history button, I still see my activity's screen behind:
Could you tell me why and how to fix it please?
androidManifest.xml:
<activity
android:name=".DialogActivity"
android:noHistory="true"
android:theme="#android:style/Theme.Dialog"
android:launchMode="singleTop">
</activity>
DialogActivity:
class DialogActivity : Activity() {
var activity:Activity = this
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.floatingactivity)
setFinishOnTouchOutside(false)
onNewIntent(intent)
}
override fun onDestroy() {
super.onDestroy()
isDisplayed = false
}
override fun onNewIntent(intent: Intent) {
val extras = intent.extras
val action = extras.getString("action")
when (action) {
"showDialog" -> {
if (!isDisplayed) {
tvMessage.text = getString(R.string.ask_for_action)
isDisplayed = true
}
}
"showErrorDialog" -> {
if (!isDisplayed) {
tvMessage.text = getString(R.string.error_action)
isDisplayed = true
}
}
"dismissDialog" -> { activity.finish() }
else -> {}
}
if (isDisplayed) {
btCancel.setOnClickListener {
activity.finish()
}
}
}
companion object {
var isDisplayed = false
}
}
EDIT I add how I currently create my Intent because of one answer which could be a solution:
val intent = Intent(applicationContext, DialogActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
intent.putExtra("action","showDialog")
startActivity(intent)
Add the android:excludeFromRecents to your activity attributes, like so:
<activity
android:name=".DialogActivity"
android:theme="#android:style/Theme.Dialog"
android:excludeFromRecents="true"
android:launchMode="singleTop">
</activity>
This is from the docs of the android:excludeFromRecents:
Whether or not the task initiated by this activity should be excluded from the list of recently used applications, the overview screen. That is, when this activity is the root activity of a new task, this attribute determines whether the task should not appear in the list of recent apps. Set "true" if the task should be excluded from the list; set "false" if it should be included. The default value is "false".
The android:noHistory="true" is for different purposes. This is from the docs of the android:noHistory:
A value of "true" means that the activity will not leave a historical trace. It will not remain in the activity stack for the task, so the user will not be able to return to it. In this case, onActivityResult() is never called if you start another activity for a result from this activity.
Try this:-
Intent i = new Intent(this,YourFirstActivity.Class);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
i.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity(i);
finish();
Or
use finishAffinity() suitable for >= API 16.