534
votes

How to get the screen density programmatically in android?

I mean: How to find the screen dpi of the current device?

19
Many answers refer to getDisplayMetrics().xdpi, which is supposed to return the real dpi of the device. Please note that this value is not consistently set correctly across devices by the manufacturers, so you just can't use them. Sad but true: the information about real dpi is not available. Source: groups.google.com/d/msg/android-developers/g56jV0Hora0/…sulai
getResources().getDisplayMetrics().xdpi and getResources().getDisplayMetrics().ydpi will give you actual horizontal and vertical densities, which are in most cases different.Ωmega

19 Answers

548
votes

You can get info on the display from the DisplayMetrics struct:

DisplayMetrics metrics = getResources().getDisplayMetrics();

Though Android doesn't use a direct pixel mapping, it uses a handful of quantized Density Independent Pixel values then scales to the actual screen size. So the metrics.densityDpi property will be one of the DENSITY_xxx constants (120, 160, 213, 240, 320, 480 or 640 dpi).

If you need the actual lcd pixel density (perhaps for an OpenGL app) you can get it from the metrics.xdpi and metrics.ydpi properties for horizontal and vertical density respectively.

If you are targeting API Levels earlier than 4. The metrics.density property is a floating point scaling factor from the reference density (160dpi). The same value now provided by metrics.densityDpi can be calculated

int densityDpi = (int)(metrics.density * 160f);
390
votes

This also works:

 getResources().getDisplayMetrics().density;

This will give you:

0.75 - ldpi

1.0 - mdpi

1.5 - hdpi

2.0 - xhdpi

3.0 - xxhdpi

4.0 - xxxhdpi

enter image description here

ref: density

enter image description here

ref 2

147
votes
DisplayMetrics metrics = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics);

switch(metrics.densityDpi) {
     case DisplayMetrics.DENSITY_LOW:
         break;

     case DisplayMetrics.DENSITY_MEDIUM:
         break;

     case DisplayMetrics.DENSITY_HIGH:
         break;
}

This will work on API level 4 and higher.

63
votes

Blundell's answer as a static helper method:

private static String getDensityName(Context context) {
    float density = context.getResources().getDisplayMetrics().density;
    if (density >= 4.0) {
        return "xxxhdpi";
    }
    if (density >= 3.0) {
        return "xxhdpi";
    }
    if (density >= 2.0) {
        return "xhdpi";
    }
    if (density >= 1.5) {
        return "hdpi";
    }
    if (density >= 1.0) {
        return "mdpi";
    }
    return "ldpi";
}
45
votes

Try this:

DisplayMetrics dm = context.getResources().getDisplayMetrics();
int densityDpi = dm.densityDpi;
40
votes

Here are some density constants, source:

enter image description here

There are, in addition to the standard densities, 5 Intermediate ones. Taking into account this fact, the following code will be a complete working example:

float density = getResources().getDisplayMetrics().density;

if (density == 0.75f)
{
    // LDPI
}
else if (density >= 1.0f && density < 1.5f)
{
    // MDPI
}
else if (density == 1.5f)
{
    // HDPI
}
else if (density > 1.5f && density <= 2.0f)
{
    // XHDPI
}
else if (density > 2.0f && density <= 3.0f)
{
    // XXHDPI
}
else
{
    // XXXHDPI 
}

Alternatively, you can find density constants using the densityDpi:

int densityDpi = getResources().getDisplayMetrics().densityDpi;

switch (densityDpi)
{
    case DisplayMetrics.DENSITY_LOW:
        // LDPI
        break;

    case DisplayMetrics.DENSITY_MEDIUM:
        // MDPI
        break;

    case DisplayMetrics.DENSITY_TV:
    case DisplayMetrics.DENSITY_HIGH:
        // HDPI
        break;

    case DisplayMetrics.DENSITY_XHIGH:
    case DisplayMetrics.DENSITY_280:
        // XHDPI
        break;

    case DisplayMetrics.DENSITY_XXHIGH:
    case DisplayMetrics.DENSITY_360:
    case DisplayMetrics.DENSITY_400:
    case DisplayMetrics.DENSITY_420:
        // XXHDPI
        break;

    case DisplayMetrics.DENSITY_XXXHIGH:
    case DisplayMetrics.DENSITY_560:
        // XXXHDPI
        break;
}
38
votes

To get dpi:

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);

// will either be DENSITY_LOW, DENSITY_MEDIUM or DENSITY_HIGH
int dpiClassification = dm.densityDpi;

// these will return the actual dpi horizontally and vertically
float xDpi = dm.xdpi;
float yDpi = dm.ydpi;
29
votes

The following answer is a small improvement based upon qwertzguy's answer.

double density = getResources().getDisplayMetrics().density;
if (density >= 4.0) {
   //"xxxhdpi";
}
else if (density >= 3.0 && density < 4.0) {
   //xxhdpi
}
else if (density >= 2.0) {
   //xhdpi
}
else if (density >= 1.5 && density < 2.0) {
   //hdpi
}
else if (density >= 1.0 && density < 1.5) {
   //mdpi
}
20
votes

Actualy if you want to have the real display dpi the answer is somewhere in between if you query for display metrics:

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int dpiClassification = dm.densityDpi;
float xDpi = dm.xdpi;
float yDpi = dm.ydpi;

densityDpi * 160 will give you the values/suggestion which density you should use

0.75 - ldpi - 120 dpi
1.0 - mdpi - 160 dpi
1.5 - hdpi - 240 dpi
2.0 - xhdpi - 320 dpi
3.0 - xxhdpi - 480 dpi
4.0 - xxxhdpi - 640 dpi

as specified in previous posts

but dm.xdpi won't give you always the REAL dpi of given display: Example:

Device: Sony ericsson xperia mini pro (SK17i)
Density: 1.0 (e.g. suggests you use 160dpi resources)
xdpi: 193.5238
Real device ppi is arround 193ppi


Device: samsung GT-I8160 (Samsung ace 2)
Density 1.5 (e.g. suggests you use 240dpi resources)
xdpi 160.42105
Real device ppi is arround 246ppi

so maybe real dpi of the display should be Density*xdpi .. but i'm not sure if this is the correct way to do!

17
votes

This should help on your activity ...

void printSecreenInfo(){

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

    Log.i(TAG, "density :" +  metrics.density);

    // density interms of dpi
    Log.i(TAG, "D density :" +  metrics.densityDpi);

    // horizontal pixel resolution
    Log.i(TAG, "width pix :" +  metrics.widthPixels);

     // actual horizontal dpi
    Log.i(TAG, "xdpi :" +  metrics.xdpi);

    // actual vertical dpi
    Log.i(TAG, "ydpi :" +  metrics.ydpi);

}

OUTPUT :

I/test( 1044): density :1.0

I/test( 1044): D density :160

I/test( 1044): width pix :800

I/test( 1044): xdpi :160.0

I/test( 1044): ydpi :160.42105
13
votes
public static String getDensity(Context context) {
    String r;
    DisplayMetrics metrics = new DisplayMetrics();

    if (!(context instanceof Activity)) {
        r = "hdpi";
    } else {
        Activity activity = (Activity) context;
        activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);

        if (metrics.densityDpi <= DisplayMetrics.DENSITY_LOW) {
            r = "ldpi";
        } else if (metrics.densityDpi <= DisplayMetrics.DENSITY_MEDIUM) {
            r = "mdpi";
        } else {
            r = "hdpi";
        }
    }

    return r;
}
11
votes

If you want to retrieve the density from a Service it works like this:

WindowManager wm = (WindowManager) this.getSystemService(Context.WINDOW_SERVICE);
DisplayMetrics metrics = new DisplayMetrics();
wm.getDefaultDisplay().getMetrics(metrics);
8
votes

You Should Try This. Just Added a Method which will find and Show the Toast. That in Which Category the Device Falls.

public static int differentDensityAndScreenSize(Context context) {
  int value = 20;
  String str = "";
  if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_SMALL) {
   switch (context.getResources().getDisplayMetrics().densityDpi) {
   case DisplayMetrics.DENSITY_LOW:
    str = "small-ldpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_MEDIUM:
    str = "small-mdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_HIGH:
    str = "small-hdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_XHIGH:
    str = "small-xhdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_XXHIGH:
    str = "small-xxhdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_XXXHIGH:
    str = "small-xxxhdpi";
    value = 20;
    break;
   case DisplayMetrics.DENSITY_TV:
    str = "small-tvdpi";
    value = 20;
    break;
   default:
    str = "small-unknown";
    value = 20;
    break;
   }

  } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_NORMAL) {
   switch (context.getResources().getDisplayMetrics().densityDpi) {
   case DisplayMetrics.DENSITY_LOW:
    str = "normal-ldpi";
    value = 82;
    break;
   case DisplayMetrics.DENSITY_MEDIUM:
    str = "normal-mdpi";
    value = 82;
    break;
   case DisplayMetrics.DENSITY_HIGH:
    str = "normal-hdpi";
    value = 82;
    break;
   case DisplayMetrics.DENSITY_XHIGH:
    str = "normal-xhdpi";
    value = 90;
    break;
   case DisplayMetrics.DENSITY_XXHIGH:
    str = "normal-xxhdpi";
    value = 96;
    break;
   case DisplayMetrics.DENSITY_XXXHIGH:
    str = "normal-xxxhdpi";
    value = 96;
    break;
   case DisplayMetrics.DENSITY_TV:
    str = "normal-tvdpi";
    value = 96;
    break;
   default:
    str = "normal-unknown";
    value = 82;
    break;
   }
  } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_LARGE) {
   switch (context.getResources().getDisplayMetrics().densityDpi) {
   case DisplayMetrics.DENSITY_LOW:
    str = "large-ldpi";
    value = 78;
    break;
   case DisplayMetrics.DENSITY_MEDIUM:
    str = "large-mdpi";
    value = 78;
    break;
   case DisplayMetrics.DENSITY_HIGH:
    str = "large-hdpi";
    value = 78;
    break;
   case DisplayMetrics.DENSITY_XHIGH:
    str = "large-xhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XXHIGH:
    str = "large-xxhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XXXHIGH:
    str = "large-xxxhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_TV:
    str = "large-tvdpi";
    value = 125;
    break;
   default:
    str = "large-unknown";
    value = 78;
    break;
   }

  } else if ((context.getResources().getConfiguration().screenLayout & Configuration.SCREENLAYOUT_SIZE_MASK) == Configuration.SCREENLAYOUT_SIZE_XLARGE) {
   switch (context.getResources().getDisplayMetrics().densityDpi) {
   case DisplayMetrics.DENSITY_LOW:
    str = "xlarge-ldpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_MEDIUM:
    str = "xlarge-mdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_HIGH:
    str = "xlarge-hdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XHIGH:
    str = "xlarge-xhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XXHIGH:
    str = "xlarge-xxhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_XXXHIGH:
    str = "xlarge-xxxhdpi";
    value = 125;
    break;
   case DisplayMetrics.DENSITY_TV:
    str = "xlarge-tvdpi";
    value = 125;
    break;
   default:
    str = "xlarge-unknown";
    value = 125;
    break;
   }
  }
// The Toast will show the Device falls in Which Categories.
Toast.makeText(MainActivity.this, ""+str, Toast.LENGTH_SHORT).show();

  return value;
 }

http://www.androidwarriors.com/2016/01/how-to-find-different-devices-screen.html

7
votes

This should work.

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels; //320
int height = dm.heightPixels; //480
7
votes

Yet another answer:

/**
* @return "ldpi", "mdpi", "hdpi", "xhdpi", "xhdpi", "xxhdpi", "xxxhdpi", "tvdpi", or "unknown".
*/
public static String getDensityBucket(Resources resources) {
    switch (resources.getDisplayMetrics().densityDpi) {
        case DisplayMetrics.DENSITY_LOW:
            return "ldpi";
        case DisplayMetrics.DENSITY_MEDIUM:
            return "mdpi";
        case DisplayMetrics.DENSITY_HIGH:
            return "hdpi";
        case DisplayMetrics.DENSITY_XHIGH:
            return "xhdpi";
        case DisplayMetrics.DENSITY_XXHIGH:
            return "xxhdpi";
        case DisplayMetrics.DENSITY_XXXHIGH:
            return "xxxhdpi";
        case DisplayMetrics.DENSITY_TV:
            return "tvdpi";
        default:
            return "unknown";
    }
}
3
votes

Another way to get the density loaded by the device:

Create values folders for each density

  • values (default mdpi)
  • values-hdpi
  • values-xhdpi
  • values-xxhdpi
  • values-xxxhdpi

Add a string resource in their respective strings.xml:

<string name="screen_density">MDPI</string>    <!-- ..\res\values\strings.xml -->
<string name="screen_density">HDPI</string>    <!-- ..\res\values-hdpi\strings.xml -->
<string name="screen_density">XHDPI</string>   <!-- ..\res\values-xhdpi\strings.xml -->
<string name="screen_density">XXHDPI</string>  <!-- ..\res\values-xxhdpi\strings.xml -->
<string name="screen_density">XXXHDPI</string> <!-- ..\res\values-xxxhdpi\strings.xml -->

Then simply get the string resource, and you have your density:

String screenDensity = getResources().getString(R.string.screen_density);

If the density is larger than XXXHDPI, it will default to XXXHDPI or if it is lower than HDPI it will default to MDPI

R.strings.screen_density values

I left out LDPI, because for my use case it isn't necessary.

2
votes

Try this...

In kotlin

fun determineScreenDensityCode(): String {
      return when (resources.displayMetrics.densityDpi) {
         DisplayMetrics.DENSITY_LOW -> "ldpi"
         DisplayMetrics.DENSITY_MEDIUM -> "mdpi"
         DisplayMetrics.DENSITY_HIGH -> "hdpi"
         DisplayMetrics.DENSITY_XHIGH, DisplayMetrics.DENSITY_280 -> "xhdpi"
         DisplayMetrics.DENSITY_XXHIGH, DisplayMetrics.DENSITY_360, DisplayMetrics.DENSITY_400, DisplayMetrics.DENSITY_420 -> "xxhdpi"
         DisplayMetrics.DENSITY_XXXHIGH, DisplayMetrics.DENSITY_560 -> "xxxhdpi"
         else -> "Unknown code ${resources.displayMetrics.densityDpi}"
     }
}

You can call by println("density: ${determineScreenDensityCode()}") and the output will be System.out: density: xxxhdpi

0
votes

I am using following code to access DPI from modules (no need for having access to a context object):

(Resources.getSystem().getDisplayMetrics().xdpi
Resources.getSystem().getDisplayMetrics().ydpi)/2
0
votes

In Android you can get the screen density like this:

public static String getScreenDensity(Context context)
{
    String density;
    switch (context.getResources().getDisplayMetrics().densityDpi)
    {
        case DisplayMetrics.DENSITY_LOW:
            density = "LDPI";
            break;
        case DisplayMetrics.DENSITY_140:
            density = "LDPI - MDPI";
            break;
        case DisplayMetrics.DENSITY_MEDIUM:
            density = "MDPI";
            break;
        case DisplayMetrics.DENSITY_180:
        case DisplayMetrics.DENSITY_200:
        case DisplayMetrics.DENSITY_220:
            density = "MDPI - HDPI";
            break;
        case DisplayMetrics.DENSITY_HIGH:
            density = "HDPI";
            break;
        case DisplayMetrics.DENSITY_260:
        case DisplayMetrics.DENSITY_280:
        case DisplayMetrics.DENSITY_300:
            density = "HDPI - XHDPI";
            break;
        case DisplayMetrics.DENSITY_XHIGH:
            density = "XHDPI";
            break;
        case DisplayMetrics.DENSITY_340:
        case DisplayMetrics.DENSITY_360:
        case DisplayMetrics.DENSITY_400:
        case DisplayMetrics.DENSITY_420:
        case DisplayMetrics.DENSITY_440:
            density = "XHDPI - XXHDPI";
            break;
        case DisplayMetrics.DENSITY_XXHIGH:
            density = "XXHDPI";
            break;
        case DisplayMetrics.DENSITY_560:
        case DisplayMetrics.DENSITY_600:
            density = "XXHDPI - XXXHDPI";
            break;
        case DisplayMetrics.DENSITY_XXXHIGH:
            density = "XXXHDPI";
            break;
        case DisplayMetrics.DENSITY_TV:
            density = "TVDPI";
            break;
        default:
            density = "UNKNOWN";
            break;
    }

    return density;
}

And in Kotlin like this:

fun getScreenDensity(context: Context): String {
    val density: String
    when (context.resources.displayMetrics.densityDpi) {
        DisplayMetrics.DENSITY_LOW -> density = "LDPI"
        DisplayMetrics.DENSITY_140 -> density = "LDPI - MDPI"
        DisplayMetrics.DENSITY_MEDIUM -> density = "MDPI"
        DisplayMetrics.DENSITY_180, DisplayMetrics.DENSITY_200, DisplayMetrics.DENSITY_220 -> density = "MDPI - HDPI"
        DisplayMetrics.DENSITY_HIGH -> density = "HDPI"
        DisplayMetrics.DENSITY_260, DisplayMetrics.DENSITY_280, DisplayMetrics.DENSITY_300 -> density = "HDPI - XHDPI"
        DisplayMetrics.DENSITY_XHIGH -> density = "XHDPI"
        DisplayMetrics.DENSITY_340, DisplayMetrics.DENSITY_360, DisplayMetrics.DENSITY_400, DisplayMetrics.DENSITY_420, DisplayMetrics.DENSITY_440 -> density =
            "XHDPI - XXHDPI"
        DisplayMetrics.DENSITY_XXHIGH -> density = "XXHDPI"
        DisplayMetrics.DENSITY_560, DisplayMetrics.DENSITY_600 -> density = "XXHDPI - XXXHDPI"
        DisplayMetrics.DENSITY_XXXHIGH -> density = "XXXHDPI"
        DisplayMetrics.DENSITY_TV -> density = "TVDPI"
        else -> density = "UNKNOWN"
    }

    return density
}

Make sure to regularly check if new densities are added.