When I click on the back button, I want to close the connection in service and go back to previous activity.
Code in second activity:
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if(mBound){
val dialog = ConfirmDialog()
dialog.show(supportFragmentManager, "confirm")
//should wait here until "yes" button is pressed and if so, run the code
mService.closeConnection()
finish()
}
return false
}
return super.onKeyDown(keyCode, event)
}
When the dialog opens the code continues and closes the connection and goes back to previous activity. I want to wait until I click the "yes" button and then continue code below. I know I should have the code inside dialog, but I can't bind the service to the dialog, so I can't stop the connection from there.
Dialog:
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val builder = AlertDialog.Builder(requireActivity())
builder.setView(view)
.setTitle("Confirm")
.setMessage("Do you want to exit?")
.setNegativeButton("no", DialogInterface.OnClickListener(){ _: DialogInterface, _: Int ->
//TODO
})
.setPositiveButton("yes", DialogInterface.OnClickListener(){ _: DialogInterface, _: Int ->
//TODO
})
return builder.create()
}
Again, what I want is simple, when clicking the back button, I can confirm or decline, if I confirm, close the connection in service and go back to previous activity. I guess there is an easier way to do this
I believe your ConfirmDialog() function returns an AlertDialog in which case you can access the components of your alerdialog view this way and close the connection on button click:
dialog.(your_yes_button_id).setOnClickListener {
}
the above code should go below the following:
dialog.show(supportFragmentManager, "confirm")
Related
I'm a total newbie, and my app has a main activity and a test-taking activity. Normally pressing back button in the test activity takes you back to main activity. This is fine, but I want to add a confirmation dialog asking if they really want to abandon the test first. So far I have the following in the test activity:
override fun onBackPressed() {
var exit = ExitTestDialogFragment()
exit.show(supportFragmentManager,"exit")
}
class ExitTestDialogFragment : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
return activity?.let {
val builder = AlertDialog.Builder(it)
builder.setTitle("Leave Test?")
builder.setMessage("Your score will be lost.")
.setPositiveButton("OK",
DialogInterface.OnClickListener { dialog, id ->
// This is where I'd like to return to Main Activity
})
.setNegativeButton("Cancel",
DialogInterface.OnClickListener { dialog, id ->
dialog.dismiss()// User cancelled the dialog
})
// Create the AlertDialog object and return it
builder.setCancelable(false)
builder.create()
} ?: throw IllegalStateException("Activity cannot be null")
}
}
I can't seem to figure out how how do what would normally be the Activity's super.onBackPressed() from the dialog fragment. Like I said, I'm super new to android, so may need a bit of an ELI5 answer.
call finish() or this.finish() inside your DialogInterface.OnClickListener. Method finish() will destroy current activity that call it, in this case its test-taking activity
You should call mainActivity from your dialog positive Button.
.setPositiveButton("OK",
DialogInterface.OnClickListener { dialog, id ->
// here you can get your current activity
//then dismiss your dialog and finish current activity
//call context.finish or activity.finish here. It will
//finish this activity
//and will take you to the previous activity (in your case
//to mainActivity)
})
If you need any further help feel free to mention it in the comments
Add this in the container dialog
dialog?.setOnKeyListener { dialog, keyCode, event ->
if (keyCode == KeyEvent.KEYCODE_BACK && event.action == KeyEvent.ACTION_UP) {
handleBack() // your code
return#setOnKeyListener true
} else
return#setOnKeyListener false
}
I want to start a timer (i think in this case CountDownTimer) as soon as I get a specific wakelock. Once the countdown timer finishes, i want to display an alert dialog. When the wakelock is released, the timer should be killed. When the timer is running and I get a user activity, I want to kill the previous timer and start a new one (or maybe reset this one)
What would be the best way for me to implement this?
Yes you can do it, the only thing you need to do is like this -->
`val dialogListener = DialogInterface.OnClickListener { dialog, which ->
when (which) {
BUTTON_POSITIVE -> {
}
DialogInterface.BUTTON_NEGATIVE -> {
}
}
}
val dialog = AlertDialog.Builder(this)
.setTitle(“YOUR TITLE HERE”)
.setMessage(“YOUR MESSAGE HERE)
.setPositiveButton(“TEXT OF BUTTON”)
.setNegativeButton(“TEXT OF BUTTON”)
.create()
dialog.setOnShowListener(object : OnShowListener {
private val AUTO_DISMISS_MILLIS = 5000 //Timer in this case 5 Seconds
override fun onShow(dialog: DialogInterface) {
//if you want to have stuff done by your buttons it's going go be here with a respective call like (dialog as AlertDialog).getButton(The button you want positive or negative)
then everything you want to happen on it
*************************************************
//here is the timer associated to the button
val defaultButton: Button =
dialog.getButton(AlertDialog.BUTTON_POSITIVE)
val positiveButtonText: CharSequence = defaultButton.text
object : CountDownTimer(AUTO_DISMISS_MILLIS.toLong(), 100) {
override fun onTick(millisUntilFinished: Long) {
defaultButton.text = java.lang.String.format(
Locale.getDefault(), "%s (%d)",
positiveButtonText,
TimeUnit.MILLISECONDS.toSeconds(millisUntilFinished) + 1
)
}
override fun onFinish() {
//everything you wanna do on the moment the timer is off is going to happen here if you wanna open another dialog you need to call it here
}
}.start()
}
})
dialog.show()
}
`
I have an AlertDialog that I want to display at least once to the user and then continuously display the dialog to the user even after the user clicks "ok" until a certain condition is met.
Here's the code structure I have so far for the AlertDialog:
do {
val dialogShow: AlertDialog.Builder = AlertDialog.Builder(this#MainActivity)
dialogShow.setCancelable(false)
dialogShow.setMessage("Message")
.setPositiveButton(
"ok",
object : DialogInterface.OnClickListener {
override fun onClick(dialogInterface: DialogInterface, i: Int) {
if (checkCondition()) {
conditionMet = true
} else {
// Keep looping
}
}
})
.setNegativeButton(
"cancel",
object : DialogInterface.OnClickListener {
override fun onClick(dialogInterface: DialogInterface, i: Int) {
conditionMet = true
return
}
})
dialogShow.show()
} while (conditionMet == false)
The problem now that I am facing is the AlertDialog will display once, but then never again. Even if conditionMet = false it still won't continue to display. How do I keep displaying the same AlertDialog in a loop?
By wrapping the show code in a loop, you're showing it continuously. What you probably want to do it re-show the dialog if it is dismissed. So something like this pseudocode:
fun showObtrusiveDialog() {
...
dialog.setPositiveButton {
if(shouldStillBeObtrusive()) showObtrusiveDialog()
...
}.setNegativeButton {
...
}
dialog.show()
}
An alternate way to handle this would be to disable the buttons until you're ready to allow the dialog to be closed by the user. Here's an extension function you could call when your condition changes:
fun AlertDialog.setAllButtonsState(enabled: Boolean) {
arrayOf(DialogInterface.BUTTON_POSITIVE, DialogInterface.BUTTON_NEGATIVE, DialogInterface.BUTTON_NEUTRAL)
.forEach { getButton(it)?.setEnabled(enabled) }
}
So you can call this to disabled them before you show it, and call it again when your condition changes. You'll need to keep the dialog in a property so you can access it from wherever your condition is being changed.
I'm having a problem with AlertDialog: if I want to finish the current activity after I open a new one, I get crashed with the following error:
E/WindowManager: android.view.WindowLeaked: Activity com.myapp.ShowsActivity has leaked window DecorView#2435213[ShowsActivity] that was originally added here
This happens when I want to log out a user. The AuthLogic.logout() method gets called (I exported it to a standalone class to have a more readable code) which triggers a "are you sure?" alert dialog which then redirects to login activity.
Logout button logic:
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_shows)
// some code . . .
btnLogout.setOnClickListener {
AuthLogic.logout(this)
finish() // *1
}
}
AuthLogic.logout():
fun logout(context: Context) {
val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.are_you_sure)
builder.setMessage(R.string.confirm_msg_logout)
builder.setPositiveButton(R.string.confirm) { dialogInterface: DialogInterface, i: Int ->
// aditional logout logic
context.startActivity(AuthActivity.newStartIntent(context))
}
builder.setNegativeButton(R.string.cancel) { di: DialogInterface, _: Int -> }
builder.show()
}
I noticed that the error pops up if I finish my activity on *1 comment. If I remove that line, no error gets shown, but this causes a problem because I can go back to the previous activity and I don't want that. I already tried using dialogInterface.dismiss() on setPositiveButton lambda method, but no success. Any ideas?
EDIT! solved!:)
I rewrote AuthLogic.logout():
fun logout(context: Context) {
val builder = AlertDialog.Builder(context)
builder.setTitle(R.string.are_you_sure)
builder.setMessage(R.string.confirm_msg_logout)
builder.setPositiveButton(R.string.confirm) { dialogInterface: DialogInterface, i: Int ->
// logout logic ...
dialogInterface.dismiss()
context.startActivity(AuthActivity.newStartIntent(context))
(context as Activity).finish()
}
builder.setNegativeButton(R.string.cancel) { di: DialogInterface, _: Int -> }
builder.show()
}
and removed the finish() line seen on *1.
Thanks to #Johan Kovalski for the tip.
Try to dimiss your alert dialog before finish the activity.
yourAlertDialog.dimiss();
Dialog Window is created with activity Context. Activity has to cleanup windows that it owns. You should destroy dialog first, then activity. Or use DialogFragment.
Log you mentioned in question tells you that activity cannot be properly destroyed (as you requested with finish()) because dialog still holds reference to it.
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
}