Android - How To Override the "Back" button so it doesn't Finish() my Activity?
Asked Answered
C

10

227

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?

Caras answered 29/6, 2010 at 15:5 Comment(6)
There is a similar question: #2460348Karafuto
Similar answer.. #5914540Selfevident
Also I think you have to change your code to ` if (Integer.parseInt(android.os.Build.VERSION.SDK) > 5, the <` should become a >.Autopilot
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.Mientao
developer.android.com/guide/navigation/navigation-custom-backNullify
UPDATE September 2022 onBackPressed() was deprecated in API level 33. Use OnBackInvokedCallback or androidx.activity.OnBackPressedCallback to handle back navigation instead.Unpretentious
B
311

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);
}
Bradway answered 29/6, 2010 at 16:0 Comment(0)
S
85

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

@Override
public void onBackPressed() {
   moveTaskToBack(true);
}
Sebastien answered 24/4, 2015 at 16:48 Comment(5)
This should be the accepted answer. This does exactly what the question is asking and is using clean built in functionality.Frohne
Thankyou :) can you elaborate the concept behind it?Azral
You simply override the onBackPressed() event, making it move the activity to the back.Astronomical
This solution won't bring the activity back when you re-launch the app from the home screen (if there is another activity on the task stack).Abiogenetic
it says this is depreciated nowMetric
A
16

simply do this..

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

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

Archduchess answered 18/5, 2016 at 11:3 Comment(2)
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.Mientao
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.Archduchess
L
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.

Laverty answered 29/6, 2010 at 15:48 Comment(5)
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. ThanksCaras
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.Angelo
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.Udele
Isnt the onSaveInstanceState and saving data a completely different question?Lapierre
@Lapierre -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.Mientao
Y
8

Try this:

@Override
public void onBackPressed() {
    finish();
}
Yuen answered 8/5, 2017 at 12:2 Comment(0)
B
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();
        }
    }    
}
Burnedout answered 25/7, 2017 at 9:11 Comment(0)
C
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)
Coretta answered 9/1, 2019 at 16:40 Comment(0)
F
2

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.

Fetishist answered 12/2, 2020 at 9:36 Comment(0)
N
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.

Naturalize answered 10/9, 2020 at 23:55 Comment(0)
M
-2

just do this

@Override
public void onBackPressed() {
    super.onBackPressed();
}
Matchbook answered 29/10, 2020 at 15:17 Comment(1)
this will exit or take to the previous screen from the application, not to homePadang

© 2022 - 2024 — McMap. All rights reserved.