1

My MainActivity leads to SecondActivity. If the user presses the phone's back button the app goes back to the MainActivity.

How can I execute something when this happens?

(I know I could put code in SecondActivity to add functionality to the back button so it passes a result to MainActivity, but I don't want to do that to every possible screen that could lead back to the MainActivity.)

Perhaps another way of asking, how can I know that MainActivity is showing because of pressing the back button rather than having been formally requested with an intent?

Ben Mora
  • 279
  • 3
  • 16

2 Answers2

1

Background

I think here is the logic to implement this requirement:

  1. When users press the back key on the current activity, we will remember that action.

  2. When users go back to the previous activity, we will check whether there is a back key pressed action exits or not.

Implementation

Step 1. Create a base activity class named BaseActivity. Every activity in your app should extend from this class.

class BaseActivity extends AppCompatActivity {

    public static String IS_BACK_KEY_PRESSED = "IS_BACK_KEY_PRESSED";

    @Override
    public void onBackPressed() {
        // Remember the user's press of the back key action
        getIntent().putExtra(IS_BACK_KEY_PRESSED, true);

        // Call the super's method
        super.onBackPressed();
    }

    /**
     * Called when the activity has been resumed from an activity
     * that has been destroyed because of user's press of the back key
     */
    public void onGoBackFromAnotherActivity() {
    }
}

Step 2. Create a class named MyApp that extends from the Application class. Its purpose is to listen to all activity lifecycle of the app by using registerActivityLifecycleCallbacks(Application.ActivityLifecycleCallbacks)

public class MyApp extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        registerActivityLifecycleCallbacks(new ActivityLifecycleCallbacksImpl());
    }

    private static final class ActivityLifecycleCallbacksImpl implements ActivityLifecycleCallbacks {
        boolean isBackKeyPressed = false;

        @Override
        public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
        }

        @Override
        public void onActivityStarted(@NonNull Activity activity) {
            if (activity instanceof BaseActivity) {
                if (isBackKeyPressed) {
                    ((BaseActivity) activity).onGoBackFromAnotherActivity();
                    isBackKeyPressed = false;
                }
            }
        }

        @Override
        public void onActivityResumed(@NonNull Activity activity) {
        }

        @Override
        public void onActivityPaused(@NonNull Activity activity) {
            if (activity instanceof BaseActivity) {
                Bundle data = activity.getIntent().getExtras();
                if (data != null) {
                    isBackKeyPressed = data.getBoolean(BaseActivity.IS_BACK_KEY_PRESSED);
                } else {
                    isBackKeyPressed = false;
                }
            }
        }

        @Override
        public void onActivityStopped(@NonNull Activity activity) {
        }

        @Override
        public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
        }

        @Override
        public void onActivityDestroyed(@NonNull Activity activity) {
        }
    }
}

Remember to add this class to AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.kotlinapp">

    <application
        android:name=".MyApp"
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity android:name=".SecondActivity" />

    </application>

</manifest>

Usage

MainActivity.java

public class MainActivity extends BaseActivity {

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public void onGoBackFromAnotherActivity() {
        // Your code logic goes here.
    }
}

SecondActivity.java

public class SecondActivity extends BaseActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);
    }
}
Son Truong
  • 13,661
  • 5
  • 32
  • 58
1

Edit: Check if any activity (without knowing which) returned to desired activity

To check in Activity A, use:

@Override
protected void onResume() {
    super.onResume();
    // TODO: Work
}

As stated in the comment, onResume will be called on an activity/fragment when:

  1. Activity runs for the first time
  2. Activity comes back into focus (from another activity, launcher, recent, another app)

However, you cannot track what triggered it, or what happened before it.


---------- Outdated ----------


Between Activity A and Activity B

use

startActivityForResult(intent, CHOOSE_AN_INT_VALUE_TO_INDICATE_IT_REQUESTS_FOR_BACK_PRESS);

In Activity A, and in Activity B, use

    @Override
    public void onBackPressed() {
        setResult(CHOOSE_AN_INT_VALUE_TO_INDICATE_IT_CAME_FROM_BACK_PRESS);
        finish();
    }

Then again in Activity A, use

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if (requestCode == CHOOSE_AN_INT_VALUE_TO_INDICATE_IT_REQUESTS_FOR_BACK_PRESS && resultCode==CHOOSE_AN_INT_VALUE_TO_INDICATE_IT_CAME_FROM_BACK_PRESS) {
        // TODO: Do your work
    }
}

If these 3 portions are implemented, you don't need to check for which activity triggered back press, you can simply compare the request and result codes

I hope this helps!!

Abdullah Z Khan
  • 1,272
  • 1
  • 8
  • 18
  • But what if I have no way of knowing where you came from? Or if I have no way of controlling it, such as if the user taps a notification which leads to a different app, and then they press the back button which goes back to my app? – Ben Mora Dec 05 '20 at 13:22
  • ^ Maybe this means my question is the wrong question. Maybe I'm asking, "how do I know when my activity is brought to front and now shown on screen? – Ben Mora Dec 05 '20 at 13:24
  • 1
    then you need to implement onResume and onStart calls. onResume will notify you every time an activity/fragment is resumed. However, onResume will provide no context as to what made it resume. onResume will also be called once when an activity starts. – Abdullah Z Khan Dec 05 '20 at 14:02