Capabilities.screenDPI: correct on emulator, wrong on device

2.8k Views Asked by At

I'm making my app multi-screen (flex mobile). Basicly I want to know when I'm dealing with a tablet or a smartphone. Therefore I want to know the screen size in inch. I'm testing this out on a Desire HD (4.3 inch). My issue is: when I use the Capabilities.screenDPI, the emulator shows the correct value (217), however when I run this on my device, it gives me a wrong DPI value (240), the width and height are correct. Based on that dpi I get a wrong screen size in inch (3.887" != 4.3"). Again on the emulator everything runs fine. The device emulator is configured with the correct values, only when I run it on the real device (no emulator), I get a wrong DPI value.

I'm calculating it with the following piece of code:

var screenX:Number = stage.stageWidth;
var screenY:Number = stage.stageHeight;
var pixels:Number = (screenX*screenX) + (screenY*screenY);
var screenSize:Number = Math.sqrt(pixels)/Capabilities.screenDPI;

return (screenSize >= 6) ? "tablet" : "phone" 

To spare you some time I'll give out the values of the Desire HD:

480 x 800 pixels, 4.3 inches (~217 ppi pixel density)

The formula used is simple ~ Pythagoras: a2 + b2 = c2 -> sqrt(c)/dpi = screen size in inch.

Based on Adobe, the DPI or PPI value can be used "interchangeably". (Adobe, Help). I haven't found any information wherether the dpi value is different than the ppi value, or wherether there is any possibility to use a ppi property in flex.

So on my real device I get:

480 x 800 pixels, 3.89" (~240 dpi).

Another note: I've seen that there are 3 default constants in flex mobile. Might it be that its directly thrown into one of these ? (I don't suspect so since I'm calling the Capabilities.screenDPI directly).

DPIClassification.DPI_160
DPIClassification.DPI_240
DPIClassification.DPI_320

What I mean is: How can I determine if it's a tablet or phone (in order to switch to another layout)? You can't follow the applicationDPI road, since it's all mixed up with new devices like the Samsung Galaxy S3 (1280x720, 319 PPI) or the Apple iPad 3 (2048×1536, 264 PPI).

4

There are 4 best solutions below

5
On

The Flex applicationDPI property will return either 160 (for most tablets), 240 (for most smartphones), and 320 for the iPhone 4/4S.

This is something that occurs under the hood to make life "Easier" for developers. Anything built for the specific DPI of the device may not be very expandable to other devices/platforms. I thought that the applicationDPI into one of those 3 values was a Flex thing, but it's entirely possible Flex just inherits it from AIR.

At the end of the day, I don't think there is any way you can use the DPI value to determine whether your app is running on a tablet or phone. Because the values I specify above are not universal. It's all a bit of a guessing game.

I'm surprised this works at all in the emulator, where I would expect the values returned to be the ones from your computer monitor, not equivalent to what the smartphone should be.

0
On

I know this is an old thread but I thought you guys would want to know how I handled it - I finally have it fixed on my end.

protected function resizeHandler(event:ResizeEvent):void
            {
                var screenX:Number = Capabilities.screenResolutionX;
                var screenY:Number = Capabilities.screenResolutionY;
                var osType:String = Capabilities.os;
                var limitNumber:Number = 960;
                var pixelCheck:Number = screenX * screenY;
                var pixels:Number = (screenX*screenX) + (screenY*screenY);
                var screenSize:Number = Math.sqrt(pixels)/Capabilities.screenDPI;

                isPortrait = height > width;
                //isTablet = screenX > limitNumber || screenY > limitNumber;
                isTablet = screenSize >= 6;
                var isDesktop:Boolean = height > limitNumber || width > limitNumber;

                if (osType.toUpperCase() == "WINDOWS 7"){
                    this.currentState = (isPortrait ? "portrait" : "landscape") + (isDesktop ? "Tablet" : "Phone");
                }else {
                    this.currentState = (isPortrait ? "portrait" : "landscape") + (isTablet ? "Tablet" : "Phone");
                }

                //DEBUGGING CODE BELOW


                debugger.text = "screen X: " + screenX.toString() + " screen Y: " + screenY.toString() + "\n pixels: " + pixels.toString() + "\n screenSize: " + screenSize.toString() + "\n capabilities.screenDPI: " + Capabilities.screenDPI.toString() + "\n current state: " + this.currentState + /*"\n IsDesktop: " + isDesktop.toString() + */ " IsTablet: " + isTablet.toString() + "\n OS Type" + osType;

                //currentState = (isPortrait ? "portrait" : "landscape") + (isTablet ? "Tablet" : "Phone");

            }

As you can see from the code above, I'm handling two different situations. 1 - when I am using the emulator on my local PC, the system always thinks im in tablet mode (because it returns very large values for my monitors' screen X and screen Y values). So I handle that with the isDesktop flag.

Then, I use the screen size value to give me tablet vs phone. There are currently (Feb 2013) no tablets under 6 for the screen size, and no phones above it.

0
On

You could try something like

var isItATablet:Boolean = screenHeight > 960 || screenWidth > 960;
var isItReallyATablet:Boolean = isTablet && screenDPI >= 240; // I think this doesn't work as is, but you get the idea..

This way you get if the screen height or width is greater than 960px and the DPI is low, probably you're on a tablet.

This is not 100% accurate, a haven't tested it but on 2 devices, it's just matter of trying with different devices and see if it guess the type of device on most cases

0
On

To detect the screen size in emulator mode you can use SystemManager object this way :

var root:DisplayObject = SystemManager.getSWFRoot(this); // this is any object of the application not only display object
screenX = root.stage.fullScreenWidth;
screenY = root.stage.fullScreenHeight;