Getter para pantalla predeterminada: ¡Pantalla!’ es obsoleto. En desuso en Java

8 minutos de lectura

Avatar de usuario de Saswata
Saswata

Necesito el ancho de la pantalla. Pero recientemente encontré Android defaultDisplay en desuso con el mensaje:

Getter para pantalla predeterminada: ¡Pantalla!’ es obsoleto. En desuso en Java

Código:

val displayMetrics = DisplayMetrics()
windowManager.defaultDisplay.getMetrics(displayMetrics)
return displayMetrics.widthPixels

Por favor sugiera una alternativa.

Avatar de usuario de Cristiano Correia
Cristiano Correia

defaultDisplay se marcó como obsoleto en el nivel de API 30 (Android R) y superior. Esto significa que si tiene una configuración de SDK mínima por debajo del nivel de API 30, debe tener ambas implementaciones con el código antiguo obsoleto y el nuevo código recomendado.

Después de solucionar el problema correctamente, puede usar @Suppress(“DEPRECATION”) para suprimir las advertencias

Ejemplo: solución de Kotlin

    val outMetrics = DisplayMetrics()

    if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R) {
        val display = activity.display
        display?.getRealMetrics(outMetrics)
    } else {
        @Suppress("DEPRECATION")
        val display = activity.windowManager.defaultDisplay
        @Suppress("DEPRECATION")
        display.getMetrics(outMetrics)
    }

  • No publique solo el código como respuesta, sino que también brinde una explicación de lo que hace su código y cómo resuelve el problema de la pregunta. Las respuestas con una explicación suelen ser más útiles y de mejor calidad, y es más probable que atraigan votos a favor.

    – Pouria Hemati

    25 de noviembre de 2020 a las 4:41

  • ¿Alguien sabe si hay algo que viene en JetPack para esto? o si hay alguna forma de hacer esto sin verificar las versiones de SDK/API?

    – Tim

    11 de marzo de 2021 a las 18:08


  • Estos dos no dan el mismo resultado para mí. Obtengo display.heightPixels y en el caso del método obsoleto obtengo 2028 pero en el caso del nuevo método obtengo 2160

    – usuario1114

    25 de abril de 2021 a las 1:19

  • Mejor escriba @Suppress(“DEPRECATION”) encima del nombre del método para facilitar la lectura

    – Jacobo

    13 de agosto de 2021 a las 2:05

  • getRealMetrics() está obsoleto en el nivel de API 31.

    – Tianyao ‘Hasta’ Chen

    5 de diciembre de 2021 a las 6:30

Avatar de usuario de David Miguel
david miguel

WindowManager.getDefaultDisplay() quedó en desuso en el nivel API 30 a favor de Context.getDisplay() método que requiere un nivel mínimo de API 30.

En este momento, androidx.core.content.ContextCompat no parece ofrecer compatibilidad con versiones anteriores getDisplay() método.

Si solo necesita recuperar la pantalla predeterminada, en lugar de usar diferentes métodos para diferentes niveles de API como sugieren otras respuestas, puede DisplayManager.getDisplay(Display.DEFAULT_DISPLAY) método (compatible desde API 17) para lograr el mismo resultado.

Código obsoleto:

val defaultDisplay = getSystemService<WindowManager>()?.defaultDisplay

Nuevo código:

val defaultDisplay = getSystemService<DisplayManager>()?.getDisplay(Display.DEFAULT_DISPLAY)

Árbitro: código fuente androidx.core


Si lo que necesitas es conseguir el tamaño de la Ventana, el nuevo Biblioteca Jetpack WindowManager proporciona una superficie de API común para las nuevas funciones de Window Manager (por ejemplo, dispositivos plegables y Chrome OS) en todas las versiones de plataforma antiguas y nuevas.

dependencies {
    implementation "androidx.window:window:1.0.0-beta02"
}

Jetpack WindowManager ofrece dos formas de recuperar Métricas de ventana información, como flujo asíncrono o síncrono.

Flujo asíncrono de WindowMetrics:

Usar WindowInfoRepository#currentWindowMetrics para recibir una notificación de la biblioteca cuando haya un cambio en el tamaño de la ventana, independientemente de si este cambio desencadena un cambio de configuración.

import androidx.window.layout.WindowInfoRepository
import androidx.window.layout.WindowInfoRepository.Companion.windowInfoRepository
import androidx.window.layout.WindowMetrics
import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.flowWithLifecycle

lifecycleScope.launch(Dispatchers.Main) {
    windowInfoRepository().currentWindowMetrics.flowWithLifecycle(lifecycle)
        .collect { windowMetrics: WindowMetrics ->
           val currentBounds = windowMetrics.bounds // E.g. [0 0 1350 1800]
           val width = currentBounds.width()
           val height = currentBounds.height()
        }
}

Métricas de ventana sincrónicas:

Usar VentanaMetricsCalculator al escribir código en una vista donde la API asíncrona puede ser demasiado difícil de manejar (como onMeasure o durante la prueba).

import androidx.window.layout.WindowMetricsCalculator
import androidx.window.layout.WindowMetrics

val windowMetrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(activity)
val currentBounds = windowMetrics.bounds // E.g. [0 0 1350 1800]
val width = currentBounds.width()
val height = currentBounds.height()

Árbitro: Desagregar el WindowManager | Desarrolladores de Android Medio

  • Tuve que agregar el androidx.lifecycle:lifecycle-runtime-ktx dependencia para poder usar flowWithLifecycle. Podría valer la pena mencionar

    – Ivo

    23 de septiembre de 2021 a las 10:03

  • Qué es windowInfoRepository? Obtuve Unresolved reference: windowInfoRepository

    – LMM

    27 de agosto de 2022 a las 3:08

Avatar de usuario de Jyotish Biswas
Jyotish Biswas

Este método quedó obsoleto en el nivel de API 30.

Usar Context.getDisplay() en cambio.

Método obsoleto: getDefaultDisplay

Nuevo método: obtener pantalla

  • Pero esto dice: La llamada requiere el nivel R de API

    – Sasvata

    6 de agosto de 2020 a las 3:27

  • si, porque getDefaultDisplay El método está en desuso en el nivel de API 30

    – Jyotish Biswas

    6 de agosto de 2020 a las 3:31

  • Entonces, ¿debemos verificar API 30 arriba y abajo?

    – Sasvata

    6 de agosto de 2020 a las 5:14

  • Supongo/espero que lo agreguen en el androidx.core liberación pronto. Acabo de comprobar el último código fuente pero no he encontrado nada (en realidad suprimió la advertencia de obsolescencia en las clases que la usan)

    –David Miguel

    24 de septiembre de 2020 a las 19:43

Avatar de usuario de Shark
Tiburón

Prueba algo como esto:


    private Display getDisplay(@NonNull WindowManager windowManager) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // This one (context) may or may not have a display associated with it, due to it being
            // an application context
            return getDisplayPostR();
        } else {
            return getDisplayPreR(windowManager);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.R)
    private Display getDisplayPostR() {
        // We can't get the WindowManager by using the context we have, because that context is a
        // application context, which isn't associated with any display. Instead, grab the default
        // display, and create a DisplayContext, from which we can use the WindowManager or
        // just get that Display from there.
        //
        // Note: the default display doesn't have to be the one where the app is on, however the
        // getDisplays which returns a Display[] has a length of 1 on Pixel 3.
        //
        // This gets rid of the exception interrupting the onUserLogin() method
        Display defaultDisplay = DisplayManagerCompat.getInstance(context).getDisplay(Display.DEFAULT_DISPLAY);
        Context displayContext = context.createDisplayContext(defaultDisplay);
        return displayContext.getDisplay();
    }

    @SuppressWarnings("deprecation")
    private Display getDisplayPreR(@NonNull WindowManager windowManager) {
        return windowManager.getDefaultDisplay();
    }

o para obtener el tamaño real:

    private Point getScreenResolution() {
        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        if (wm == null) {
            return null;
        }
        Display display = getDisplay(wm);

        return getSize(display, wm);
    }

    private Point getSize(Display forWhichDisplay, WindowManager windowManager) {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            return getSizePostR(windowManager);
        } else {
            return getSizePreR(forWhichDisplay);
        }
    }

    @RequiresApi(api = Build.VERSION_CODES.R)
    private Point getSizePostR(@NonNull WindowManager windowManager) {
        WindowMetrics currentWindowMetrics = windowManager.getCurrentWindowMetrics();
        Rect bounds = currentWindowMetrics.getBounds();

        // Get the insets, such as titlebar and other decor views
        WindowInsets windowInsets = currentWindowMetrics.getWindowInsets();
        Insets insets = windowInsets.getInsets(WindowInsets.Type.navigationBars());
        // If cutouts exist, get the max of what we already calculated and the system's safe insets
        if (windowInsets.getDisplayCutout() != null) {
            insets = Insets.max(
                    insets,
                    Insets.of(
                            windowInsets.getDisplayCutout().getSafeInsetLeft(),
                            windowInsets.getDisplayCutout().getSafeInsetTop(),
                            windowInsets.getDisplayCutout().getSafeInsetRight(),
                            windowInsets.getDisplayCutout().getSafeInsetBottom()
                    )
            );
        }
        // Calculate the inset widths/heights
        int insetsWidth = insets.right + insets.left;
        int insetsHeight = insets.top + insets.bottom;

        // Get the display width
        int displayWidth = bounds.width() - insetsWidth;
        int displayHeight = bounds.height() - insetsHeight;

        return new Point(displayWidth, displayHeight);
    }

    // This was deprecated in API 30
    @SuppressWarnings("deprecation")
    private Point getSizePreR(Display display) {
        Point size = new Point();
        if (isRealDisplaySizeAvailable()) {
            display.getRealSize(size);
        } else {
            display.getSize(size);
        }

        return size;
    }

    private static boolean isRealDisplaySizeAvailable() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1;
    }

Avatar de usuario de Jonry Simbolon
Jonry Simbolon

yo suelo DisplayCompatManager para obtener ancho y alto en Android R-Above y usar DisplayMatrics para obtenerlo en otra versión de Android.

Entonces, este es mi código (+ @Suppress(“DEPRECATION”) )

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

        val defaultDisplay =
            DisplayManagerCompat.getInstance(this).getDisplay(Display.DEFAULT_DISPLAY)
        val displayContext = createDisplayContext(defaultDisplay!!)

        width = displayContext.resources.displayMetrics.widthPixels
        height = displayContext.resources.displayMetrics.heightPixels

        Log.e(tag, "width (ANDOIRD R/ABOVE): $width")
        Log.e(tag, "height (ANDOIRD R/ABOVE) : $height")

    } else {

        val displayMetrics = DisplayMetrics()
        @Suppress("DEPRECATION")
        windowManager.defaultDisplay.getMetrics(displayMetrics)

        height = displayMetrics.heightPixels
        width = displayMetrics.widthPixels

        Log.e(tag, "width (BOTTOM ANDROID R): $width")
        Log.e(tag, "height (BOTTOM ANDROID R) : $height")

    }
}

Si quieres ver mi esencia en github

En el método Api Level 31 Display.getRealMetrics() también quedó en desuso. La forma recomendada es usar WindowManager#getCurrentWindowMetrics(). Prefiero el siguiente enfoque para obtener el tamaño de la pantalla:

object ScreenSizeCompat {
    private val api: Api =
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) ApiLevel30()
        else Api()

    /**
     * Returns screen size in pixels.
     */
    fun getScreenSize(context: Context): Size = api.getScreenSize(context)

    @Suppress("DEPRECATION")
    private open class Api {
        open fun getScreenSize(context: Context): Size {
            val display = context.getSystemService(WindowManager::class.java).defaultDisplay
            val metrics = if (display != null) {
                DisplayMetrics().also { display.getRealMetrics(it) }
            } else {
                Resources.getSystem().displayMetrics
            }
            return Size(metrics.widthPixels, metrics.heightPixels)
        }
    }

    @RequiresApi(Build.VERSION_CODES.R)
    private class ApiLevel30 : Api() {
        override fun getScreenSize(context: Context): Size {
            val metrics: WindowMetrics = context.getSystemService(WindowManager::class.java).currentWindowMetrics
            return Size(metrics.bounds.width(), metrics.bounds.height())
        }
    }
}

Y para obtener, por ejemplo, la altura de la pantalla, utilícelo en Activity:

ScreenSizeCompat.getScreenSize(this).height

Avatar de usuario de Roxin Vivian Topp
Roxin Vivian Topp

Cualquiera que quiera hacerlo en Java aquí tiene:

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

        Display display = this.getDisplay();
        DisplayMetrics displayMetrics = new DisplayMetrics();
        display.getRealMetrics(displayMetrics);

        float density  = getResources().getDisplayMetrics().density;
        float dpHeight = displayMetrics.heightPixels / density;
        float dpWidth  = displayMetrics.widthPixels / density;

        Log.d(TAG, "OmesChecka R: "+"second width:"+dpWidth+"second h:"+dpHeight);

    }else {

        Display display = getWindowManager().getDefaultDisplay();
        DisplayMetrics outMetrics = new DisplayMetrics ();
        display.getMetrics(outMetrics);

        float density  = getResources().getDisplayMetrics().density;
        float dpHeight = outMetrics.heightPixels / density;
        float dpWidth  = outMetrics.widthPixels / density;

        Log.d(TAG, "OmesChecka: "+"second width:"+dpWidth+"second h:"+dpHeight);
    }

¿Ha sido útil esta solución?