在android8.0设备发现一个问题,在androidManifest.xml中已配置了固定的屏幕方向,
但是在应用中,点击设备menu键,选择应用时,此时应用仍然可以旋转。

在MainActivity中通过代码设置 setRequestedOrientation时会报错:Only fullscreen activities can request orientation

原因是在android8.0 的Activity.java 的代码中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
protected void onCreate(@Nullable Bundle savedInstanceState) {
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);
if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState);

if (getApplicationInfo().targetSdkVersion >= O && mActivityInfo.isFixedOrientation()) {
final TypedArray ta = obtainStyledAttributes(com.android.internal.R.styleable.Window);
final boolean isTranslucentOrFloating = ActivityInfo.isTranslucentOrFloating(ta);
ta.recycle();

if (isTranslucentOrFloating) {
throw new IllegalStateException(
"Only fullscreen opaque activities can request orientation");
}
}

.......
}

如果sdk版本>O && 当前Activity的屏幕方向固定时,
判断当前主题样式,如果包含透明样式,则会抛出该异常。

很明显这段代码存在问题,sdk>=O其实就是android8.0(26)及以上。
而后面两个要求,固定屏幕方向在特定应用时很常见的,而透明样式页比较常见,
我们常用透明背景做一个简单的启动优化,避免其他样式导致的闪屏现象。

而这段代码也在8.0之后的版本修复,但是现在市面存在的手机在andorid8.0的时候基本都存在该问题。

修复方式时只能去除透明背景,但为了修复26存在的问题,修改应用整个的表现有些得不偿失。

所以我们可以针对特定版本修改资源。

首先去掉AndroidManifest.xml中的 android:screenOrientation 配置,

在res新增values-v26文件夹,这样在sdk26的手机就会在这个文件夹下寻找对应的资源,如果没有才会有主目录values中去找。

在values-v26中修改styles.xml,去掉此处的透明背景。

再在代码中调用setRequestedOrientation来固定屏幕

1
2
3
4
5
6
@Override
protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
}

此时则不会再报错,
也不存在之前所说的点击menu键,回到应用会旋转问题。