Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getter for defaultDisplay: Display!' is deprecated. Deprecated in Java

I need the width of the screen. But recently found Android defaultDisplay deprecacted with message:

Getter for defaultDisplay: Display!' is deprecated. Deprecated in Java

Code:

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

Please suggest an alternative.

like image 732
Saswata Avatar asked Aug 06 '20 02:08

Saswata


4 Answers

defaultDisplay was marked as deprecated in API level 30 (Android R) and above. This means if you have a minimum SDK configuration below API level 30, you should have both implementations with the old deprecated code and the new recommended code.

After fixing the problem correctly you can use @Suppress("DEPRECATION") to suppress warnings

Example: Kotlin solution

    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)
    }
like image 52
Cristiano Correia Avatar answered Nov 05 '22 21:11

Cristiano Correia


WindowManager.getDefaultDisplay() was deprecated in API level 30 in favour of Context.getDisplay() method which requires minimum API level 30.

At the moment, androidx.core.content.ContextCompat doesn't seem to offer any backwards compatible getDisplay() method.

If you only need to retrieve the default display, instead of using different methods for different API levels as other answers suggest, you can you DisplayManager.getDisplay(Display.DEFAULT_DISPLAY) method (supported since API 17) to achieve the same result.

Deprecated code:

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

New code:

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

Ref: androidx.core source code


If what you need is to get the size of the Window, the new Jetpack WindowManager library provides a common API surface for new Window Manager features (e.g. foldable devices and Chrome OS) throughout old and new platform versions.

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

Jetpack WindowManager offers two ways to retrieve WindowMetrics information, as an asynchronous stream or synchronously.

Asynchronous WindowMetrics flow:

Use WindowInfoRepository#currentWindowMetrics to get notified by the library when there’s a window size change, independent of whether this change fires a configuration change.

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()
        }
}
  • Note: lifecycleScope and flowWithLifecycle() are part of Jetpack Lifecycle library.

Synchronous WindowMetrics:

Use WindowMetricsCalculator when writing code in a view where the asynchronous API can be too hard to deal with (such as onMeasure or during testing).

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()

Ref: Unbundling the WindowManager | Android Developers Medium

like image 38
David Miguel Avatar answered Nov 05 '22 22:11

David Miguel


This method was deprecated in API level 30.

Use Context.getDisplay() instead.

Deprecated method: getDefaultDisplay

New Method: getDisplay

like image 8
Jyotish Biswas Avatar answered Nov 05 '22 22:11

Jyotish Biswas


Try something like this:


    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();
    }

or to get the actual size:

    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;
    }
like image 4
Shark Avatar answered Nov 05 '22 22:11

Shark