You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android跨API版本获取宽高仍遇废弃警告:问题排查与解决

问题:区分API版本实现屏幕宽高获取仍收到废弃警告,如何解决?

我参考Stack Overflow相关问题后,编写了适配Android API level >=30和API level <30的屏幕宽高获取代码,代码如下:

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val backgroundThread = Thread {

            val metric: WindowMetrics
            val insets: Insets    // An Insets instance holds four integer offsets which describe changes to the four edges of a Rectangle.
            val displayMetrics: DisplayMetrics
            val width: Int
            val height: Int
            val insetsWidth: Int
            val insetsHeight: Int

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {

                // Code for API level 30 and higher

                metric = windowManager.currentWindowMetrics
                insets = windowManager.currentWindowMetrics.windowInsets.getInsetsIgnoringVisibility (WindowInsets.Type.navigationBars() or WindowInsets.Type.displayCutout ())

                insetsWidth = insets.right + insets.left
                insetsHeight = insets.top + insets.bottom

                Log.d ("tally", "${insets.right}, ${insets.left}, ${insets.top}, ${insets.bottom}")

                width = metric.bounds.width () - insetsWidth
                height = metric.bounds.height () - insetsHeight

            } else {

                displayMetrics = DisplayMetrics ()
                windowManager.defaultDisplay.getMetrics (displayMetrics)

                width = displayMetrics.widthPixels
                height = displayMetrics.heightPixels
            }
        }
        backgroundThread.start()
    }

    /**
     * A native method that is implemented by the 'dpi_poc' native library,
     * which is packaged with this application.
     */
    external fun stringFromJNI(): String

    companion object {
        // Used to load the 'dpi_poc' library on application startup.
        init {
            System.loadLibrary("dpi_poc")
        }
    }
}

尽管已通过if-else分支区分不同API版本的实现,但仍收到废弃警告,请问代码存在什么问题?如何解决该警告并实现跨API版本的屏幕宽高获取?


问题原因

出现废弃警告的核心原因是Lint静态代码检测不区分运行时分支:你在else分支中调用的WindowManager.DefaultDisplay.getMetrics()方法在API 30+已被标记为废弃,Lint只要检测到代码中存在该调用,就会触发警告——哪怕你已经通过Build.VERSION.SDK_INT做了版本判断,确保低版本才会执行这段代码。

另外,代码中把所有变量都声明在if-else分支外部,虽然语法上合法(if-else覆盖了所有赋值路径),但会导致变量作用域不合理,也增加了代码冗余性。

解决方法

1. 忽略废弃警告(安全且简单)

在包含废弃方法调用的代码块或方法上添加@Suppress("DEPRECATION")注解,明确告诉Lint你已经知晓该方法废弃,且通过版本判断保证了调用的安全性。

2. 优化变量作用域

将变量声明移到对应的分支内部,避免不必要的全局声明,让代码逻辑更清晰,同时减少潜在的编译警告。

3. 统一宽高获取逻辑(可选)

低版本的getMetrics()获取的是屏幕整体尺寸(包含系统导航栏等),而高版本代码中你减去了导航栏和刘海的Insets,得到的是应用可用区域。如果需要统一逻辑,低版本可以通过View.getWindowVisibleDisplayFrame()获取可用区域;如果需求就是获取屏幕整体尺寸,可保持现有逻辑。

修改后的代码示例

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        val backgroundThread = Thread {
            val width: Int
            val height: Int

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
                // API 30+ 逻辑
                val metric = windowManager.currentWindowMetrics
                val insets = metric.windowInsets.getInsetsIgnoringVisibility(
                    WindowInsets.Type.navigationBars() or WindowInsets.Type.displayCutout()
                )
                val insetsWidth = insets.right + insets.left
                val insetsHeight = insets.top + insets.bottom

                Log.d("tally", "${insets.right}, ${insets.left}, ${insets.top}, ${insets.bottom}")

                width = metric.bounds.width() - insetsWidth
                height = metric.bounds.height() - insetsHeight
            } else {
                // API <30 逻辑,添加注解忽略废弃警告
                @Suppress("DEPRECATION")
                val displayMetrics = DisplayMetrics().apply {
                    windowManager.defaultDisplay.getMetrics(this)
                }
                width = displayMetrics.widthPixels
                height = displayMetrics.heightPixels
            }

            // 此处可使用获取到的width和height执行后续操作
        }
        backgroundThread.start()
    }

    external fun stringFromJNI(): String

    companion object {
        init {
            System.loadLibrary("dpi_poc")
        }
    }
}

额外说明

  • 若项目使用AndroidX Core库,可考虑用WindowInsetsCompat统一处理Insets,进一步简化跨版本适配逻辑,但上述方案已能解决核心问题。
  • 确保在非UI线程中执行屏幕尺寸获取时,不涉及UI操作(你的代码已用Thread处理,这部分合理)。

内容的提问来源于stack exchange,提问作者Jatin guglani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 04:25:58