google出于安全的考虑,对android8.0以后的版本做的处理,当一个Activity固定方向并且是透明的,在8.0以后的版本中就会抛出异常:
java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
异常抛出条件如下:
ActivityInfo.isFixedOrientation(requestedOrientation) —— 表示判断当前的|Activity是否固定了方向
fullscreen —— 表示Activity是否是透明的或者是否悬浮在Activity上,是透明的或者悬浮在Activity上fullscreen就等于false
appInfo.targetSdkVersion >= O —— 表示版本号大于等于26
解决方法
- 利用反射,修改mActivityInfo中的变量screenOrientation,设置成SCREEN_ORIENTATION_UNSPECIFIED
- override setRequestedOrientation方法,直接return
@Override protected void onCreate(Bundle savedInstanceState) { if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating()) { boolean result = fixOrientation(); XLog.i(XLog.BASE, "onCreate fixOrientation when Oreo, result = " + result); } super.onCreate(savedInstanceState); } @Override public void setRequestedOrientation(int requestedOrientation) { if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating()) { XLog.i(XLog.BASE, "avoid calling setRequestedOrientation when Oreo."); return; } super.setRequestedOrientation(requestedOrientation); } private boolean isTranslucentOrFloating(){ boolean isTranslucentOrFloating = false; try { int [] styleableRes = (int[]) Class.forName("com.android.internal.R$styleable").getField("Window").get(null); final TypedArray ta = obtainStyledAttributes(styleableRes); Method m = ActivityInfo.class.getMethod("isTranslucentOrFloating", TypedArray.class); m.setAccessible(true); isTranslucentOrFloating = (boolean)m.invoke(null, ta); m.setAccessible(false); } catch (Exception e) { e.printStackTrace(); } return isTranslucentOrFloating; } private boolean fixOrientation(){ try { Field field = Activity.class.getDeclaredField("mActivityInfo"); field.setAccessible(true); ActivityInfo o = (ActivityInfo)field.get(this); o.screenOrientation = -1; field.setAccessible(false); return true; } catch (Exception e) { e.printStackTrace(); } return false; }