背景
2018年7月18日上午,電信終端產業協會(TAF)釋出《移動應用軟體高API等級預置與分發自律公約》(以下簡稱《公約》)。OPPO、華為、百度、360、阿里、小米、VIVO、騰訊作為發起單位,共同簽署《公約》併發出聯合倡議:號召廣大移動應用軟體預置與分發服務提供者,拒絕上架並及時更新低API等級的應用,共同維護使用者權益。《公約》規定,自2019年5月1日起,新上架和預置應用應基於Android 8.0 (API等級26)及以上開發。自2019年8月1日起,現有應用的更新應基於Android 8.0 (API等級26)及以上開發。
老專案開始做高版本的適配,這不將targetSDK版本改為最新的28,問題不斷,這裡特地做個記錄
異常日誌
Caused by: java.lang.IllegalStateException: Only fullscreen opaque activities can request orientation
at android.app.Activity.onCreate(Activity.java:1081)
at android.support.v4.app.BaseFragmentActivityDonut.onCreate(BaseFragmentActivityDonut.java:39)
at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:278)
at com.seeyon.mobile.android.model.gesture.activity.BaseGuestureActivity.onCreate(BaseGuestureActivity.java:31)
at com.seeyon.mobile.android.model.base.BaseActivity.onCreate(BaseActivity.java:83)
at com.seeyon.mobile.android.model.base.ActionBarBaseActivity.onCreate(ActionBarBaseActivity.java:61)
at com.seeyon.mobile.android.model.flow.FlowSearchActivity.onCreate(FlowSearchActivity.java:53)
at android.app.Activity.performCreate(Activity.java:7372)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1218)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:3147)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:3302)
at android.app.ActivityThread.-wrap12(Unknown Source:0)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1891)
at android.os.Handler.dispatchMessage(Handler.java:108)
at android.os.Looper.loop(Looper.java:166)
at android.app.ActivityThread.main(ActivityThread.java:7425)
at java.lang.reflect.Method.invoke(Native Method)
複製程式碼
首先這是google的一個bug,別等修復了,現在9.0了還是有問題。
原始碼
//Need to pay attention mActivityInfo.isFixedOrientation() and ActivityInfo.isTranslucentOrFloating(ta)
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();
//Exception occurred
if (isTranslucentOrFloating) {
throw new IllegalStateException(
"Only fullscreen opaque activities can request orientation");
}
}
複製程式碼
從上述程式碼,不難看出報錯的原因,就是 isTranslucentOrFloating 的activity不能是固定orientation的
* Returns true if the activity's orientation is fixed.
* @hide
*/
public boolean isFixedOrientation() {
return isFixedOrientationLandscape() || isFixedOrientationPortrait()
|| screenOrientation == SCREEN_ORIENTATION_LOCKED;
}
/**
* Returns true if the activity's orientation is fixed to portrait.
* @hide
*/
boolean isFixedOrientationPortrait() {
return isFixedOrientationPortrait(screenOrientation);
}
/**
* Returns true if the activity's orientation is fixed to portrait.
* @hide
*/
public static boolean isFixedOrientationPortrait(@ScreenOrientation int orientation) {
return orientation == SCREEN_ORIENTATION_PORTRAIT
|| orientation == SCREEN_ORIENTATION_SENSOR_PORTRAIT
|| orientation == SCREEN_ORIENTATION_REVERSE_PORTRAIT
|| orientation == SCREEN_ORIENTATION_USER_PORTRAIT;
}
/**
* Determines whether the {@link Activity} is considered translucent or floating.
* @hide
*/
public static boolean isTranslucentOrFloating(TypedArray attributes) {
final boolean isTranslucent = attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsTranslucent, false);
final boolean isSwipeToDismiss = !attributes.hasValue(com.android.internal.R.styleable.Window_windowIsTranslucent)
&& attributes.getBoolean(com.android.internal.R.styleable.Window_windowSwipeToDismiss, false);
final boolean isFloating = attributes.getBoolean(com.android.internal.R.styleable.Window_windowIsFloating, false);
return isFloating || isTranslucent || isSwipeToDismiss;
}
複製程式碼
從上面的原始碼中可以知道,解決問題的方法
解決方法
- 不固定方向
比如去除 android:screenOrientation="portrait",或者不呼叫設定方向的程式碼
-
isTranslucentOrFloating 返回false
只有android:windowIsTranslucent
<item name="android:windowIsTranslucent">false</item>
複製程式碼
若同時還有windowIsFloating
複製程式碼
<item name="android:windowIsTranslucent">false</item>
<item name="android:windowIsFloating">false</item>
複製程式碼
總結:
這個改動的目的是想阻止非全屏的Activity鎖定螢幕旋轉,因為當前Activity是透明的,浮動的或可滑動取消的,是否鎖屏應該由全屏的Activity決定,而不是並沒有全部佔據螢幕的Activity決定。