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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章