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) {
//在onCreate的时候,先判断,如果透明,直接把方向改为SCREEN_ORIENTATION_UNSPECIFIED:
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;
}