有许多应用程序可以强制屏幕旋转,即使某个应用显式要求以另一种方向查看也能起作用。现在我正在禁用加速度计旋转系统设置并设置我的首选方向,但是某些应用仍然可以覆盖这个设置。
这是其中一个可以覆盖应用请求方向的应用:
https://play.google.com/store/apps/details?id=nl.fameit.rotate&hl=en
有许多应用程序可以强制屏幕旋转,即使某个应用显式要求以另一种方向查看也能起作用。现在我正在禁用加速度计旋转系统设置并设置我的首选方向,但是某些应用仍然可以覆盖这个设置。
这是其中一个可以覆盖应用请求方向的应用:
https://play.google.com/store/apps/details?id=nl.fameit.rotate&hl=en
我尝试了kagronick的方法但无法使其工作。经过一段时间的摸索,我最终使用了一个系统覆盖窗口,并删除了我发现全都是不必要的LayoutParams,最终找到了解决方案:
orientationChanger = new LinearLayout(this);
// Using TYPE_SYSTEM_OVERLAY is crucial to make your window appear on top
// You'll need the permission android.permission.SYSTEM_ALERT_WINDOW
WindowManager.LayoutParams orientationLayout = new WindowManager.LayoutParams(WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY, 0, PixelFormat.RGBA_8888);
// Use whatever constant you need for your desired rotation
orientationLayout.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_SENSOR;
// Optional: Replace "Context" with "Service" when used in a service
WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
wm.addView(orientationChanger, orientationLayout);
orientationChanger.setVisibility(View.VISIBLE);
你可以在我发布的这个应用中看到我的成功:Force Dock Rotation。这可以通过创建一个隐藏的系统对话框来实现。虽然有点小技巧,但足够疯狂以使其奏效。
wm = (WindowManager) content.getSystemService(Service.WINDOW_SERVICE);
orientationChanger = new LinearLayout(content);
orientationChanger.setClickable(false);
orientationChanger.setFocusable(false);
orientationChanger.setFocusableInTouchMode(false);
orientationChanger.setLongClickable(false);
orientationLayout = new WindowManager.LayoutParams(
LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT,
windowType, WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
| WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE,
PixelFormat.RGBA_8888);
wm.addView(orientationChanger, orientationLayout);
orientationChanger.setVisibility(View.GONE);
orientationLayout.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
wm.updateViewLayout(orientationChanger, orientationLayout);
orientationChanger.setVisibility(View.VISIBLE);
windowType = LayoutParams.TYPE_APPLICATION_OVERLAY
时才能正常工作 :) - JBSnorroGrant access to system settings (WRITE_SETTINGS
) in AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
Import Settings
import android.provider.Settings;
Ensure Android screen auto-rotation is disabled
Settings.System.putInt(
getContentResolver(),
Settings.System.ACCELEROMETER_ROTATION,
0
);
Set USER_ROTATION
to the desired setting, which should be one of the ROTATION_
constants. These values represent screen rotations from the device's natural orientation, which could be either landscape or portrait.
Settings.System.putInt(
getContentResolver(),
Settings.System.USER_ROTATION,
Surface.ROTATION_0 //Or a different ROTATION_ constant
);
USER_ROTATION
的更改仍将持续存在。如果我没记错的话,用户可以通过手动禁用和启用自动旋转来重置此值。创建一个不可见的 View
,它始终显示在其他应用程序之上。 View
可以指定自己的方向偏好,因此您的视图方向可以用于覆盖底层视图和应用程序的方向。
我意识到有几种不同的视图类型可以用来实现这一点,每种类型都有其自身的缺点。
System Overlay window (TYPE_SYSTEM_OVERLAY
)
Requires the SYSTEM_ALERT_WINDOW
permission. (Add the following to AndroidManifest.xml.)
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
Toast window (TYPE_TOAST
)
No permission required, except on MIUI V8.
Doesn't display over some window types, so their orientations mightn't be affected:
TYPE_PRIORITY_PHONE
)TYPE_DREAM
)TYPE_KEYGUARD_DIALOG
, TYPE_KEYGUARD_SCRIM
)View
。WindowManager.LayoutParams
。
type
设置为您上面选择的值。width
和height
设置为零,以防止与不支持重叠窗口的应用程序发生问题。(例如, 当您尝试启用无障碍服务时,如果有一个窗口位于"确定"按钮之上,则Android将不允许您按下该按钮。)screenOrientation
设置为您想要的任何屏幕方向值。public class ScreenOrientationEnforcer {
private final View view;
private final WindowManager windows;
public ScreenOrientationEnforcer(Context context) {
windows = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
view = new View(context);
}
public void start() {
WindowManager.LayoutParams layout = generateLayout();
windows.addView(view, layout);
view.setVisibility(View.VISIBLE);
}
public void stop() {
windows.removeView(view);
}
private WindowManager.LayoutParams generateLayout() {
WindowManager.LayoutParams layoutParams = new WindowManager.LayoutParams();
//So we don't need a permission or activity
//Note that this won't work on some devices running MIUI
layoutParams.type = WindowManager.LayoutParams.TYPE_TOAST;
//Just in case the window type somehow doesn't enforce this
layoutParams.flags =
WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
| WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
//Prevents breaking apps that detect overlying windows enabling
//(eg UBank app, or enabling an accessibility service)
layoutParams.width = 0;
layoutParams.height = 0;
//Try to make it completely invisible
layoutParams.format = PixelFormat.TRANSPARENT;
layoutParams.alpha = 0f;
//The orientation to force
layoutParams.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE;
return layoutParams;
}
}
ScreenOrientationEnforcer screenOrientationEnforcer
= new ScreenOrientationEnforcer(context);
//Force screen orientation
screenOrientationEnforcer.start();
//Stop forcing screen orientation
screenOrientationEnforcer.stop();
PhoneWindowManager.windowTypeToLayerLw
PhoneWindowManager.checkAddPermission