web-dev-qa-db-ja.com

Androidで画面の向きをグローバルに強制するにはどうすればよいですか?

画面の回転を強制できるアプリはたくさんあります。アプリが明示的に別の向きで表示したい場合でも機能します。現在、加速度計の回転システムの設定を無効にして、優先する方向を設定しています。アプリはこれをオーバーライドできます。

以下は、アプリの要求された向きを上書きできるアプリの1つです。

https://play.google.com/store/apps/details?id=nl.fameit.rotate&hl=en

17
kagronick

これは、非表示のシステムダイアログを作成することで実行できます。その種のハックですが、動作するのに十分クレイジーです。

    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);
14
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;

WindowManager wm = (WindowManager) this.getSystemService(Service.WINDOW_SERVICE);
wm.addView(orientationChanger, orientationLayout);
orientationChanger.setVisibility(View.VISIBLE);

これに基づいてリリースしたアプリでの私の成功を確認できます: Force Dock Rotation

25
chrispaton

余談ですが、サポートされていないアプリで画面の向きを強制せずにグローバルに変更することもできます。 (私はこの質問がアプリの設定を上書きすることについてであることを知っていますが、これは依然として有用であり、ほとんどの場合関連情報です。)

  1. アクセスを許可 to システム設定(WRITE_SETTINGS AndroidManifest.xml内

    <uses-permission Android:name="Android.permission.WRITE_SETTINGS" />
    
  2. インポート Settings

    import Android.provider.Settings;
    
  3. Android画面の自動回転 が無効になっていることを確認します

    Settings.System.putInt(
        getContentResolver(),
        Settings.System.ACCELEROMETER_ROTATION,
        0
    );
    
  4. セットする - USER_ROTATION 希望する設定に変更します。これは ROTATION_定数 。これらの値は、デバイスの自然な向きからの画面の回転を表します。

    Settings.System.putInt(
        getContentResolver(),
        Settings.System.USER_ROTATION,
        Surface.ROTATION_0 //Or a different ROTATION_ constant
    );
    

USER_ROTATION アプリが実行されていない、またはアンインストールされている場合でも保持されます。私が正しく思い出した場合、ユーザーは自動回転を手動で無効または有効にすることでこの値をリセットできます。

13
Sam

システムビューを作成する

常に他のアプリケーションの上に表示される非表示の View を作成します。 View sは独自の方向設定を指定できるため、ビューの方向を使用して、基礎となるビューおよびアプリケーションの方向をオーバーライドできます。

オプション

これを実現するために使用できるいくつかの異なるビュータイプがあり、それぞれに独自の欠点があります。

  1. システムオーバーレイウィンドウ( TYPE_SYSTEM_OVERLAY

    SYSTEM_ALERT_WINDOW 許可。 (以下を AndroidManifest.xml に追加します。)

    <uses-permission Android:name="Android.permission.SYSTEM_ALERT_WINDOW" />
    
  2. トーストウィンドウ( TYPE_TOAST

    許可は不要です MIUI V8を除く

    一部のウィンドウタイプでは表示されないため、方向は影響を受けません。

指示

  1. View を作成します。
  2. WindowManager.LayoutParams
    1. type を上記で選択した値に設定します。
    2. その widthheight をゼロにすると、オーバーラップすると機能しないアプリケーションの問題を回避できます。 (たとえば、Androidでは、ウィンドウがその上にある場合に、アクセシビリティサービスを有効にしようとしたときに[OK]ボタンを押すことができません。)
    3. screenOrientation を任意の orientation value に設定します。

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();

短所

  • 私の経験では、アプリがクラッシュまたは強制終了された場合、ビューは保持される可能性があります。デバイスを再起動すると、この問題を回避できるようです。

参考文献

3
Sam