5

I have an activity BasicReactActivity which extends ReactActivity. I use this activity as a base activity to host my react-native views. I have a use case where I am opening multiple instances of BasicReactActivity one on top of the other. I face the following exception crash:

Fatal Exception: java.lang.AssertionError: Pausing an activity that is not the current activity, this is incorrect! Current activity: BasicReactActivity Paused activity: BasicReactActivity
       at com.facebook.infer.annotation.Assertions.assertCondition(Assertions.java:72)
       at com.facebook.react.ReactInstanceManager.onHostPause(ReactInstanceManager.java:549)
       at com.facebook.react.ReactDelegate.onHostPause(ReactDelegate.java:63)
       at com.facebook.react.ReactActivityDelegate.onPause(ReactActivityDelegate.java:95)
       at com.facebook.react.ReactActivity.onPause(ReactActivity.java:51)
       at com.apollorncontainer.activities.BasicReactActivity.onPause(BasicReactActivity.java:267)
       at android.app.Activity.performPause(Activity.java:8142)
       at android.app.Instrumentation.callActivityOnPause(Instrumentation.java:1508)
       at android.app.ActivityThread.performPauseActivityIfNeeded(ActivityThread.java:4726)
       at android.app.ActivityThread.performPauseActivity(ActivityThread.java:4687)
       at android.app.ActivityThread.handlePauseActivity(ActivityThread.java:4639)
       at android.app.servertransaction.TransactionExecutor.performLifecycleSequence(TransactionExecutor.java:228)
       at android.app.servertransaction.TransactionExecutor.cycleToPath(TransactionExecutor.java:201)
       at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:173)
       at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
       at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2147)
       at android.os.Handler.dispatchMessage(Handler.java:107)

Following is the code for my onResume() and onPause() of the BasicReactActivity:

public static Object REACT_DELEGATE_LOCK = new Object();

@Override
    protected void onPause() {
        super.onPause();
        Timber.d("{CrashDebug} Calling onPause for: " + getTag());
        Timber.d("\n");
        if(reactDelegate != null) {
            try {
                synchronized (REACT_DELEGATE_LOCK) {
                    reactDelegate.onHostPause();
                }
            } catch (Exception e) {
                Timber.e(e);
            }
        }
    }


@Override
    protected void onResume() {
        super.onResume();
        Timber.d("{CrashDebug} Calling onResume for: " + getTag());
        if(reactDelegate != null) {
            synchronized (REACT_DELEGATE_LOCK) {
                reactDelegate.onHostResume();
            }
        }
}

private String getTag() {
        if(reactDelegate.getReactInstanceManager().getCurrentReactContext() != null &&
                reactDelegate.getReactInstanceManager().getCurrentReactContext()
                        .getCurrentActivity() != null) {
            return component + " : " + getReactNativeHost().getReactInstanceManager().getCurrentReactContext()
                    .getCurrentActivity() + " : " + this;
        }
        return component + " : null : " + this;
    }

Few notes for the above code:

  • I have added a lock around reactDelegate operations to avoid any concurrency between the onHostPause() and onHostResume() calls between two instances of BasicReactActivity
  • getTag() method is usedd to trace the current state in runtime.

In one of the crashes, I see the following logs:

Calling onResume for: ACCOUNT_BLOCKED : com.apollorncontainer.activities.BasicReactActivity@90a3e41 : com.apollorncontainer.activities.BasicReactActivity@90a3e41
Calling onResume for: ACCOUNT_BLOCKED : com.apollorncontainer.activities.BasicReactActivity@90a3e41 : com.apollorncontainer.activities.BasicReactActivity@b89a25c
Calling onPause for: ACCOUNT_BLOCKED : com.apollorncontainer.activities.BasicReactActivity@90a3e41 : com.apollorncontainer.activities.BasicReactActivity@b89a25c

Calling onResume for: POST_SIGNUP : com.apollorncontainer.activities.BasicReactActivity@96f6947 : com.apollorncontainer.activities.BasicReactActivity@96f6947
Calling onResume for: POST_SIGNUP : com.apollorncontainer.activities.BasicReactActivity@96f6947 : com.apollorncontainer.activities.BasicReactActivity@a9f057a
Calling onPause for: POST_SIGNUP : com.apollorncontainer.activities.BasicReactActivity@96f6947 : com.apollorncontainer.activities.BasicReactActivity@a9f057a

If we observe these two lines specifically:

Calling onResume for: ACCOUNT_BLOCKED : com.apollorncontainer.activities.BasicReactActivity@90a3e41 : com.apollorncontainer.activities.BasicReactActivity@b89a25c
Calling onPause for: ACCOUNT_BLOCKED : com.apollorncontainer.activities.BasicReactActivity@90a3e41 : com.apollorncontainer.activities.BasicReactActivity@b89a25c

Even after calling of onHostResume() for instance b89a25c, the mCurrentActivity fetched from the ReactContext does not change when onHostPause() is called.

If we check the method onHostResume(), only two things can cause this not to set:

  • getReactNativeHost().hasInstance() returns false OR
  • mLifecycleState != LifecycleState.BEFORE_RESUME and mLifecycleState != LifecycleState.BEFORE_CREATE (from ReactInstanceManager.moveToResumedLifecycleState)

Both above don't seem probable. Not sure, where is the problem here.

PS: I am using version 0.63.4 of react native.

Swapnil
  • 1,870
  • 2
  • 23
  • 48

0 Answers0