web-dev-qa-db-fra.com

Comment forcer globalement l'orientation de l'écran dans Android?

Un certain nombre d'applications sont capables de forcer la rotation de l'écran. Ils fonctionnent même si une application souhaite explicitement être visualisée dans une autre orientation. En ce moment, je désactive le réglage du système de rotation de l’accéléromètre et mon orientation préférée. Une application peut toujours remplacer cela.

Voici l'une des applications pouvant annuler l'orientation demandée d'une application:

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

15
kagronick

Cela peut être fait en créant un dialogue système caché. C'est une sorte de bidouille mais assez fou pour fonctionner.

    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);
13
kagronick

J'ai essayé la réponse de kagronick mais je n'ai pas réussi à la faire fonctionner. Après avoir déconné un peu, je l'ai finalement fait fonctionner en utilisant une fenêtre de superposition système et en retirant les LayoutParams que je trouvais inutiles. Voici ma solution éventuelle:

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

Vous pouvez voir mon succès dans l'application que j'ai publiée basée sur ceci: Force Dock Rotation .

22
chrispaton

Par ailleurs, vous pouvez également modifier globalement l'orientation de l'écran sans le forcer dans des applications non prises en charge. (Je sais que cette question concerne le dépassement des préférences des applications, mais cela reste utile et concerne principalement des informations pertinentes.)

  1. Accorder l'accès à paramètres système (WRITE_SETTINGS) dans AndroidManifest.xml

    <uses-permission Android:name="Android.permission.WRITE_SETTINGS" />
    
  2. Importer Settings

    import Android.provider.Settings;
    
  3. Assurer Rotation automatique de l'écran Android est désactivé

    Settings.System.putInt(
        getContentResolver(),
        Settings.System.ACCELEROMETER_ROTATION,
        0
    );
    
  4. Réglez USER_ROTATION sur le réglage souhaité, qui devrait être l’une des constantes ROTATION_ . Ces valeurs représentent les rotations d'écran à partir de l'orientation naturelle de l'appareil, qu'il s'agisse de paysage ou de portrait.

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

Notez que les modifications apportées à USER_ROTATION persistent même si votre application n'est pas en cours d'exécution ou est désinstallée. Si je me souviens bien, les utilisateurs peuvent réinitialiser cette valeur en désactivant et en activant manuellement la rotation automatique.

12
Sam

Créer une vue système

Créez une variable invisible View qui s'affiche toujours au-dessus des autres applications. View s peut spécifier ses propres préférences d'orientation. Ainsi, l'orientation de votre vue peut être utilisée pour remplacer les orientations des vues et des applications sous-jacentes.

Les options

Je connais quelques types de vues différents que vous pouvez utiliser pour y parvenir, chacun avec ses propres inconvénients.

  1. Fenêtre Superposition système ( TYPE_SYSTEM_OVERLAY )

    Nécessite l'autorisation SYSTEM_ALERT_WINDOW . (Ajoutez ce qui suit à AndroidManifest.xml .)

    <uses-permission Android:name="Android.permission.SYSTEM_ALERT_WINDOW" />
    
  2. Fenêtre Toast ( TYPE_TOAST )

    Aucune autorisation requise, sauf sur MIUI V8 .

    N'affiche pas sur certains types de fenêtres, ainsi leurs orientations pourraient ne pas être affectées:

Instructions

  1. Créez une View .
  2. Créez un WindowManager.LayoutParams .
    1. Définissez type sur la valeur que vous avez choisie ci-dessus.
    2. Remettez à zéro ses width et height pour éviter les problèmes liés aux applications qui ne fonctionneront pas en cas de chevauchement. (Par exemple, Android ne vous laissera pas appuyer sur le bouton "OK" lorsque vous essayez d'activer un service d'accessibilité si une fenêtre se trouve en haut de celui-ci.)
    3. Définissez sa screenOrientation sur n'importe laquelle valeur d'orientation vous voulez.

Exemple

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

Désavantages

  • D'après mon expérience, la vue pourrait persister si votre application se bloque ou est supprimée. Redémarrer l'appareil semble résoudre ce problème.

Références

2
Sam