当Android当activity同时满足以下三个条件,会出现闪退当问题
1.Android系统8.0
2.透明主题
3.固定屏幕方向,screenOrientation的值为portrait 或者 landscape(代码或者清单文件)
错误信息:java.lang.IllegalStateException: Only fullscreen activities can request orientation
解决方案:
1.最暴力到方法就是回退sdk版本,sdk 26及以下
2.去除主题中的透明属性
例如:将android:windowIsTranslucent设置为false
3.指定除8.0以外的系统固定屏幕方向:
去掉清单文件中screenOrientation属性,activity中onCreate中执行屏幕方向固定的代码
if (android.os.Build.VERSION.SDK_INT != android.os.Build.VERSION_CODES.O) {
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
//setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
}
4.如果你前一个页面和需要透明主题的界面屏幕方向一致,我们只需要在清单文件中配置android:screenOrientation="behind",behind的意思就是和之前页面的屏幕方向保持一致。
5.通过反射,让系统绕过屏幕方向的检测,设置屏幕不固定
/**
* @description: 修复android 8报错:Only fullscreen opaque activities can request orientation
* 透明主题的 Activity,一般在以下2个场景中会出现闪退:
*
* 1、在 AndroidManfest.xml 中有 android:screenOrientation="portrait" 之类的配置;
* 2、代码中调用 setRequestedOrientation(int orientation) 方法设置横竖屏方向;
*
* @date :2022/10/27 14:43
*/
public class FixAndroid8FixOrientationBug {
/**
* 在activity onCreate中调用,且早于父类的onCreate调用
* @param act
*/
public static void needFixAndroid8Bug(Activity act) {
//如果是8.0系统的手机,并且认为是透明或者悬浮主题的Activity
if (Build.VERSION.SDK_INT == 26 && isTranslucentOrFloating(act)) {
//通过反射取消方向的设置,这样绕开系统的检查,避免闪退
fixOrientation(act);
}
}
//通过反射判断是否是透明页面
private static boolean isTranslucentOrFloating(Activity act) {
boolean isTranslucentOrFloating = false;
try {
int[] styleableRes = (int[]) Class.forName("com.android.internal.R$styleable").getField("Window").get(null);
final TypedArray ta = act.obtainStyledAttributes(styleableRes);
Method m = ActivityInfo.class.getMethod("isTranslucentOrFloating", TypedArray.class);
m.setAccessible(true);
isTranslucentOrFloating = (boolean) m.invoke(null, ta);
m.setAccessible(false);
} catch (Throwable e) {
e.printStackTrace();
}
return isTranslucentOrFloating;
}
//通过反射将方向设置为 SCREEN_ORIENTATION_UNSPECIFIED,绕开系统的检查
private static boolean fixOrientation(Activity act) {
try {
Field field = Activity.class.getDeclaredField("mActivityInfo");
field.setAccessible(true);
ActivityInfo o = (ActivityInfo) field.get(act);
o.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
field.setAccessible(false);
return true;
} catch (Throwable e) {
e.printStackTrace();
}
return false;
}
}