如何强制全屏视频随屏幕旋转?Amazon Fire TV Stick适配问题
问题描述
我在实现设备屏幕旋转功能时,遇到了Amazon Fire TV Stick特有的问题:除该设备外,其他测试设备上代码运行正常,屏幕能完成旋转,但YouTube、Netflix等流媒体应用的全屏视频仍保持默认方向——比如YouTube界面已经倒置,但视频本身还是默认方向。
相关代码如下:
private WindowManager.LayoutParams mainLayoutParams; private TextView fakeTextView; private WindowManager windowManager; private static final int OVERLAY_FLAGS = FLAG_NOT_FOCUSABLE | FLAG_KEEP_SCREEN_ON | FLAG_DISMISS_KEYGUARD | FLAG_TURN_SCREEN_ON | FLAG_SHOW_WHEN_LOCKED | FLAG_NOT_TOUCHABLE | FLAG_WATCH_OUTSIDE_TOUCH; @Override public void onCreate() { super.onCreate(); LogUtils.dTag("NotificationDebug", "onCreate from notification"); createNotificationChannel(); mainLayoutParams = new WindowManager.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT, (Build.VERSION.SDK_INT >= 26) ? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY : WindowManager.LayoutParams.TYPE_PHONE, OVERLAY_FLAGS, PixelFormat.TRANSLUCENT); fakeTextView = new TextView(this); windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE); WindowManager.LayoutParams layoutParams = mainLayoutParams; layoutParams.x = 0; layoutParams.y = 0; layoutParams.gravity = Gravity.CENTER; windowManager.addView(fakeTextView, layoutParams); } @Override public int onStartCommand(Intent intent, int flags, int startId) { String orientationType = intent.getStringExtra("NEW_ORIENT_STRING_INTENT_EXTRA_KEY"); if (orientationType != null) if (orientationType.equalsIgnoreCase("landscape")) { mainLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; } else if (orientationType.equalsIgnoreCase("portrait")) { mainLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; } else if (orientationType.equalsIgnoreCase("landscape_reverse")) { mainLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; } else if (orientationType.equalsIgnoreCase("portrait_reverse")) { mainLayoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; } windowManager.updateViewLayout(fakeTextView, mainLayoutParams); return START_STICKY; }
解决方案
问题根源
当前方案通过添加全屏透明Overlay视图、修改其screenOrientation来强制旋转,但Fire TV上的流媒体应用(如YouTube、Netflix)可能直接调用底层显示服务处理视频渲染,不受WindowManager的Overlay方向控制,导致界面旋转但视频内容保持原方向。
需要改用系统级屏幕旋转控制,直接修改系统显示方向,才能覆盖所有应用(包括流媒体视频)的渲染方向。
1. 申请必要权限
在AndroidManifest.xml中添加WRITE_SETTINGS权限,用于修改系统显示设置:
<uses-permission android:name="android.permission.WRITE_SETTINGS" android:required="false" />
2. 替换为系统级旋转控制代码
删除原有的Overlay相关逻辑,改用以下代码控制屏幕旋转:
private void setSystemOrientation(int orientation) { ContentResolver resolver = getContentResolver(); // Android 6.0+ 需要引导用户授权WRITE_SETTINGS权限 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !Settings.System.canWrite(this)) { Intent intent = new Intent(Settings.ACTION_MANAGE_WRITE_SETTINGS); intent.setData(Uri.parse("package:" + getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); return; } // 根据目标方向设置系统旋转参数 switch (orientation) { case ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE: Settings.System.putInt(resolver, Settings.System.USER_ROTATION, Surface.ROTATION_0); break; case ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE: Settings.System.putInt(resolver, Settings.System.USER_ROTATION, Surface.ROTATION_180); break; case ActivityInfo.SCREEN_ORIENTATION_PORTRAIT: Settings.System.putInt(resolver, Settings.System.USER_ROTATION, Surface.ROTATION_270); break; case ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT: Settings.System.putInt(resolver, Settings.System.USER_ROTATION, Surface.ROTATION_90); break; } }
3. 修改onStartCommand逻辑
替换原有的Overlay更新逻辑,调用新的系统旋转方法:
@Override public int onStartCommand(Intent intent, int flags, int startId) { String orientationType = intent.getStringExtra("NEW_ORIENT_STRING_INTENT_EXTRA_KEY"); if (orientationType != null) { int targetOrientation = -1; switch (orientationType.toLowerCase()) { case "landscape": targetOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE; break; case "portrait": targetOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT; break; case "landscape_reverse": targetOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE; break; case "portrait_reverse": targetOrientation = ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT; break; } if (targetOrientation != -1) { setSystemOrientation(targetOrientation); } } return START_STICKY; }
4. 清理Overlay代码
删除onCreate中与fakeTextView、WindowManager Overlay相关的所有代码,不需要再创建透明覆盖视图。
原理说明
通过修改系统USER_ROTATION设置,直接改变整个屏幕的物理显示方向,所有应用(包括流媒体视频的渲染层)都会跟随这个系统级方向旋转,从根源解决Fire TV上视频不跟随旋转的问题。
内容的提问来源于stack exchange,提问作者user7954210
相关产品推荐
相关产品推荐

