559

How to get the screen density programmatically in android?

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

Ωmega
  • 42,614
  • 34
  • 134
  • 203
Praveen
  • 90,477
  • 74
  • 177
  • 219
  • 10
    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: https://groups.google.com/d/msg/android-developers/g56jV0Hora0/9d8p8QJg1ksJ – sulai Aug 05 '15 at 13:21
  • 2
    `getResources().getDisplayMetrics().xdpi` and `getResources().getDisplayMetrics().ydpi` will give you **actual horizontal and vertical densities**, which are in most cases different. – Ωmega Feb 22 '18 at 12:47

21 Answers21

564

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);
Ωmega
  • 42,614
  • 34
  • 134
  • 203
joshperry
  • 41,167
  • 16
  • 88
  • 103
  • 50
    Granted this post is from over two years ago, but this is the first thing that comes up on Google for this search, so for anyone who finds this, you no longer have to multiply by 160. –  Nov 18 '12 at 04:05
  • 7
    No longer since which version? – TacB0sS Jul 29 '13 at 20:15
  • I've updated the answer to match the latest API revisions that people may be using. – joshperry Nov 01 '13 at 21:15
  • 8
    Note: You may want this newer API instead: `getWindowManager().getDefaultDisplay().getRealMetrics(metrics);` This was officially added in API 17, but I was surprised to find that it worked correctly even on a 4.0 device I tried. – benkc Feb 05 '14 at 21:40
  • If you go into the Android documentation and set your API to API 15, this line of code is displayed... so it may have been added in API 15. – Lou Morda Oct 09 '14 at 17:30
  • @roboguy12 I tried not multiplying it by 160, and it showed 4. multiplying by 160 using the code in the answer above, requires multiplying by 160 – Zoe Jul 28 '16 at 18:01
  • @Polarbear0106 If you are using the `density` property you will need to multiply by 160. In API levels >= 4 you can use the `xdpi` and `ydpi` or the `desnityDpi` properties to get scalar values. – joshperry Jul 28 '16 at 21:14
  • 5
    there is also getResources().getDisplayMetrics().densityDpi – amorenew Jan 03 '17 at 08:29
  • 1
    now 'getDefaultDisplay()' is deprecated & 'getMetrics(android.util.DisplayMetrics)' is deprecated help me – Prabhakaran P Sep 28 '20 at 09:17
412

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

Blundell
  • 75,855
  • 30
  • 208
  • 233
  • 11
    +1 This works when you don't have direct access to `WindowManager` (e.g. inside a Loader). Just multiply it by 160 – Michał Klimczak Jun 10 '12 at 08:12
  • 2
    API Level 16 added xxdpi, which translates here to 3.0. – QED Aug 03 '12 at 17:50
  • 4
    this will give 1.3312501 for `tvdpi`. For more info on `tvdpi` see [here](https://plus.google.com/105051985738280261832/posts/6eWwQvFGLV8) – Dori Aug 07 '13 at 09:36
  • 2
    Nexus 7 reports 1.3, why bracket should that go in? – Neil Apr 01 '14 at 12:18
  • Not getting this "x" factor i.e. 0.75x? – Rahul Matte Aug 27 '15 at 07:59
  • If you need to scale text, I found a way to avoid the API stuff, you can also get the density information from the 1dp value. 1. Define a dimension in your dimens.xml file, value should be 1dp 2. From your Java code, do `Context#getResources().getDimensionPixelSize(DIMEN_NAME_HERE)` 3. Multiply your pixel value with this value (for hdpi I think it will be the same) – milosmns Sep 02 '15 at 09:49
  • My phone pulls drawables from xxxdpi, but reports a density of 3.5. The above chart says "4.0" maps to xxxhdpi. Which is correct? – selbie Feb 24 '16 at 08:24
  • 1
    @selbie, your phone is probably pulling and scaling the higher quality resources since your phone is reporting half way between two defined densities. – Sakiboy Jun 14 '17 at 03:57
  • @selbie, `...the system prefers to scale-down the high-density version of the resource..` from https://developer.android.com/guide/practices/screens_support.html#terms – Sakiboy Jun 14 '17 at 04:03
  • What if you get 1.75? – Patrice Andala May 22 '20 at 20:15
149
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.

K Neeraj Lal
  • 6,768
  • 3
  • 24
  • 33
Mitul Nakum
  • 5,514
  • 5
  • 35
  • 41
  • How would you hand devices like Nexus 7 that reports densityDpi as 213? – Neil Apr 01 '14 at 12:17
  • have if-else hand check between density value like, if (metrics.densityDpi > DisplayMetrics.DENSITY_LOW && metrics.densityDpi < DisplayMetrics.DENSITY_MEDIUM) – Mitul Nakum Apr 01 '14 at 14:26
  • 1
    OR if (metrics.densityDpi < DisplayMetrics.DENSITY_LOW){} else if (metrics.densityDpi < DisplayMetrics. DENSITY_MEDIUM){}..... – Mitul Nakum Apr 01 '14 at 14:36
  • 1
    Neil, 213 is called TV DPI, there is a named display metrics density for that DENSITY_TV. – Andrew S Jul 01 '15 at 05:15
64

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";
}
Community
  • 1
  • 1
qwertzguy
  • 15,699
  • 9
  • 63
  • 66
  • 1
    what about the tvdpi density. I guess it is 1.33 – Anoop May 21 '14 at 04:50
  • @AnoopssGolden It's not really standard, so you can add it if you want, but I don't think the answer should include it. From the android docs: "This is not considered a "primary" density group. It is mostly intended for televisions and most apps shouldn't need it". – qwertzguy May 21 '14 at 10:23
  • But nexus 7 device belong to tvdpi density group. – Anoop May 21 '14 at 10:32
  • @AnoopssGolden Isn't it better to use mdpi for it? – qwertzguy May 21 '14 at 10:41
  • 1
    I know this is a bit old but just to add; MDPI might work for most things on a Nexus 7 but as I am trying now, images coming down as MDPI are not big enough. I am having to define TVDPI and then ask for a bigger image size from my server. It may not be used a lot but that doesn't mean MDPI will pick up everything. – RED_ Aug 13 '14 at 14:01
  • That code could do with some elses. I hope you don't mind but I added them and removed the braces. It's slightly more efficient now. – Andrew S Jul 01 '15 at 05:42
  • 3
    Hey @Andrew S, using elses does not change anything to the efficiency of the code since every if returns immediately. Removing braces is a question of style only and IMHO makes it more error prone when maintaining the code. – qwertzguy Jul 01 '15 at 11:04
  • 2020 year: This was maybe true before, but take in mind that android evolved. For example this would be wrong for Pixel 3a phone which density is 2.75, but according to this documentation: https://developer.android.com/reference/android/util/DisplayMetrics#DENSITY_440 It belongs to XXHDPI. – I.Step Nov 20 '20 at 19:20
  • this method returns `hdpi` for 1.7. But it actually belongs to `xhdpi` – Randunu.KSW Aug 02 '21 at 11:28
48

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;
}
Ayaz Alifov
  • 8,334
  • 4
  • 61
  • 56
45

Try this:

DisplayMetrics dm = context.getResources().getDisplayMetrics();
int densityDpi = dm.densityDpi;
Wizist
  • 553
  • 4
  • 5
38

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;
Jere.Jones
  • 9,915
  • 5
  • 35
  • 38
  • 4
    dm.densityDpi returns either DENSITY_LOW or DENSITY_MEDIUM or DENSITY_HIGH. What about xhdpi? Is there any DENSITY_XHIGH or so? – Eugene Chumak Apr 16 '12 at 08:52
  • Yes, there is: http://developer.android.com/reference/android/util/DisplayMetrics.html – caw May 13 '12 at 18:31
29

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
}
San
  • 2,078
  • 1
  • 24
  • 42
  • 1
    This code could do with some elses, and the ampersands and conditions after it are redundant. – Andrew S Jul 01 '15 at 05:42
  • 1
    @Andrew, thanks for the correction. I have edited the answer accordingly. – San Aug 17 '15 at 08:12
  • 2
    @San You don't need the && in any of those conditions, as long as you consistently checked for >= the else if will terminate for the first condition that is true. – dbenson Oct 13 '15 at 12:54
  • 3
    This doesn't return a correct result for me with my Nexus 5X (a default google device btw). The device density is xxhdpi, and the double density returned is around 2.6. – Tobliug Sep 19 '17 at 07:23
21

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!

cyborg86pl
  • 2,597
  • 2
  • 26
  • 43
Marek Halmo
  • 2,181
  • 2
  • 15
  • 18
  • 1
    Using Density*xdpi is working perfectly so far on all my apps on google play so far for the past 6 months – Marek Halmo May 05 '14 at 09:34
  • Multiplying density * xdpi is not logical, which is clearer now that there are more higher density devices - both Density and xdpi increase, so multiplying them would be double-counting the increase. I would say Samsung ace 2 was an error by the vendor. The Android spec is that xdpi and ydpi are the true pixel densities - don't multiply by anything. – ToolmakerSteve Jun 10 '18 at 18:53
17

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
j0k
  • 22,600
  • 28
  • 79
  • 90
prabhu
  • 301
  • 2
  • 6
13
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;
}
Felipe
  • 16,649
  • 11
  • 68
  • 92
11

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);
Display name
  • 2,697
  • 2
  • 31
  • 49
8

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

Avinash Verma
  • 2,572
  • 1
  • 18
  • 22
7

This should work.

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int width = dm.widthPixels; //320
int height = dm.heightPixels; //480
Robby Pond
  • 73,164
  • 16
  • 126
  • 119
  • 4
    The size in pixels of the display is not the density. – joshperry Jul 02 '10 at 14:33
  • 1
    This is density independent pixels not the pixels. And that 320 you see is 320dip not 320px. The calculation of px is different see this http://stackoverflow.com/questions/6840904/how-to-get-the-screen-size-of-the-device/6841335#6841335 – Lukap Jul 27 '11 at 08:19
7

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";
    }
}
Jared Rummler
  • 37,824
  • 19
  • 133
  • 148
4

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

Silambarasan Poonguti
  • 9,386
  • 4
  • 45
  • 38
4

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.

Pierre
  • 8,397
  • 4
  • 64
  • 80
  • I think this is the right way to get the density. Because I use the getResources().getDisplayMetrics().density, the density would change if I changes the display size in setting. – Fantasy Fang Jun 06 '20 at 07:41
2

Kotlin

LocalContext.current.resources.displayMetrics.density

To get the density multiplier.

Clément Cardonnel
  • 4,232
  • 3
  • 29
  • 36
1

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.

Wirling
  • 4,810
  • 3
  • 48
  • 78
1

For Jetpack compose first get the screen density inside a composable function with

var density = LocalDensity.current.density

then switch off the density value like the other answers

    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";
GoBig06
  • 255
  • 2
  • 13
0

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
Jan Málek
  • 531
  • 8
  • 21