Android: deshabilita temporalmente los cambios de orientación en una actividad

Mi actividad principal tiene algún código que hace algunos cambios en la base de datos que no deben interrumpirse. Estoy haciendo el trabajo pesado en otro hilo, y utilizando un diálogo de progreso que establecí como no cancelable. Sin embargo, me di cuenta de que si girar mi teléfono se reinicia la actividad que es muy malo para el proceso que se estaba ejecutando, y obtuve un cierre de la Fuerza.

Lo que quiero hacer es desactivar programaticamente los cambios de orientación de pantalla hasta que se complete mi proceso, momento en el que los cambios de orientación están habilitados.

Como explicó Chris en su auto-respuesta , llamando

setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); 

y entonces

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); 

Realmente funciona como el encanto … en dispositivos reales!

No pienses que se ha roto al probar en el emulador, el atajo ctrl + F11 SIEMPRE cambia la orientación de la pantalla, sin emular los movimientos de los sensores.

EDIT: esta no fue la mejor respuesta posible. Como se explica en los comentarios, hay problemas con este método. La verdadera respuesta está aquí .

Ninguna de las otras respuestas hizo el truco perfectamente para mí, pero aquí es lo que encontré que hace.

Bloquear la orientación a la corriente …

 if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); 

Al cambiar la orientación se debe permitir de nuevo, volver a la configuración predeterminada …

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 

Aquí hay una solución más completa y actualizada que funciona para la API 8+, funciona para retratos inversos y paisaje y funciona en una pestaña Galaxy donde la orientación "natural" es de paisaje (llamada activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED) para desbloquear la orientación):

 @SuppressWarnings("deprecation") @SuppressLint("NewApi") public static void lockActivityOrientation(Activity activity) { Display display = activity.getWindowManager().getDefaultDisplay(); int rotation = display.getRotation(); int height; int width; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) { height = display.getHeight(); width = display.getWidth(); } else { Point size = new Point(); display.getSize(size); height = size.y; width = size.x; } switch (rotation) { case Surface.ROTATION_90: if (width > height) activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); else activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; case Surface.ROTATION_180: if (height > width) activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); else activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; case Surface.ROTATION_270: if (width > height) activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); else activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; default : if (height > width) activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); else activity.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } } 

Encontré la respuesta. Para ello, en una Actividad puede llamar a setRequestedOrientation(int) con uno de los valores especificados aquí: http://developer.android.com/reference/android/R.attr.html#screenOrientation

Antes de patear mi hilo llamé a setRequestedOrientation(OFF) (OFF = nosensor) y cuando el hilo se hizo llamé setRequestedOrientation(ON) (ON = sensor). Funciona de maravilla.

Para manejar también los modos de orientación inversa, he utilizado ese código para fijar la orientación de la actividad:

 int rotation = getWindowManager().getDefaultDisplay().getRotation(); switch(rotation) { case Surface.ROTATION_180: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; case Surface.ROTATION_270: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; case Surface.ROTATION_0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; case Surface.ROTATION_90: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; } 

Y para permitir de nuevo la orientación:

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 

Gracias a todos. He modificado la solución Pilot_51, para asegurarme de restaurar el estado anterior. También lancé un cambio para apoyar las pantallas que no son de paisaje y no de retrato (pero no las he probado en tal pantalla).

 prevOrientation = getRequestedOrientation(); if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } else if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_NOSENSOR); } 

Luego para restaurarlo

 setRequestedOrientation(prevOrientation); 

Utilice setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); Para bloquear la orientación actual, ya sea horizontal o vertical.

Utilice setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); Para desbloquear la orientación.

Aquí hay una solución que funciona cada vez y conserva la orientación actual (utilizando Activity.Info.SCREEN_ORIENTATION_PORTRAIT establece a 0 ° por ejemplo, pero el usuario puede tener una orientación de 180 ° como actual).

 // Scope: Activity private void _lockOrientation() { if (super.getResources().getConfiguration().orientation == Configuration.ORIENTATION_PORTRAIT) { super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT); } else { super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE); } } private void _unlockOrientation() { super.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); } 
 protected void setLockScreenOrientation(boolean lock) { if (Build.VERSION.SDK_INT >= 18) { setRequestedOrientation(lock?ActivityInfo.SCREEN_ORIENTATION_LOCKED:ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); return; } if (lock) { switch (getWindowManager().getDefaultDisplay().getRotation()) { case 0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; // value 1 case 2: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; // value 9 case 1: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; // value 0 case 3: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; // value 8 } } else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_FULL_SENSOR); // value 10 } 

Esto funciona prefecto para mí. Resuelve el problema con diversa "orientación natural" de la tableta / del teléfono;)

 int rotation = getWindowManager().getDefaultDisplay().getRotation(); Configuration config = getResources().getConfiguration(); int naturalOrientation; if (((rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_180) && config.orientation == Configuration.ORIENTATION_LANDSCAPE) || ((rotation == Surface.ROTATION_90 || rotation == Surface.ROTATION_270) && config.orientation == Configuration.ORIENTATION_PORTRAIT)) { naturalOrientation = Configuration.ORIENTATION_LANDSCAPE; } else { naturalOrientation = Configuration.ORIENTATION_PORTRAIT; } // because getRotation() gives "rotation from natural orientation" of device (different on phone and tablet) // we need to update rotation variable if natural orienation isn't 0 (mainly tablets) if (naturalOrientation == Configuration.ORIENTATION_LANDSCAPE) rotation = ++rotation % 4; switch (rotation) { case Surface.ROTATION_0: //0 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; case Surface.ROTATION_90: //1 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; case Surface.ROTATION_180: //2 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); break; case Surface.ROTATION_270: //3 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; } } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); } 

Utilice ActivityInfo.SCREEN_ORIENTATION_USER si desea girar la pantalla sólo si está activada en el dispositivo.

He llegado con una solución que depende de la rotación de la pantalla y luego decide la orientación del dispositivo. De conocer la orientación podemos bloquear la orientación y liberarla más tarde cuando sea necesario. Esta solución también puede determinar si el dispositivo en el modo de paisaje reverso .

 private void lockOrientation(){ switch (((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation()) { // Portrait case Surface.ROTATION_0: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; //Landscape case Surface.ROTATION_90: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); break; // Reversed landscape case Surface.ROTATION_270: setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); break; } } 

Luego, si necesitamos liberar la orientación, podemos llamar a este método:

 setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); 

Creo que este código es más fácil de leer.

 private void keepOrientation() { int orientation = getResources().getConfiguration().orientation; int rotation = getWindowManager().getDefaultDisplay().getRotation(); switch (rotation) { case Surface.ROTATION_0: if (orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } break; case Surface.ROTATION_90: if (orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } break; case Surface.ROTATION_180: if (orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); } break; default: if (orientation == Configuration.ORIENTATION_PORTRAIT) { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); } else { setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE); } } } 

He encontrado que una combinación de valores de rotación / orientación existentes son necesarios para cubrir las cuatro posibilidades; Hay los valores de retrato / paisaje y la orientación natural del dispositivo. Digamos que la orientación natural de los dispositivos tendrá un valor de rotación de 0 grados cuando la pantalla está en su orientación "natural" vertical u horizontal. Del mismo modo, habrá un valor de rotación de 90 grados cuando está en el paisaje o el retrato (observe que es opuesto a la orientación @ 0 grados). Por lo tanto, los valores de rotación que no sean 0 o 90 grados implicarán orientación "Inversa". Ok, he aquí un código:

 public enum eScreenOrientation { PORTRAIT (ActivityInfo.SCREEN_ORIENTATION_PORTRAIT), LANDSCAPE (ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE), PORTRAIT_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_PORTRAIT), LANDSCAPE_REVERSE (ActivityInfo.SCREEN_ORIENTATION_REVERSE_LANDSCAPE), UNSPECIFIED_ORIENTATION (ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED); public final int activityInfoValue; eScreenOrientation ( int orientation ) { activityInfoValue = orientation; } } public eScreenOrientation currentScreenOrientation ( ) { final int rotation = ((WindowManager) getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay().getRotation(); final int orientation = getResources().getConfiguration().orientation; switch ( orientation ) { case Configuration.ORIENTATION_PORTRAIT: if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 ) return eScreenOrientation.PORTRAIT; else return eScreenOrientation.PORTRAIT_REVERSE; case Configuration.ORIENTATION_LANDSCAPE: if ( rotation == Surface.ROTATION_0 || rotation == Surface.ROTATION_90 ) return eScreenOrientation.LANDSCAPE; else return eScreenOrientation.LANDSCAPE_REVERSE; default: return eScreenOrientation.UNSPECIFIED_ORIENTATION; } } public void lockScreenOrientation ( ) throws UnsupportedDisplayException { eScreenOrientation currentOrientation = currentScreenOrientation( ); if ( currentOrientation == eScreenOrientation.UNSPECIFIED_ORIENTATION ) throw new UnsupportedDisplayException("Unable to lock screen - unspecified orientation"); else setRequestedOrientation( currentOrientation.activityInfoValue ); } public void unlockScreenOrientation ( ) { setRequestedOrientation( ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED ); } 

No me gustó la mayoría de las respuestas aquí, ya que en el desbloqueo que lo puso a UNSPECIFIED en contraposición al estado anterior. ProjectJourneyman lo tuvo en cuenta, lo cual fue genial, pero preferí el código de bloqueo de Roy. Por lo tanto, mi recomendación sería una mezcla de los dos:

 private int prevOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED; private void unlockOrientation() { setRequestedOrientation(prevOrientation); } @SuppressWarnings("deprecation") @SuppressLint("NewApi") private void lockOrientation() { prevOrientation = getRequestedOrientation(); Display display = getWindowManager().getDefaultDisplay(); int rotation = display.getRotation(); int height; int width; if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR2) { height = display.getHeight(); width = display.getWidth(); } else { Point size = new Point(); display.getSize(size); height = size.y; width = size.x; } switch (rotation) { case Surface.ROTATION_90: if (width > height) setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); else setRequestedOrientation(9/* reversePortait */); break; case Surface.ROTATION_180: if (height > width) setRequestedOrientation(9/* reversePortait */); else setRequestedOrientation(8/* reverseLandscape */); break; case Surface.ROTATION_270: if (width > height) setRequestedOrientation(8/* reverseLandscape */); else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); break; default : if (height > width) setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); else setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); } } 

Puedes usar

 public void swapOrientaionLockState(){ try{ if (Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 1) { Display defaultDisplay = ((WindowManager) mContext.getSystemService(Context.WINDOW_SERVICE)).getDefaultDisplay(); Settings.System.putInt(mContext.getContentResolver(), Settings.System.USER_ROTATION, defaultDisplay.getRotation()); Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 0); } else { Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, 1); } Settings.System.putInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION, !orientationIsLocked() ? 1 : 0); } catch (Settings.SettingNotFoundException e){ e.printStackTrace(); } } public boolean orientationIsLocked(){ if(canModifiSetting(mContext)){ try { return Settings.System.getInt(mContext.getContentResolver(), Settings.System.ACCELEROMETER_ROTATION) == 0; } catch (Settings.SettingNotFoundException e) { e.printStackTrace(); } } return false; } public static boolean canModifiSetting(Context context){ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { return Settings.System.canWrite(context); } else { return true; } } 

Usar esa línea de código

 this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT); 

En su actividad en el método de creación

  • ¿Cómo detectar el paisaje izquierdo (normal) contra el derecho del paisaje (reverso) con la ayuda para los dispositivos naturales del paisaje?
  • Cómo utilizar SensorManager.getOrientation () en lugar de TYPE_ORIENTATION
  • Android Compass orientación en poco fiable (filtro de paso bajo)
  • Android onConfigurationChanged () no se llama en Actividad
  • Orientación de la pantalla de Android al sensor
  • ¿Diferencia entre sensor de orientación y sensor de campo magnético en Android?
  • IScroll no funciona en android a menos que realice un cambio de orientación y regrese
  • FragmentActivity con ViewPager: Crash en el cambio de orientación
  • Cómo habilitar sólo retratos y retratos en los teléfonos, "sensorPortrait" no funciona en los teléfonos?
  • Forzar el vídeo para que se reproduzca en Orientación vertical sólo con MediaPlayer y VideoView
  • Android: orientación / rotación de la pantalla para la vista previa de la cámara
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.