Skip to content

Commit

Permalink
Fix crash when current activity is null (#6022)
Browse files Browse the repository at this point in the history
## Summary

Should fix: #5892. We do not check if the current activity is `null` and
it seems that it randomly can be null. It seems like ongoing issue on
react native side:
facebook/react-native#37518,
facebook/react-native#18345. The
`useAnimatedKeyboard` hook won't work when the app when current activity
is `null`, but it should not crash the app anymore. Our assumption is
that most of the libs handle it this way (#5892), so it must be some
corner case when most functionality won't work - that's why we don't try
to recover from this state.

---------

Co-authored-by: Krzysztof Piaskowy <krzysztof.piaskowy@swmansion.com>
  • Loading branch information
maciekstosio and piaskowyk authored Jun 3, 2024
1 parent 3188d92 commit a2db53d
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 12 deletions.
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package com.swmansion.reanimated.keyboard;

import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.FrameLayout;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowCompat;
Expand All @@ -18,6 +19,8 @@ public class WindowsInsetsManager {
private final Keyboard mKeyboard;
private final NotifyAboutKeyboardChangeFunction mNotifyAboutKeyboardChange;

private final String MissingContextErrorMsg = "Unable to get reference to react activity";

public WindowsInsetsManager(
WeakReference<ReactApplicationContext> reactContext,
Keyboard keyboard,
Expand All @@ -27,33 +30,54 @@ public WindowsInsetsManager(
mNotifyAboutKeyboardChange = notifyAboutKeyboardChange;
}

private Window getWindow() {
return mReactContext.get().getCurrentActivity().getWindow();
}

private View getRootView() {
return getWindow().getDecorView();
private Activity getCurrentActivity() {
return mReactContext.get().getCurrentActivity();
}

public void startObservingChanges(
KeyboardAnimationCallback keyboardAnimationCallback, boolean isStatusBarTranslucent) {
mIsStatusBarTranslucent = isStatusBarTranslucent;
updateWindowDecor(false);
ViewCompat.setOnApplyWindowInsetsListener(getRootView(), this::onApplyWindowInsetsListener);
ViewCompat.setWindowInsetsAnimationCallback(getRootView(), keyboardAnimationCallback);

Activity currentActivity = getCurrentActivity();
if (currentActivity == null) {
Log.e("Reanimated", MissingContextErrorMsg);
return;
}

View rootView = currentActivity.getWindow().getDecorView();
ViewCompat.setOnApplyWindowInsetsListener(rootView, this::onApplyWindowInsetsListener);
ViewCompat.setWindowInsetsAnimationCallback(rootView, keyboardAnimationCallback);
}

public void stopObservingChanges() {
updateWindowDecor(!mIsStatusBarTranslucent);
updateInsets(0, 0);
View rootView = getRootView();

Activity currentActivity = getCurrentActivity();
if (currentActivity == null) {
Log.e("Reanimated", MissingContextErrorMsg);
return;
}

View rootView = currentActivity.getWindow().getDecorView();
ViewCompat.setWindowInsetsAnimationCallback(rootView, null);
ViewCompat.setOnApplyWindowInsetsListener(rootView, null);
}

private void updateWindowDecor(boolean decorFitsSystemWindow) {
new Handler(Looper.getMainLooper())
.post(() -> WindowCompat.setDecorFitsSystemWindows(getWindow(), decorFitsSystemWindow));
.post(
() -> {
Activity currentActivity = getCurrentActivity();
if (currentActivity == null) {
Log.e("Reanimated", MissingContextErrorMsg);
return;
}

WindowCompat.setDecorFitsSystemWindows(
currentActivity.getWindow(), decorFitsSystemWindow);
});
}

private WindowInsetsCompat onApplyWindowInsetsListener(View view, WindowInsetsCompat insets) {
Expand All @@ -79,7 +103,15 @@ private void updateInsets(int paddingTop, int paddingBottom) {
() -> {
FrameLayout.LayoutParams params = getLayoutParams(paddingTop, paddingBottom);
int actionBarId = androidx.appcompat.R.id.action_bar_root;
View actionBarRootView = getRootView().findViewById(actionBarId);

Activity currentActivity = getCurrentActivity();
if (currentActivity == null) {
Log.e("Reanimated", MissingContextErrorMsg);
return;
}

View actionBarRootView =
currentActivity.getWindow().getDecorView().findViewById(actionBarId);
actionBarRootView.setLayoutParams(params);
});
}
Expand Down
2 changes: 2 additions & 0 deletions cspell.json
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
{
"language": "en",
"words": [
"androidx",
"animable",
"animatable",
"appcompat",
"barfoo",
"barfoo",
"bfrg",
Expand Down

0 comments on commit a2db53d

Please sign in to comment.