-
-
Notifications
You must be signed in to change notification settings - Fork 359
fix(session-replay): Fixes orientation change misalignment for session replay on Android #5321
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 8 commits
960f850
185b920
87ce208
c8266c3
1672112
464601e
cf4ca99
97097b5
919dff2
5c6a512
a0c30cc
1f6a939
1099bd7
f4690cc
dbee1d4
21a37a5
bbddc27
b408aed
e8e516f
e8debff
a8ad163
f963590
affda3d
f56e75c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| import android.os.Bundle; | ||
| import android.view.View; | ||
| import android.view.ViewGroup; | ||
| import android.view.ViewTreeObserver; | ||
| import androidx.annotation.NonNull; | ||
| import androidx.fragment.app.Fragment; | ||
| import androidx.fragment.app.FragmentManager; | ||
|
|
@@ -13,9 +14,13 @@ | |
| import com.facebook.react.uimanager.events.EventDispatcher; | ||
| import com.facebook.react.uimanager.events.EventDispatcherListener; | ||
| import io.sentry.ILogger; | ||
| import io.sentry.Integration; | ||
| import io.sentry.ScopesAdapter; | ||
| import io.sentry.SentryLevel; | ||
| import io.sentry.SentryOptions; | ||
| import io.sentry.android.core.BuildInfoProvider; | ||
| import io.sentry.android.core.internal.util.FirstDrawDoneListener; | ||
| import io.sentry.android.replay.ReplayIntegration; | ||
| import org.jetbrains.annotations.NotNull; | ||
| import org.jetbrains.annotations.Nullable; | ||
|
|
||
|
|
@@ -25,6 +30,13 @@ public class RNSentryReactFragmentLifecycleTracer extends FragmentLifecycleCallb | |
| private @NotNull final Runnable emitNewFrameEvent; | ||
| private @NotNull final ILogger logger; | ||
|
|
||
| private @Nullable ReplayIntegration replayIntegration; | ||
| private int lastWidth = -1; | ||
| private int lastHeight = -1; | ||
|
|
||
| private @Nullable View currentView; | ||
| private @Nullable ViewTreeObserver.OnGlobalLayoutListener currentListener; | ||
|
|
||
| public RNSentryReactFragmentLifecycleTracer( | ||
| @NotNull BuildInfoProvider buildInfoProvider, | ||
| @NotNull Runnable emitNewFrameEvent, | ||
|
|
@@ -95,6 +107,94 @@ public void onEventDispatch(Event event) { | |
| } | ||
| } | ||
| }); | ||
|
|
||
| // Add layout listener to detect configuration changes after detaching any previous one | ||
|
||
| detachLayoutChangeListener(); | ||
| attachLayoutChangeListener(v); | ||
| } | ||
|
|
||
| @Override | ||
| public void onFragmentViewDestroyed(@NonNull FragmentManager fm, @NonNull Fragment f) { | ||
| detachLayoutChangeListener(); | ||
| } | ||
|
|
||
| private void attachLayoutChangeListener(final View view) { | ||
| final ViewTreeObserver.OnGlobalLayoutListener listener = | ||
| new ViewTreeObserver.OnGlobalLayoutListener() { | ||
| @Override | ||
| public void onGlobalLayout() { | ||
| checkAndNotifyWindowSizeChange(view); | ||
| } | ||
| }; | ||
|
|
||
| currentView = view; | ||
| currentListener = listener; | ||
|
|
||
| view.getViewTreeObserver().addOnGlobalLayoutListener(listener); | ||
antonis marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
antonis marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| private void detachLayoutChangeListener() { | ||
| if (currentView != null && currentListener != null) { | ||
| try { | ||
| currentView.getViewTreeObserver().removeOnGlobalLayoutListener(currentListener); | ||
| } catch (Exception e) { | ||
| logger.log(SentryLevel.DEBUG, "Failed to remove layout change listener", e); | ||
| } | ||
| } | ||
|
|
||
| currentView = null; | ||
| currentListener = null; | ||
antonis marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } | ||
|
|
||
| private void checkAndNotifyWindowSizeChange(View view) { | ||
| try { | ||
| android.util.DisplayMetrics metrics = view.getContext().getResources().getDisplayMetrics(); | ||
| int currentWidth = metrics.widthPixels; | ||
| int currentHeight = metrics.heightPixels; | ||
|
|
||
| if (lastWidth != currentWidth || lastHeight != currentHeight) { | ||
| lastWidth = currentWidth; | ||
| lastHeight = currentHeight; | ||
antonis marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| notifyReplayIntegrationOfSizeChange(currentWidth, currentHeight); | ||
| } | ||
| } catch (Exception e) { | ||
| logger.log(SentryLevel.DEBUG, "Failed to check window size", e); | ||
| } | ||
| } | ||
|
|
||
| private void notifyReplayIntegrationOfSizeChange(int width, int height) { | ||
| try { | ||
antonis marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| if (replayIntegration == null) { | ||
| replayIntegration = getReplayIntegration(); | ||
| } | ||
antonis marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| if (replayIntegration == null) { | ||
| return; | ||
| } | ||
|
|
||
| replayIntegration.onWindowSizeChanged(width, height); | ||
antonis marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| } catch (Exception e) { | ||
| logger.log(SentryLevel.DEBUG, "Failed to notify replay integration of size change", e); | ||
| } | ||
| } | ||
|
|
||
| private @Nullable ReplayIntegration getReplayIntegration() { | ||
|
||
| try { | ||
| final SentryOptions options = ScopesAdapter.getInstance().getOptions(); | ||
| if (options == null) { | ||
| return null; | ||
| } | ||
|
|
||
| for (Integration integration : options.getIntegrations()) { | ||
| if (integration instanceof ReplayIntegration) { | ||
| return (ReplayIntegration) integration; | ||
| } | ||
| } | ||
| } catch (Exception e) { | ||
| logger.log(SentryLevel.DEBUG, "Error getting replay integration", e); | ||
| } | ||
| return null; | ||
| } | ||
|
|
||
| private static @Nullable EventDispatcher getEventDispatcherForReactTag( | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.