Android: Prompt user to save changes when Back button is pressed - java

I have an activity that contains several user editable items (an EditText field, RatingBar, etc). I'd like to prompt the user if the back/home button is pressed and changes have been made that have not yet been saved. After reading through the android documentation, it seems like this piece of code should go in the onPause method. I've tried putting an AlertDialog in the onPause however the dialog gets shown and then immediately tears down because nothing is there to block the pause from completing.
This is what I've come up with so far:
#Override
protected void onPause() {
super.onPause();
AlertDialog ad = new AlertDialog.Builder(this).setMessage(
R.string.rating_exit_message).setTitle(
R.string.rating_exit_title).setCancelable(false)
.setPositiveButton(android.R.string.ok,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// User selects OK, save changes to db
}
}).setNeutralButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog,
int whichButton) {
// User selects Cancel, discard all changes
}
}).show();
}
Am I on the right track or is there another way to accomplish what I'm trying to do here? Any help would be great!

You're not quite on the right track; what you should be doing is overriding onKeyDown() and listening for the back key, then overriding the default behavior:
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
// do something on back.
return true;
}
return super.onKeyDown(keyCode, event);
}
If you're only supporting Android 2.0 and higher, they've added an onBackPressed() you can use instead:
#Override
public void onBackPressed() {
// do something on back.
return;
}
This answer is essentially ripped from this blog post. Read it if you need long presses, compatibility support, support for virtual hard keys, or raw solutions like onPreIme() etc.

What do you think about this approach ..
private void exit(){
this.finish();
}
#Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK && event.getRepeatCount() == 0) {
AlertDialog.Builder alertbox = new AlertDialog.Builder(this);
alertbox.setTitle("Message");
alertbox.setMessage("Quit ??? ");
alertbox.setPositiveButton("Yes",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
exit();
}
});
alertbox.setNeutralButton("No",
new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
}
});
alertbox.show();
return true;
} else {
return super.onKeyDown(keyCode, event);
}
}

Here is some sample code:
#Override
public void onBackPressed() {
if (isDirty) {
new AlertDialog.Builder(this)
.setTitle("You have made some changes.")
.setMessage("Would you like to save before exiting?")
//.setNegativeButton(android.R.string.no, null)
.setNegativeButton("No", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
MyActivity.super.onBackPressed();
}
})
.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface arg0, int arg1) {
if (Save())
MyActivity.super.onBackPressed();
}
}).create().show();
}
else {
MyActivity.super.onBackPressed();
}
}

I am doing the same thing that you do. I have one activity with a customer information (EditText for name, last name, email, ..., you know, EditText everywhere) and I used AsyncTask for that, and it works wonderfully.
#Override
public void onBackPressed()
{
// start async task for save changes.
new GuardandoContactoHilo().execute()
}
public void VolverAtras()
{
super.onBackPressed();
}
public class GuardandoContactoHilo extends AsyncTask< Void, Void, Void>
{
private ProgressDialog saving;
#Override
protected void onPreExecute()
{
super.onPreExecute();
saving = new ProgressDialog(cont);
saving.setProgressStyle(ProgressDialog.STYLE_SPINNER);
saving.setMessage("Saving customer ...");
saving.show();
}
#Override
protected void onPostExecute(Void result)
{
super.onPostExecute(result);
saving.dismiss();
VolverAtras(); // go back !!
}
#Override
synchronized protected Void doInBackground(Void... arg0)
{
// do what you want to do before come back ! for example, save data ;)
return null;
}
}

Related

Alert Dialog Button Pressed returning 0 values always

So, I want to detect button pressed by the user when an alert dialog pops up. This is my code.
public class AlertUtils {
private int BTN_PRESSED;
private AlertDialog.Builder builder;
public AlertUtils(Context context){
builder = new AlertDialog.Builder(context);
}
public int ShowAlertWithTwoButtons(String Title,String Message,String PositiveButtonText,
String NegativeButtonText){
builder.setTitle(Title);
builder.setMessage(Message);
builder.setPositiveButton(PositiveButtonText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
BTN_PRESSED = i;
}
});
builder.setNegativeButton(NegativeButtonText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
BTN_PRESSED = i;
dialogInterface.dismiss();
}
});
builder.show();
return BTN_PRESSED;
}
}
By calling ShowAlertWithTwoButtons method, returns int value detecting Positive or Negative Button pressed. My Problem is it's giving me default 0 value when I chose from an alert dialog and when I again open us alert dialog it returns the correct value.
Try in this way. Make AlertUtils class like this.
public class AlertUtils {
private AlertDialog.Builder builder;
private AlertDialogListener alertDialogListener;
// Interface to send back the response of click
interface AlertDialogListener {
void onClick(int a);
}
public AlertUtils(Context context, AlertDialogListener alertDialogListener) {
builder = new AlertDialog.Builder(context);
this.alertDialogListener = alertDialogListener;
}
public void ShowAlertWithTwoButtons(String Title, String Message, String PositiveButtonText,
String NegativeButtonText) {
builder.setTitle(Title);
builder.setMessage(Message);
builder.setPositiveButton(PositiveButtonText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// if you want to pass the actual value of i,then pass the i in onClick or if you want 1 on
// positive button click then pass 1 here.
alertDialogListener.onClick(1);
}
});
builder.setNegativeButton(NegativeButtonText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
// if you want to pass the actual value of i, then pass the i in onClick or if you want 1 on
// negative button click then pass 0 here.
alertDialogListener.onClick(0);
dialogInterface.dismiss();
}
});
builder.show();
}
}
Call the dialog in this way where you need this.
AlertUtils alertUtils = new AlertUtils(getContext(), new AlertUtils.AlertDialogListener() {
#Override
public void onClick(int a) {
if (a == 1) {
// Do your work on Positive button click
} else {
// Do your work on Negative button click
}
}
});
alertUtils.ShowAlertWithTwoButtons("Alert Dialog", "Alert Dialog Description ", "Positive", "Negative");
You'll always get BTN_PRESSED with 0 value whenever you're instantiating your AlertUtils object and the calling the ShowAlertWithTwoButtons method. But you'll get another value if you're recalling the ShowAlertWithTwoButtons again.
I think what you're currently doing is like the following:
// First, you're instantiating the object
AlertUtils alertUtils = new AlertUtils(getContext());
// then you're calling the method
int pressedButton = alertUtils.ShowAlertWithTwoButtons("title", "message", "yes", "no");
// which will return pressedButton as 0
// then you calling the method again after clicked yes or no
int anotherPressedButton = alertUtils.ShowAlertWithTwoButtons("title", "message", "yes", "no");
// which will not zero. But can be -1, -2, -3 like in the
// https://developer.android.com/reference/android/content/DialogInterface.html
Which is incorrect if want to get the button value directly after the click because of asynchronous nature of AlertDialog interface.
Instead, you need to add a listener (ohh no, another listener) to your AlertUtils.
UPDATE
You need to add another listener for click button, something like this:
public class AlertUtils {
public interface Listener {
void onButtonClicked(int pressedButton);
}
private Listener mListener;
private AlertDialog.Builder builder;
public AlertUtils(Context context, Listener listener){
builder = new AlertDialog.Builder(context);
mListener = listener;
}
public void ShowAlertWithTwoButtons(String Title,String Message,String PositiveButtonText,
String NegativeButtonText){
...
builder.setPositiveButton(PositiveButtonText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
mListener.onButtonClicked(i);
}
});
builder.setNegativeButton(NegativeButtonText, new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialogInterface, int i) {
mListener.onButtonClicked(i);
dialogInterface.dismiss();
}
});
builder.show();
}
}
then you can create and call the method with:
// create the listener to listen for the clicked button.
AlertUtils.Listener listener = new AlertUtils.Listener() {
#Override
public void onButtonClicked(int pressedButton) {
// here you'll receive the button value
// do something here.
}
};
AlertUtils alertUtils = new AlertUtils(getContext(), listener);
// then you're calling the method
alertUtils.ShowAlertWithTwoButtons("title", "message", "yes", "no");

How to check Alert Dialog visibility?

I want to check alert dialog is visible or not. In most post I saw that they used isShowing, but seems like its not describable now.
When user click info textview, I pause music. If user close alert dialog, music will be play again.
info_Button.setClickable(true);
info_Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mediaControl.pause();
AlertDialog.Builder playstopbutton_builder = new AlertDialog.Builder(exercise_arm_triceps_execute.this);
playstopbutton_builder.setTitle("WARNING").setMessage("Please get warm before exercising!");
playstopbutton_builder.create().show();
playstopbutton_builder.setCancelable(false);
//if alert dialog is visible keep music paused
//else if mediaControl.start();
}
});
since you have made Cancelable false, you might need to use
for positive button say like a okay
playstopbutton_builder.setPositiveButton(positiveBtnText,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
//resume ur media player here
}
})
for negative button say like a cancel
playstopbutton_builder.setNegativeButton(negativeBtnText,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
//resume ur media player here
}
})
so it would look like this
info_Button.setClickable(true);
info_Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mediaControl.pause();
AlertDialog.Builder playstopbutton_builder = new AlertDialog.Builder(exercise_arm_triceps_execute.this);
playstopbutton_builder.setTitle("WARNING").setMessage("Please get warm before exercising!");
playstopbutton_builder.create().show();
playstopbutton_builder.setCancelable(false);
playstopbutton_builder.setPositiveButton(positiveBtnText,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
//resume ur media player here
}
});
playstopbutton_builder.setNegativeButton(negativeBtnText,
new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
//resume ur media player here
}
});
}
});
You need to check dialog show or not change you code like this.
info_Button.setClickable(true);
info_Button.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View view) {
mediaControl.pause();
AlertDialog.Builder playstopbutton_builder = new AlertDialog.Builder(exercise_arm_triceps_execute.this);
playstopbutton_builder.setTitle("WARNING").setMessage("Please get warm before exercising!");
playstopbutton_builder.create();
playstopbutton_builder.setCancelable(false);
//if alert dialog is visible keep music paused
//else if mediaControl.start();
if(!playstopbutton_builder.isShowing()){
//if its visibility is not showing then show here
playstopbutton_builder.show();
}else{
//do something here... if already showing
}
}
});
You may want to add an OnDismissListener to the playstopbutton_builder:
playstopbutton_builder.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
mediaControl.start();
}
});
This way, when the user dismisses the Alert Dialog, the music will start to play again.
EDIT: if the OnDismissListener approach is not desired, maybe something like this would be better:
public void infoClickHandler(View v) {
mediaControl.pause();
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setMessage("restart the music?");
b.setPositiveButton("ok", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
mediaControl.start();
}
});
b.show();
}
EDIT 2: On the other hand, if the dialog cannot have positive or negative buttons, and you do not want to set cancellable to false, this seems to work:
public void infoClickHandler(View v) {
mediaControl.pause();
AlertDialog.Builder b = new AlertDialog.Builder(this);
b.setMessage("restart the music?");
b.setOnDismissListener(new DialogInterface.OnDismissListener() {
#Override
public void onDismiss(DialogInterface dialog) {
if (!mediaControl.isPlaying()) {
mediaControl.start();
}
}
});
b.show();
}
The OnDismissListener will be called when the user clicks outside of the dialog box.

java android return method within listener?

I am kind of new in Java Android, and Im facing this problem and i don't know what it's called, here is my code:
public boolean msgBox(String title, String text) {
boolean bReturn = false;
AlertDialog.Builder adb = new AlertDialog.Builder(this);
adb.setCancelable(false);
adb.setTitle(title);
adb.setMessage(text);
adb.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
//this suppose tell msgBox return true
}
});
adb.setNegativeButton("Yes", new DialogInterface.OnClickListener() {
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
//this suppose tell msgBox return false
}
});
adb.show();
return bReturn;
}
Now how do I tell msgBox to return true / false when user clicked positive / negative button? thanks before
This is not possible, because the method will end after the Dialog is opened. The Dialog will continue to be open after the method is finished.
In order to return information back to your msgBox caller, you will need to provide a callback function.
You can create an interface, pass that into msgBox, and call it in your Dialog button.
public interface OnDialogButtonClickedCallback {
public void onDialogButtonClicked(boolean wasPositive);
}
Pass it in like this:
public boolean msgBox(String title, String text, final OnDialogButtonClickedCallback callback)
Use it in the button like this:
#Override
public void onClick(DialogInterface dialog, int which) {
if(callback != null) {
callback.onDialogButtonClicked(true);
}
}
#Override
public void onClick(DialogInterface dialog, int which) {
if(which == 1) {
bReturn = true or false;//yes or no
}
//this suppose tell msgBox return false
}
In the function above you determine which button was clicked by variable int which (f.e.: Yes is first, No is second).
bReturn should be global.
Since you are doing separate listeners for each button, you don't even have to distinguish, since those are separate listeners.

back button alert box(Android Studio)

In my first class, I have this piece of code:
public void onBackPressed() {
new AlertDialog.Builder(this)
.setIcon(R.drawable.ic_launcher)
.setTitle(R.string.ALERTA1)
.setMessage(R.string.ALERTA2)
.setPositiveButton(R.string.ALERTA3, new DialogInterface.OnClickListener()
{
public void onClick(DialogInterface dialog, int which) {
finish();
}
})
.setNegativeButton(R.string.ALERTA4, null)
.show();
}
This will make an alert box when the back button is pressed, but this works in every class, I only want it to work in this one.
UPDATE:
public void onBackPressed() {
finish();
}
In every class.
Put this in your other classes:
public void onBackPressed() {
super.onBackPressed();
return;
}
That might work.

Start and stop recording with button click

I'm making a simple android app for recording sound. I have a startRecording() and stopRecording() methods. Now I implemented a ToggleButton named "Touch to record" so as you can already imagine, when the button is checked, you have to hold the record button to record sound and when the button is on "off" you have to click to start and then click to stop.
This is the current code:
touchToRecord.setOnCheckedChangeListener(new OnCheckedChangeListener(){
#Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked)
{
recBtn.setOnTouchListener(new OnTouchListener(){
#Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN)
{
recBtn.setImageResource(com.whizzappseasyvoicenotepad.R.drawable.record_btn_pressed);
chTimer.start();
chTimer.setTextColor(Color.GREEN);
startRecording();
}
else if (event.getAction() == MotionEvent.ACTION_UP)
{
recBtn.setImageResource(com.whizzappseasyvoicenotepad.R.drawable.record_btn);
chTimer.stop();
stopRecording();
nameAlert();
}
return true;
}
});
}
else
{
//onClickListener
}
}
});
Now I'm not sure how to make the onClickListener. If I try to do it like this:
recBtn.setOnClickListener(new OnClickListener(){
#Override
public void onClick(DialogInterface dialog, int which) {
// TODO Auto-generated method stub
}
});
It won't work because it underlines setOnClickListener and says:
The method setOnClickListener (View.OnClickListener) in the type View is not applicable for the arguments (new DialogInterface.OnClickListener(){})
Also, one more thing after I get this working; how do I check if the method is already running with if statement? I want to do something like this:
if (startRecording == isRunning)
{
stopRecording();
}
You could try android toggle button. Please see more information on:
http://developer.android.com/guide/topics/ui/controls/togglebutton.html
Solved the problem!
I avoided using onClickListener by setting onClick in XML and then just creating the method. Here's the code:
public void recordBtnClick(View v){
final ToggleButton touchToRecord = (ToggleButton)findViewById(R.id.tBtn1);
final ImageButton recBtn = (ImageButton) findViewById(com.whizzappseasyvoicenotepad.R.id.recButton);
if (touchToRecord.isChecked() == false)
{
if (recorder == null)
{
recBtn.setImageResource(com.whizzappseasyvoicenotepad.R.drawable.record_btn_pressed);
chTimer.start();
chTimer.setTextColor(Color.GREEN);
startRecording();
}
else if (recorder != null)
{
recBtn.setImageResource(com.whizzappseasyvoicenotepad.R.drawable.record_btn);
chTimer.stop();
stopRecording();
nameAlert();
}
}
else
{
//DO NOTHING
}
}

Categories

Resources