java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation

java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation

背景

手机升级系统后,到了Android8.0,打开原来自己开发的一个app后,发现直接打不开,即闪退了。

只有全屏不透明的activity才可以设置横竖屏方向,半透明/对话框等不可设置横竖屏。

这个是SDK8.0的系统Bug,之后的版本已修复。

 

报错提示:java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation

产生这个错误的原因是因为清单配置文件中给这个 SplashActivity 设置了 Theme 为:

android:theme="@android:style/Theme.Translucent.NoTitleBar"

设置这个主题是为了解决 App启动白屏的问题。

但是Android8.0下,透明主题的Activity是不可以设置方向的,但是我又设置了方向,所以会引发这个异常。

给出我的清单配置文件图示:

在这里插入图片描述
可以看到我主题透明的同时也设置了方向。因此异常就产生了,直接闪退。

解决

一、去掉 android:screenOrientation="portrait"

1、为了横竖屏的切换,添加一个 values-26 的文件夹,存放针对 Android8.0 以上手机的 style.xml。

2、将theme中的android:windowIsTranslucent改为false  <item name="android:windowIsTranslucent">false</item>

3、再加入<item name="android:windowDisablePreview">true</item>就搞定了。

这样就解决掉进入程序闪退,和横竖屏正常切换的问题了。

二、但是如果有需求固定横屏或竖屏呢,很简单,在 Java/Kotlin 代码的 onCreate 中设置 

if (android.os.Build.VERSION.SDK_INT != Build.VERSION_CODES.O) {
        setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
 }
 

上面的是针对一个Activity的解决办法,如果想全局设置,可以在基类里面这样设置。

  1. 利用反射,修改mActivityInfo中的变量screenOrientation,设置成SCREEN_ORIENTATION_UNSPECIFIED
  2. 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;
    }

以上参考:https://www.cnblogs.com/ggband/p/11435912.html

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值