美文网首页Android异常
Android8.X异常之Only fullscreen opa

Android8.X异常之Only fullscreen opa

作者: 渐渐懂了吧 | 来源:发表于2020-06-30 18:43 被阅读0次

前言

这几天在Sentry上发现了1个从未见过的异常
java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
印象中从未遇到过这个问题,但也一时觉得莫名其妙,经过查证是只有Android8.X版本才会出现的bug,而且估计很少有人遇到,既然自己解决了也就把怎么解决的说一下。

bug.png

产生原因

简单来说满足3个条件时会报这个异常
1)当前Activity是否固定了方向,例如android:screenOrientation="portrait"
2)当前Activity的主题是否设置了如下的属性:
windowIsTranslucent为true
windowIsTranslucent为false,但windowSwipeToDismiss为true
windowIsFloating为true
3)项目的targetSdkVersion是否为26或27即Android8.X版本
当满足以上条件你又去打开那个Activity,这个bug就会如约而至

解决方案

这里就直接上代码吧

/**
 * 修复Android8.X存在的java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation问题
 * 在Activity中onCreate()中super之前调用
 *
 * @author yzt 2020/6/30
 */
public class ActivityOrientationHook {

    public static void hook(Activity activity) {
        if (activity == null)
            return;

        //目标版本8.X
        if (Build.VERSION.SDK_INT > Build.VERSION_CODES.N_MR1
                && Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
            if (isTranslucentOrFloating(activity)) {
                fixOrientation(activity);
            }
        }
    }

    /**
     * 检查屏幕是否固定,横竖屏或者锁定就是固定的
     */
    private static boolean isTranslucentOrFloating(Activity activity) {
        boolean isTranslucentOrFloating = false;
        try {
            Class<?> styleableClass = Class.forName("com.android.internal.R$styleable");
            Field WindowField = styleableClass.getDeclaredField("Window");
            WindowField.setAccessible(true);
            int[] styleableRes = (int[]) WindowField.get(null);
            //先获取到TypedArray
            final TypedArray typedArray = activity.obtainStyledAttributes(styleableRes);
            Class<?> ActivityInfoClass = ActivityInfo.class;
            //调用检查是否屏幕旋转
            Method isTranslucentOrFloatingMethod = ActivityInfoClass.getDeclaredMethod("isTranslucentOrFloating", TypedArray.class);
            isTranslucentOrFloatingMethod.setAccessible(true);
            isTranslucentOrFloating = (boolean) isTranslucentOrFloatingMethod.invoke(null, typedArray);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return isTranslucentOrFloating;
    }

    /**
     * 设置屏幕不固定,绕过检查
     */
    private static void fixOrientation(Activity activity) {
        try {
            Class<Activity> activityClass = Activity.class;
            Field mActivityInfoField = activityClass.getDeclaredField("mActivityInfo");
            mActivityInfoField.setAccessible(true);
            ActivityInfo activityInfo = (ActivityInfo) mActivityInfoField.get(activity);
            //设置屏幕不固定
            activityInfo.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

然后在对应的Activity中这么使用即可

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        ActivityOrientationHook.hook(this);
        super.onCreate(savedInstanceState);
    }

解决思路就是判断targetSdkVersion版本,如果为8.X版本则不固定方向,来达到规避这个异常的目的。由于这个问题在9.0及以上的版本已经解决,所以这里只要判断一下是否是8.X版本即可。

在此感谢

https://blog.csdn.net/na2609613672/article/details/89403053
https://www.jianshu.com/p/8328a586f9de

相关文章

网友评论

    本文标题:Android8.X异常之Only fullscreen opa

    本文链接:https://www.haomeiwen.com/subject/jmzxqktx.html