Wednesday, April 11, 2012

Getting the "density" of your Android device

This is one of those crazy small things you'll be needing sooner or later in game development on Android devices.

How to get the "density" of your device?  Or more specifically, how many physical pixels are there per inch, how big is my display?

Well, first of all, we need to get data from our device.

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

That will fill in everything we will need to know. From there, we can get all sorts of useful information.

How many pixels can we work with horizontally and vertically?  *Warning*: These are filled in based on the current orientation of the device!!!
xpixels = dm.widthPixels;
ypixels = dm.heightPixels;

How about pixels per inch on the display?
xpixelsPerInch = dm.xdpi;
ypixelsPerInch = dm.ydpi;

If we know how many pixels are given in a dimension, and how many pixels there are per inch, we can determine the exact inches of our display (more or less).
displayWidth = xpixels / xpixelsPerInch;
displayHeight = ypixels / ypixelsPerInch;

Now, for the part that can be a little bit more mysterious.  What about the actual "density"?  Well, in Android API 4+, our DisplayMetric (dm) has a property conveniently called "densityDpi".  This is well and good for Android 1.6 and beyond, but what about our poor Android 1.5 customers where this field didn't exist?  Fear not, we can still get this information!

There is a field called "density" which is a floating number based on the scaling factor of our pixels in comparison to a 160 DPI device.  In other words, if our device is "160 dpi", this scaling factor is 1 (160/160 = 1).

Common DPIs for Android devices are: 120, 160, 240, and 320.  Knowing this, we can now cater to Android 1.5's missing densityDpi field by making our own.
if (dm.density == 0.75)
    densityDpi = 120;
if (dm.density == 1.0)
    densityDpi = 160;
if (dm.density == 1.5)
    densityDpi = 240;
if (dm.density == 2)
    densityDpi = 320;

Normally it is NOT a good idea to do a straight floating point equality comparison check (rounding errors, precision point problems, etc), but in this case, there shouldn't be any issue.


Correction: Do not do it this way.  We recently received a problem report from a user with a 148 density, which is seemingly not standard.  I will leave this code in here for illustration and so that the reader gets an idea of catering to different hardware displays.

The following way is how you should calculate the density.

densityDpi = (int) (dm.density * 160.0f);

*Update* 4.29.2012 : Added the note about a user with a 148 density.

No comments:

Post a Comment