Create a system view
Create an invisible View
that always displays on top of other applications. View
s can specify their own orientation preferences, so your view's orientation can be used to override the orientations of underlying views and applications.
Options
I'm aware of a couple of different view types that you can use to achieve this, each with its own disadvantages.
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:
Instructions
- Create a
View
.
- Create a
WindowManager.LayoutParams
.
- Set
type
to value you chose above.
- Zero its
width
and height
to prevent problems with applications that won't function when overlapped. (For example, Android won't let you press the "OK" button when you try to enable an accessibility service if a window is on top of it.)
- Set its
screenOrientation
to whichever orientation value you want.
Example
Implementation
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;
}
}
Usage
ScreenOrientationEnforcer screenOrientationEnforcer
= new ScreenOrientationEnforcer(context);
//Force screen orientation
screenOrientationEnforcer.start();
//Stop forcing screen orientation
screenOrientationEnforcer.stop();
Disadvantages
- From my experience, the view might persist if your app crashes or is killed. Restarting the device seems to work around this.
References