您的当前位置:首页正文

Android N获取屏幕高度的问题

2022-06-15 来源:知库网

获取屏幕高度的代码

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即可。

显示全文