获取屏幕高度的代码
int getScreenHeight(Activity context) {
WindowManager wm = (WindowManager)context.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
return metrics.heightPixels;
}
问题现象
在Android N 7.0(SDK 24)上当,Activity进入过分屏模式再退出后,使用上面的代码去获取屏幕高度,得到的值是真正的屏幕高度减去状态栏的高度。然而在Android 7.1(SDK 25) 上,确没有这个问题,猜测是谷歌的BUG,在7.1上已经得到了修正。同时出问题的时候,传入的context是Activity,但是当我传入的是ApplicationContext时,返回的屏幕高度又是正确的,这就无语了。
问题原因
通过调试Android SDK 24和25的框架代码,发现出现问题的原因是,SDK 24的ActivityThread的performConfigurationChanged方法configuration没有正确地更新,但是SDK25做了修正。下面直接给出导致这个问题的框架代码:
Android 7.0
public final class ActivityThread {
...
private void performConfigurationChanged(...) {
...
boolean shouldChangeConfig = false;
if ((activity == null) || (activity.mCurrentConfig == null)) {
shouldChangeConfig = true;
} else {
// If the new config is the same as the config this Activity
// is already running with then don't bother calling
// onConfigurationChanged
int diff = activity.mCurrentConfig.diff(newConfig);
if (diff != 0) {
shouldChangeConfig = true;
}
}
...
}
Android 7.1
public final class ActivityThread {
...
private void performConfigurationChanged(...) {
...
boolean shouldChangeConfig = false;
if ((activity == null) || (activity.mCurrentConfig == null)) {
shouldChangeConfig = true;
} else {
// If the new config is the same as the config this Activity is already
// running with and the override config also didn't change, then don't
// bother calling onConfigurationChanged.
int diff = activity.mCurrentConfig.diff(newConfig);
if (diff != 0 || !mResourcesManager.isSameResourcesOverrideConfig(activityToken, amOverrideConfig)) {
// Always send the task-level config changes. For system-level configuration, if
// this activity doesn't handle any of the config changes, then don't bother
// calling onConfigurationChanged as we're going to destroy it.
if (!mUpdatingSystemConfig
|| (~activity.mActivityInfo.getRealConfigChanged() & diff) == 0
|| !reportToActivity) {
shouldChangeConfig = true;
}
}
}
...
}
比较这两块代码,可以发现 SDK25增加了!mResourcesManager.isSameResourcesOverrideConfig(activityToken, amOverrideConfig)这个条件来设置shouldChangeConfig的值。如果shouldChangeConfig那么Activity的configuration在退出分屏后会更新为未分屏之前的值。
解决方案
为了解决这个问题,只需要将context更换为ApplicationContext即可。