225

I currently have an Activity that when it gets displayed a Notification will also get displayed in the Notification bar.

This is so that when the User presses home and the Activity gets pushed to the background they can get back to the Activity via the Notification.

The problem arises when a User presses the back button, my Activity gets destroyed but the Notification remains as I want the user to be able to press back but still be able to get to the Activity via the Notification. But when a USER tries this I get Null Pointers as its trying to start a new activity rather than bringing back the old one.

So essentially I want the Back button to act the exact same as the Home button and here is how I have tried so far:


        @Override
        public boolean onKeyDown(int keyCode, KeyEvent event)  {
            if (Integer.parseInt(android.os.Build.VERSION.SDK) < 5
                    && keyCode == KeyEvent.KEYCODE_BACK
                    && event.getRepeatCount() == 0) {
                Log.d("CDA", "onKeyDown Called");
                onBackPressed();
            }

            return super.onKeyDown(keyCode, event);
        }

        public void onBackPressed() {
            Log.d("CDA", "onBackPressed Called");
            Intent setIntent = new Intent(Intent.ACTION_MAIN);
            setIntent.addCategory(Intent.CATEGORY_HOME);
            setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            startActivity(setIntent); 

            return;
        }   

However the above code still seems to allow my Activity to be destroyed, How can I stop my Activity from being destroyed when the back button is pressed?

Donal Rafferty
  • 19,707
  • 39
  • 114
  • 191
  • There is a similar question: http://stackoverflow.com/questions/2459848/android-prompt-user-to-save-changes-when-back-button-is-pressed – aleung Dec 19 '10 at 13:26
  • 1
    Similar answer.. http://stackoverflow.com/questions/5914040/onbackpressed-to-hide-not-destroy-activity/23759328#23759328 – Zar E Ahmer May 20 '14 at 12:06
  • Also I think you have to change your code to ` if (Integer.parseInt(android.os.Build.VERSION.SDK) > 5`, the `<` should become a `>`. – SudoPlz Nov 18 '15 at 23:40
  • 1
    Even if you solve this, you still must handle the possibility of the system killing your app, right? I mean, the null case is still possible? Or if the system kills your app for any reason, will that also remove your notification? I'm thinking this must be a problem, since the purpose of a notification is to exist even if the app does not. – ToolmakerSteve Sep 22 '16 at 11:14
  • https://developer.android.com/guide/navigation/navigation-custom-back – Anoop M Maddasseri Jan 19 '21 at 12:24
  • 1
    ***UPDATE September 2022*** [onBackPressed()](https://developer.android.com/reference/android/app/Activity#onBackPressed()) was deprecated in API level 33. Use `OnBackInvokedCallback` or `androidx.activity.OnBackPressedCallback` to handle back navigation instead. – Alex Cohn Dec 22 '22 at 10:17

10 Answers10

310

Remove your key listener or return true when you have KEY_BACK.

You just need the following to catch the back key (Make sure not to call super in onBackPressed()).

Also, if you plan on having a service run in the background, make sure to look at startForeground() and make sure to have an ongoing notification or else Android will kill your service if it needs to free memory.

@Override
public void onBackPressed() {
   Log.d("CDA", "onBackPressed Called");
   Intent setIntent = new Intent(Intent.ACTION_MAIN);
   setIntent.addCategory(Intent.CATEGORY_HOME);
   setIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
   startActivity(setIntent);
}
Community
  • 1
  • 1
ekawas
  • 6,594
  • 3
  • 27
  • 39
84

It was easier to implement it only with one line of code:

@Override
public void onBackPressed() {
   moveTaskToBack(true);
}
Teo Inke
  • 5,928
  • 4
  • 38
  • 37
16

simply do this..

@Override
public void onBackPressed() {
    //super.onBackPressed();
}

commenting out the //super.onBackPressed(); will do the trick

androCoder-BD
  • 498
  • 7
  • 13
  • 1
    A useful observation, but won't this cause the back button to do nothing at all, as if it were broken? That is not a good thing to do - confusing and annoying for users. IMHO must add logic from another answer, to act like Home button, as was requested in question. The accepted answer *mentions* that they were deliberately not calling super method. – ToolmakerSteve Sep 22 '16 at 11:31
  • Yes, you are absolutely right. It will just override the back button and will do nothing until you put some logic there. May be a condition for double press the button to close the application or you just want to disable an ongoing operation (progress dialog)etc, but its completely up to the requirement. – androCoder-BD Dec 02 '16 at 15:51
12

I think what you want is not to override the back button (that just doesn't seem like a good idea - Android OS defines that behavior, why change it?), but to use the Activity Lifecycle and persist your settings/data in the onSaveInstanceState(Bundle) event.

@Override
onSaveInstanceState(Bundle frozenState) {
    frozenState.putSerializable("object_key",
        someSerializableClassYouWantToPersist);
    // etc. until you have everything important stored in the bundle
}

Then you use onCreate(Bundle) to get everything out of that persisted bundle and recreate your state.

@Override
onCreate(Bundle savedInstanceState) {
    if(savedInstanceState!=null){ //It could be null if starting the app.
        mCustomObject = savedInstanceState.getSerializable("object_key");
    }
    // etc. until you have reloaded everything you stored
}

Consider the above psuedo-code to point you in the right direction. Reading up on the Activity Lifecycle should help you determine the best way to accomplish what you're looking for.

ramon_salla
  • 1,587
  • 1
  • 17
  • 35
kiswa
  • 14,737
  • 1
  • 21
  • 29
  • Hi Kiswa, this is true, I dont want to change the default behaviour. I have tried using the onSavedInstanceState and it wasn't working but I believe I have spotted my error now. Thanks – Donal Rafferty Jun 29 '10 at 16:11
  • 5
    I've come across at least a few situations where I wanted to simulate the standard Activity stack behavior without actually starting new Activities. In these cases, I think, it's appropriate to override the default onBackPressed() behavior. In general, though, I agree: avoid overriding. – Matt Briançon May 09 '11 at 07:17
  • 4
    I agree with @Matt. I'm currently working on a cross platform game which uses the NDK. As such, it's easiest if everything is a single activity. Because of this, the default behavour of the back button is to escape the application, which is not what most users expect. So I had to overwrite the default behavour to make the activity behave differently, as if the user had actually gone to a different activity, and only quit the app in certain circomstances. – Leif Andersen Aug 11 '11 at 02:11
  • 1
    Isnt the onSaveInstanceState and saving data a completely different question? – Ted Oct 05 '11 at 13:21
  • @Ted -if you are saying that in adition to onSaveInstanceState, there also needs to be code that persists non-UI app data, then I agree. As soon as you relinquish foreground, your app could be killed with no further warning. Must always save anything that matters. On the other hand, I think the app lifecycle methods will be called regardless of what technique you use to hide app but keep it around, so it should not be necessary to add save logic just for this case. Your app needs that code in all the right places regardless. – ToolmakerSteve Sep 22 '16 at 11:22
8

Try this:

@Override
public void onBackPressed() {
    finish();
}
FelixSFD
  • 6,052
  • 10
  • 43
  • 117
Thakur
  • 99
  • 1
  • 3
4

Just in case you want to handle the behaviour of the back button (at the bottom of the phone) and the home button (the one to the left of the action bar), this custom activity I'm using in my project may help you.

import android.os.Bundle;
import android.support.v7.app.ActionBar;
import android.support.v7.app.AppCompatActivity;
import android.view.MenuItem;

/**
 * Activity where the home action bar button behaves like back by default
 */
public class BackActivity extends AppCompatActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setupHomeButton();
    }

    private void setupHomeButton() {
        final ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setDisplayHomeAsUpEnabled(true);
            actionBar.setHomeButtonEnabled(true);
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                onMenuHomePressed();
                return true;
        }
        return super.onOptionsItemSelected(item);
    }

    protected void onMenuHomePressed() {
        onBackPressed();
    }
}

Example of use in your activity:

public class SomeActivity extends BackActivity {

    // ....

    @Override
    public void onBackPressed()
    {
        // Example of logic
        if ( yourConditionToOverride ) {
            // ... do your logic ...
        } else {
            super.onBackPressed();
        }
    }    
}
Ferran Maylinch
  • 10,919
  • 16
  • 85
  • 100
2
@Override
public void onBackPressed() {
// Put your code here.
}

//I had to go back to the dashboard. Hence,

@Override
public void onBackPressed() {
    Intent intent = new Intent(this,Dashboard.class);
    startActivity(intent);
}
Just write this above or below the onCreate Method(within the class)
user3156040
  • 723
  • 5
  • 5
1

In Kotlin:

val callback = requireActivity().onBackPressedDispatcher.addCallback(this) {
    // Handle the back button event
}

For more information you can check this.

There is also specific question about overriding back button in Kotlin.

solaza
  • 1,251
  • 1
  • 17
  • 30
0

Looks like im very late but for those of you who need to switch to new screen and clear back button stack here is a very simple solution.

startActivity(new Intent(this,your-new-screen.class));
finishAffinity();

The finishAffinity(); method clears back button stack.

RK_DUDE02
  • 25
  • 5
-2

just do this

@Override
public void onBackPressed() {
    super.onBackPressed();
}
PMerlet
  • 2,568
  • 4
  • 23
  • 39
  • this will exit or take to the previous screen from the application, not to home – YLS Oct 29 '20 at 16:43