Android DPI and screen width/height still wrong

Hello.
There are a few threads about issues getting screen size and DPI on Android.

Here is an issue from 2017 that appears to be still open.

In addition to the wrong DPI, I’m not even getting the correct width and height for my device.

Samsung A8 - from Droid Info app, the internet, and screenshots, my device is
2220 x 1080 (landscape width + height)

The following calls in code:

	float width = director->getWinSize().width;
	float height = director->getWinSize().height;

	Size sizeInPixles = director->getWinSizeInPixels();

	Size visibleSize = director->getVisibleSize();

all give me 1665 x 810

Also,

float dpi = (float)(Device::getDPI());

reports 360, when it should be 480.

The situation is somewhat better on iOS. iPad3 and iPhone5s give correct width, height, and dpi, but iPad Mini (original) has correct width, height, but WRONG dpi – this makes the calculation for screen size give a result almost the same as a 9.7" screen, instead of the 7" it actually is.

I saw this workaround for Android dpi:
https://discuss.cocos2d-x.org/t/cocos2dx-device-getdpi-confusion-on-android/39956/10?u=gmayer

but that appears to be java code. Not sure how to expose that to C++.

Could this be fixed please!?
I’m on the verge of shipping and important update to my game, and am blocked by this, because there are a few decisions I want to make in code at startup based on physical screen size, but I have no reliable way of doing it!
:frowning:

thanks
Greg

@coulsonwang @zhangxm can we take a look at this topic please.

I will ask somebody to take a look.

This should be fixed asap. DPI is useful for gesture recognitions which require calculations of fingers’ movements on the screen.

Hi @gmayer,

i just did a test with my device and indeed there is something wrong with the dpi.
it returned 440 while the actual calculated value supposed to be ~386.

However, there is no problem with the screen size.
i placed a break point here https://github.com/cocos2d/cocos2d-x/blob/v3/cocos/platform/CCGLView.cpp#L207
and the value is as per my device, 1080 x 1920.

i’m just wondering can it be that you have set a custom design resolution or content scale factor? As doing so will affect the values returned from those director functions that you highlighted.

So far i have no use for the dpi function, and i have not run into any problems with screen size. Setting the design resolution is great for me too for having a consistent look across devices.

If you just need to get the device’s actual screen size instead of the ‘refactored’ size based on design resolution, you can call
director->getOpenGLView()->getFrameSize();

@Darren, all the code I pasted above is before I set the design resolution, or a content scale factor.

Your test proved that you got the correct values for your device. That doesn’t mean it’s generally working.

Also, you not having use for the DPI function doesn’t seem like a good reason to leave it broken in the engine.
@stephenhurry above posted a need for it.

And I would like to use it to determine the physical screen size, because I need to make some scaling decisions based on that for certain gameplay elements if I’m on a phone, vs. a tablet.

Thanks
Greg

@gmayer, the source for the very first width and height sent to glview->setFrameSize(w, h) comes from here :point_down:
cocos2d-x/Cocos2dxGLSurfaceView.java at v3 · cocos2d/cocos2d-x · GitHub
i suggest you try placing a break point here and see it is giving you the right values.

This is Android’s official documentation describing about the function. If it gives the wrong values, then something is really wrong there.

@stephenhurry for input gestures, I have been doing it like this

void MyClass::onTouchMoved(Touch* touch, Event* e)
{
	Point pos = convertTouchToNodeSpace(touch);
    Point prevPos = convertToNodeSpace(touch->getPreviousLocation());
}

As it is using the node’s coordinates, it should be relative to the design resolution taking into account the scale factor for different devices? @zhangxm can you confirm this?

if you need movement that is unique to device’s screen, you can use
touch->getDelta()

I really don’t see how getting the dpi will be useful, unless it’s an app for displaying technical info that is unique to the device?

@Darren That’s not the use case I referred to. The coordinates retrieved from Touch are in OpenGL context and cannot reflect their physical positions on the screen. My use case is gesture recognitions, e.g. distinguish panning from swiping, which takes account of touches’ real physical distance. In fact, the design resolution should be taken out of account instead:

float screenDistance(const Vec2& pos1, const Vec2& pos2)
{
	do {
		// get the OpenGL view
		auto pGLView = Director::getInstance()->getOpenGLView();
		BREAK_IF(!pGLView);
		
		// the factors to take OpenGL view's scales & device's DPI for conversion
		static float x_factor = pGLView->getScaleX() / static_cast<float>(Device::getDPI()), y_factor = pGLView->getScaleY() / static_cast<float>(Device::getDPI());
		
		// calculate the distance in inches
		return Vec2((pos1.x - pos2.x) * x_factor, (pos1.y - pos2.y) * y_factor).getLength();
		
	} while (0); return 0;
}