diff --git a/RELEASENOTES.md b/RELEASENOTES.md
index 98de3a6255..c9b986f731 100644
--- a/RELEASENOTES.md
+++ b/RELEASENOTES.md
@@ -5,6 +5,9 @@
* Text: Catch-and-log all fatal exceptions in `TextRenderer` instead of
re-throwing, allowing playback to continue even if subtitles fail
([#6885](https://github.com/google/ExoPlayer/issues/6885)).
+* UI: Add an option to set whether to use the orientation sensor for rotation
+ in spherical playbacks
+ ([#6761](https://github.com/google/ExoPlayer/issues/6761)).
* DASH:
* Update the manifest URI to avoid repeated HTTP redirects
([#6907](https://github.com/google/ExoPlayer/issues/6907)).
diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
index 03168643cf..2eae9c1dde 100644
--- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/PlayerView.java
@@ -143,6 +143,12 @@ import org.checkerframework.checker.nullness.qual.RequiresNonNull;
*
Corresponding method: None
* Default: {@code surface_view}
*
+ * {@code use_sensor_rotation} - Whether to use the orientation sensor for rotation
+ * during spherical playbacks (if available).
+ *
+ * - Corresponding method: {@link #setUseSensorRotation(boolean)}
+ *
- Default: {@code true}
+ *
* {@code shutter_background_color} - The background color of the {@code exo_shutter}
* view.
*
@@ -308,6 +314,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
@Nullable private Drawable defaultArtwork;
private @ShowBuffering int showBuffering;
private boolean keepContentOnPlayerReset;
+ private boolean useSensorRotation;
@Nullable private ErrorMessageProvider super ExoPlaybackException> errorMessageProvider;
@Nullable private CharSequence customErrorMessage;
private int controllerShowTimeoutMs;
@@ -367,6 +374,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
boolean controllerAutoShow = true;
boolean controllerHideDuringAds = true;
int showBuffering = SHOW_BUFFERING_NEVER;
+ useSensorRotation = true;
if (attrs != null) {
TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.PlayerView, 0, 0);
try {
@@ -390,6 +398,8 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
R.styleable.PlayerView_keep_content_on_player_reset, keepContentOnPlayerReset);
controllerHideDuringAds =
a.getBoolean(R.styleable.PlayerView_hide_during_ads, controllerHideDuringAds);
+ useSensorRotation =
+ a.getBoolean(R.styleable.PlayerView_use_sensor_rotation, useSensorRotation);
} finally {
a.recycle();
}
@@ -422,6 +432,7 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
case SURFACE_TYPE_SPHERICAL_GL_SURFACE_VIEW:
SphericalGLSurfaceView sphericalGLSurfaceView = new SphericalGLSurfaceView(context);
sphericalGLSurfaceView.setSingleTapListener(componentListener);
+ sphericalGLSurfaceView.setUseSensorRotation(useSensorRotation);
surfaceView = sphericalGLSurfaceView;
break;
case SURFACE_TYPE_VIDEO_DECODER_GL_SURFACE_VIEW:
@@ -746,6 +757,22 @@ public class PlayerView extends FrameLayout implements AdsLoader.AdViewProvider
}
}
+ /**
+ * Sets whether to use the orientation sensor for rotation during spherical playbacks (if
+ * available)
+ *
+ * @param useSensorRotation Whether to use the orientation sensor for rotation during spherical
+ * playbacks.
+ */
+ public void setUseSensorRotation(boolean useSensorRotation) {
+ if (this.useSensorRotation != useSensorRotation) {
+ this.useSensorRotation = useSensorRotation;
+ if (surfaceView instanceof SphericalGLSurfaceView) {
+ ((SphericalGLSurfaceView) surfaceView).setUseSensorRotation(useSensorRotation);
+ }
+ }
+ }
+
/**
* Sets whether a buffering spinner is displayed when the player is in the buffering state. The
* buffering spinner is not displayed by default.
diff --git a/library/ui/src/main/java/com/google/android/exoplayer2/ui/spherical/SphericalGLSurfaceView.java b/library/ui/src/main/java/com/google/android/exoplayer2/ui/spherical/SphericalGLSurfaceView.java
index c01fccf54b..1c96f41df5 100644
--- a/library/ui/src/main/java/com/google/android/exoplayer2/ui/spherical/SphericalGLSurfaceView.java
+++ b/library/ui/src/main/java/com/google/android/exoplayer2/ui/spherical/SphericalGLSurfaceView.java
@@ -72,6 +72,9 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
@Nullable private SurfaceTexture surfaceTexture;
@Nullable private Surface surface;
@Nullable private Player.VideoComponent videoComponent;
+ private boolean useSensorRotation;
+ private boolean isStarted;
+ private boolean isOrientationListenerRegistered;
public SphericalGLSurfaceView(Context context) {
this(context, null);
@@ -104,6 +107,7 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
WindowManager windowManager = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
Display display = Assertions.checkNotNull(windowManager).getDefaultDisplay();
orientationListener = new OrientationListener(display, touchTracker, renderer);
+ useSensorRotation = true;
setEGLContextClientVersion(2);
setRenderer(renderer);
@@ -145,20 +149,23 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
touchTracker.setSingleTapListener(listener);
}
+ /** Sets whether to use the orientation sensor for rotation (if available). */
+ public void setUseSensorRotation(boolean useSensorRotation) {
+ this.useSensorRotation = useSensorRotation;
+ updateOrientationListenerRegistration();
+ }
+
@Override
public void onResume() {
super.onResume();
- if (orientationSensor != null) {
- sensorManager.registerListener(
- orientationListener, orientationSensor, SensorManager.SENSOR_DELAY_FASTEST);
- }
+ isStarted = true;
+ updateOrientationListenerRegistration();
}
@Override
public void onPause() {
- if (orientationSensor != null) {
- sensorManager.unregisterListener(orientationListener);
- }
+ isStarted = false;
+ updateOrientationListenerRegistration();
super.onPause();
}
@@ -181,6 +188,20 @@ public final class SphericalGLSurfaceView extends GLSurfaceView {
});
}
+ private void updateOrientationListenerRegistration() {
+ boolean enabled = useSensorRotation && isStarted;
+ if (orientationSensor == null || enabled == isOrientationListenerRegistered) {
+ return;
+ }
+ if (enabled) {
+ sensorManager.registerListener(
+ orientationListener, orientationSensor, SensorManager.SENSOR_DELAY_FASTEST);
+ } else {
+ sensorManager.unregisterListener(orientationListener);
+ }
+ isOrientationListenerRegistered = enabled;
+ }
+
// Called on GL thread.
private void onSurfaceTextureAvailable(SurfaceTexture surfaceTexture) {
mainHandler.post(
diff --git a/library/ui/src/main/res/values/attrs.xml b/library/ui/src/main/res/values/attrs.xml
index 535bf320fb..e0a6b7faf4 100644
--- a/library/ui/src/main/res/values/attrs.xml
+++ b/library/ui/src/main/res/values/attrs.xml
@@ -77,8 +77,8 @@
+
-