Only fullscreen opaque activities can request orientation

出现Only fullscreen opaque activities can request orientation是谷歌爸爸在安卓8.0版本时为了支持全面屏,增加了一个限制:如果是透明的Activity,则不能固定它的方向,因为它的方向其实是依赖其父Activity的(因为透明)。然而这个bug只有在8.0中有,8.1中已经修复。还有种原因是代码中手动取消App启动白屏或者黑屏的时候,将Splash界面设为了透明,然后这个时候又设置了方向为垂直,从而导致了这个问题。总结具体原因有两种:

1.Activity的风格为透明,在manifest文件中指定了一个方向,则在onCreate中崩溃

2.Activity的风格为透明,如果调用setRequestedOrientation方法固定方向,就会崩溃

解决方法

方法一:

1.找到你设置透明的Activity,然后在他的theme中将android:windowIsTranslucent改为false

即:false

2.再加入true就搞定了。

方法二:

        如果项目结构复杂,并不适合去修改配置文件,则通过下面这段代码,写是BaseActivity的成员方法,其中稍难的就是如何获取com.android.internal.R$styleable.Window这个stylable,记住$这个符号是等于代码中的“.”反射是需要写成$,stylable其实是R的内部类,获取到这个数组,就可以用反射调用ActivityInfo#isTranslucentOrFloating()这个方法了。

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;

    }

在onCreate的时候,先判断,如果透明,直接把方向改为SCREEN_ORIENTATION_UNSPECIFIED:

@Override

    protected void onCreate(Bundle savedInstanceState) {

        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating()) {

            boolean result = fixOrientation();

        }

        super.onCreate(savedInstanceState);

    }

    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;

    }

然后在重写setRequestedOrientation设置方向的时候如果透明,直接不执行:

@Override

    public void setRequestedOrientation(int requestedOrientation) {

        if (Build.VERSION.SDK_INT == Build.VERSION_CODES.O && isTranslucentOrFloating()) {

            return;

        }

        super.setRequestedOrientation(requestedOrientation);

    }

链接:https://www.jianshu.com/p/f26774dc0f2e
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

你可能感兴趣的:(Android,android)