chriskopec
chriskopec

Reputation: 605

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

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!

Upvotes: 35

Views: 43795

Answers (4)

Dan Lew
Dan Lew

Reputation: 87430

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.

Upvotes: 96

live-love
live-love

Reputation: 52366

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();
    }
}

Upvotes: 4

danigonlinea
danigonlinea

Reputation: 1113

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;
    }

}

Upvotes: 0

Oxydant
Oxydant

Reputation: 111

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);
    }

}

Upvotes: 11

Related Questions