最近遇到一个奇怪的bug。就是:
当targetSdk>=27 并且android SDK版本是26(Android 8.0.0)或者27(Android 8.1.0)时,此时在应用中,如果把一个Activity的主题设置为透明并且屏幕方向固定时,就会crash,如下:
java.lang.IllegalStateException:Only fullscreen activities can request orientation
现已查明,此为Android 8.0.0 和Android 8.1.0的bug(Android 9已修改)。
具体源码如下:
protected void onCreate(@Nullable Bundle savedInstanceState) { if (DEBUG_LIFECYCLE) Slog.v(TAG, "onCreate " + this + ": " + savedInstanceState); if (getApplicationInfo().targetSdkVersion >= O_MR1 && 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"); } }
Android 9已去掉此段代码,证明在Android 9已修复此bug。
如何产生此bug ?举例如下:
比如对Activity设置了主题:android:theme="@android:style/Theme.Translucent.NoTitleBar"
又设置了固定方向:android:screenOrientation="portrait"
或者在代码中设置的固定方向:setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
此时,就会报crash :
java.lang.IllegalStateException:Only fullscreen activities can request orientation
解决方案:
第一种:让主题透明Translucent 和Activity 固定方向不要同时存在。
第二种:设置targetSdk < 27
第三种:android:screenOrientation="behind" (如果你上一个Activity的方向是portrait,那么你把当前Activity设置为behind后,behind的意思是方向跟随上一个打开自己的Activity)
如果采用第一种方案修改,代码判断如下:
if (activity.getApplicationInfo().targetSdkVersion >= 27 && (Build.VERSION.SDK_INT == 26 || Build.VERSION.SDK_INT == 27)) { //ToDoSomething }
此bug 是典型的谷歌程序员的bug ,凭什么不让开发者设置透明和固定方向同时存在?唉,谷歌大爷犯了这个错,咱们开发者也没办法,只能去适配。