Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android screen density calculation

Tags:

android

screen

Can somebody tell me how Android counts the screen density?

My problem is I have a device (ODYS Space) with 480x800 resolution and with 7" diagonal screen. If I calculate its density I get a value 133 DPI but Android (2.2 and 2.3 too) reports it like "MEDIUM" density device (160 DPI).

I'm fighting with multiscreen support so I supposed 133 DPI will be rather reported like "LOW" than "MEDIUM" so now my screen layout looks quite stupid on this medium reported device.

I check the device with code like this:

DisplayMetrics dMetrics = new DisplayMetrics(); 
getWindowManager().getDefaultDisplay().getMetrics(dMetrics);  
int d=dMetrics.densityDpi;

If I run that code on a virtual device configured (480x800/7" and 133 DPI) then I got density=120.

On the real device why does it say 160 instead?

like image 224
rugo Avatar asked Jan 29 '12 14:01

rugo


People also ask

How is screen density calculated?

You can take either the horizontal or vertical resolution. Once you have the resolution, you must measure the length of the display. Usually, this will be measured in inches (2.54cm = 1 inch). If you divide the two numbers, you'll find the “pixels per inch” (ppi).

What is Android screen density?

density equals 1.0; on a high-density screen it equals 1.5; on an extra-high-density screen, it equals 2.0; and on a low-density screen, it equals 0.75. This figure is the factor by which you should multiply the dp units in order to get the actual pixel count for the current screen.

How is dp calculated in Android?

Dps and screen density A dp is equal to one physical pixel on a screen with a density of 160. To calculate dp: dp = (width in pixels *... A dp is equal to one physical pixel on a screen with a density of 160.

What is mobile screen density?

Base density for Android is mdpi. All other densities are its appropriate ratios, which is as follows: 0.75x – low-density (ldpi) 1.0x – medium-density (mdpi) 1.5x – high-density (hdpi)


3 Answers

There are two different things here.

  1. The behavior in the emulator which is a combination of the AVD manager configuring the AVD itself and maybe using a device definition. The emulator system images have baked in values so that we can ship the same image for all device configurations. This baked in value is mdpi for density. When you create an AVD with a different density we inject just before boot time the new value. The injected value is converted to a density bucket value (ldpi, mdpi, hdpi, ...) based on basic rules (if you are past the half point between bucket value, you go in the next value).

So the half point between 120 and 160 is 140, and therefore 133dpi -> ldpi.

  1. Device do whatever they want. It's a manual process for any OEM to decide what their device's bucket value is, and this get set in a property. It is not dynamically computed based on the actual hardware screen size of the device. You can do a device that has a true screen density of 133 and yet put it in the xxdpi bucket if you want.

The end result is that you need to create a new device definition where you manually say your 7" 480x800 device is actually a medium density device, and it should work. If it doesn't, it's a bug on our side when we configure the emulator for a particular device-based AVD. It's not an issue on the Android platform itself which doesn't compute anything.

like image 196
Xavier Ducrohet Avatar answered Sep 22 '22 23:09

Xavier Ducrohet


I have updated one of the other solutions for 2014.

Call this method in one of your Activities:

private void tellMeDensity() {
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int dpiClassification = dm.densityDpi;

        float xDpi = dm.xdpi;
        float yDpi = dm.ydpi;

        Toast.makeText(this, "xdpi=" + xDpi, Toast.LENGTH_SHORT).show();
        Toast.makeText(this, "ydpi=" + yDpi, Toast.LENGTH_SHORT).show();

        switch(dpiClassification) {
           case DisplayMetrics.DENSITY_LOW:
               Toast.makeText(this, "low density", Toast.LENGTH_SHORT).show();
               break;    
           case DisplayMetrics.DENSITY_MEDIUM:
               Toast.makeText(this, "medium density", Toast.LENGTH_SHORT).show();
               break;                
           case DisplayMetrics.DENSITY_HIGH:
               Toast.makeText(this, "high density", Toast.LENGTH_SHORT).show();
               break;    
           case DisplayMetrics.DENSITY_XHIGH:
               Toast.makeText(this, "xhigh density", Toast.LENGTH_SHORT).show();
               break;                  
           case DisplayMetrics.DENSITY_XXHIGH:
               Toast.makeText(this, "xxhigh density", Toast.LENGTH_SHORT).show();
               break;                  
           case DisplayMetrics.DENSITY_XXXHIGH:
               Toast.makeText(this, "xxxhigh density", Toast.LENGTH_SHORT).show();
               break;      
        }
    }
like image 39
Tyler Avatar answered Sep 21 '22 23:09

Tyler


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 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, so maybe real dpi of the display should be Density*xdpi

like image 24
Sagar Pilkhwal Avatar answered Sep 23 '22 23:09

Sagar Pilkhwal