Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Screen.dpi on android

Discussion in 'Android' started by JuliusM, Jun 29, 2016.

  1. JuliusM

    JuliusM

    Unity Technologies

    Joined:
    Apr 17, 2013
    Posts:
    835
    Before Unity 5.1 Screen.dpi value was calculated as the average of xdpi and ydpi. However on some devices these values are not correct, because they have to be set by device manufacturer and they are not used by Android OS, so they are not guaranteed to be correct. Instead Android OS uses densityDpi value for UI scaling. In Unity 5.3 we've changed Screen.dpi implementation to return the average of xdpi and ydpi only when the value is not too far from densityDPI, otherwise we were returning densityDPI. This was an attempt to return better dpi value on devices where xdpi and ydpi are totally wrong. However this turned out to be quite inconsistent because more devices than expected have xdpi (and ydpi) different than densityDpi.

    We are going to make Screen.dpi to always return densityDpi value. This may change how your existing games look. If you'll encounter this issue, or if you need a more precise dpi value, you can use the following C# script to get dpi value in an old way. Just keep in mind that on some devices xdpi and ydpi values are totally wrong.

    Code (CSharp):
    1. float GetDPI()
    2. {
    3.     AndroidJavaClass activityClass = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
    4.     AndroidJavaObject activity = activityClass.GetStatic<AndroidJavaObject>("currentActivity");
    5.  
    6.     AndroidJavaObject metrics = new AndroidJavaObject("android.util.DisplayMetrics");
    7.     activity.Call<AndroidJavaObject>("getWindowManager").Call<AndroidJavaObject>("getDefaultDisplay").Call("getMetrics", metrics);
    8.  
    9.     return (metrics.Get<float>("xdpi") + metrics.Get<float>("ydpi")) * 0.5f;
    10. }
     
    Last edited: Jun 29, 2016
    Nit_Ram, Lesh48, konsnos and 2 others like this.
  2. chidl003

    chidl003

    Joined:
    Dec 7, 2016
    Posts:
    1
    When you say "some devices xdpi and ydpi values are totally wrong", can you elaborate? Can you please provide some examples of deviceModels that have wrong values and how far off they are?
    Also do any of the iOS devices suffer from Screen.dpi being incorrect that you are aware of?
    Our app is very dependent on drawing elements on the screen in an exact physical size so having an accurate dpi is crucial.
     
  3. JuliusM

    JuliusM

    Unity Technologies

    Joined:
    Apr 17, 2013
    Posts:
    835
    We haven't done thorough testing on all devices and the testing was done 2 years ago, but the results we got back then were as follows:
    Everything is fine, issue not reproducible: Google Nexus 5 (Android 5.1), LG G3 (Android 4.4.2), Samsung Galaxy S4 (Android 4.4.2), Motorola Droid Bionic (Android 2.3.4), LG Optimus L7 (Android 4.0.3), Sony Xperia U (Android 2.3.7).
    Issue reproducible: Redmi returned dpi 160 should be ~312, Samsung Galaxy M Style (Android 2.3.7 K) returned dpi 160 should be ~233, HTC One X (Android 4.2.2) returned dpi 213 should be ~312, LG Optimus L5 II (Android 4.1.2) returned dpi 240 should be ~233.
    As I've said, the testing was done 2 years ago. Some of those devices might have this issue fixed with Android updates as well as new devices might not have this issue at all, but we don't have any data on this. You will have to do your own testing to find that out.
    All iOS devices should return correct dpi value, because there are just a few dpi variants in iOS ecosystem and Apple has standardised them there.
     
  4. cstenson

    cstenson

    Joined:
    Dec 10, 2015
    Posts:
    3
    Hi! I have run into the same problem. I need to know the total screensize. Can say that Screen.dpi returns a wrong value on Nexus 5X resulting in the screen precived as a 6.2" screen becoming 33% bigger than the actual screen area. Using the function above makes it work fine :)
     
  5. PZ2100

    PZ2100

    Joined:
    May 27, 2017
    Posts:
    21
    xdpi and ydpi fields also return incorrect values (e.g. on my Samsung Galaxy Mini 3). These values are set by the manufacturer and aren't used by anything in the OS. See Google's explanation on this here:
    https://groups.google.com/forum/#!topic/android-developers/g56jV0Hora0
    As Google says, the physical size simply can't be known. It will always be wrong on some devices. And it doesn't matter if Screen.dpi in Unity is used or any kind of direct polling from Android thru Java is used. This platform isn't capable of returning its screen size.
     
    maxrevilo likes this.
  6. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,251
    While this is misleading for anyone who wants exact physical sizing it otherwise sounds sensible as it will follow the manufacturers guidelines - on android I read the screen.dpi and render UI at a virtual 160dpi resolution thus I seem to get exactly what android material wants in terms of sizing - using their dp sizing recomendations.

    On iOS is there not something similar where UI is a little bigger or smaller or it does weird scaling depending on device, with its native UI?

    I really don't like the docs on Screen.dpi which say: "Note that on Android this returns densityDpi which is a logical bucket containing a range of dpi values"
    What does that even mean? Cut the logical bucket stuff and link to android docs maybe
     
    jbecana and nicloay like this.
  7. andyz

    andyz

    Joined:
    Jan 5, 2010
    Posts:
    2,251
    There is actually a major issue on Android if you do not consider it - the screen zoom setting (part of android) affects the dpi returned by Screen.dpi so it is by no means consistent on a given device!!
    If you scale your UI based on Screen.dpi and the user changes the android zoom level then everything is going to be bigger or smaller the next time they run your app or you check the dpi (you really need to check for dpi changes while the app is running in case they change this setting!!)

    All of this means reproducing the native UI scaling is easier, but not exactly well documented on Unity's side...
    It also means Screen.dpi is not at all reliable on android if you really need actual physical size.
     
    Salvador-Romero likes this.
  8. martinasenovdev

    martinasenovdev

    Joined:
    May 7, 2017
    Posts:
    67
    hello, is there still a not reliable way to determine physical screen size in inches/cm as per September 2018

    P.S. Is this solution relevant:
    https://answers.unity.com/questions/161281/is-there-a-way-to-android-physical-screen-size.html

    What bothers me most is that xDPI (density of pixels in horizontal direction) might be different from yDPI (density of pixels in vertical direction). First time I hear there is such thing!

    Another P.S:
    does current Unity versions 2018.x.x use 'densityDpi' property or the average of 'xDpi' and 'yDpi' as mentioned above. Seems like 'densityDpi' is much more reliable
     
    Last edited: Sep 30, 2018
  9. AbandonedCart

    AbandonedCart

    Joined:
    Mar 4, 2014
    Posts:
    72
    One thing to consider is devices, such as the newer ones in the Samsung S / Note series, have a fullscreen mode. Basically, you may be running with a 16:10 resolution or 18.5:9, depending on user preference.

    heightPixels and widthPixels return the 16:10 resolution values.

    http://answers.unity.com/answers/927187/view.html will allow getting the 18.5:9 values.
     
    Last edited: Nov 21, 2018
  10. Gillissie

    Gillissie

    Joined:
    May 16, 2011
    Posts:
    305
    I would love to have Screen.dpi report correct values for iOS. It's wrong even as of Unity 2018.
     
  11. sq_eye

    sq_eye

    Joined:
    Aug 27, 2021
    Posts:
    2

    I need to get the ppi for my android device so that I can display the same size picture on the different screen. For example, the same picture displayed on the ppi screen is 0.32mm.

    The current official document,

    https://docs.unity3d.com/cn/2018.2/ScriptReference/Screen-dpi.html

    And https://forum.unity.com/threads/screen-dpi-on-android.414014/

    The test results are different from the actual results.

    The test method is to measure the distance of 3cm horizontally and vertically, so as to obtain the number of pixels of 3cm horizontally and vertically, and finally calculate ppi.

    If the number of pixels 3cm across and 3cm up and down is 558, the ppi can be calculated by 558 squared +558 squared =A, and then the square root of the value A is to obtain the value B, and finally the corresponding ppi can be calculated.

    I believe that what I measured is the correct value. After verification, I found that using the measured value can also display pictures with the same visual size on the different screen.

    My question is, is there a better way to get this ppi than by measuring it with a ruler?

    Code (CSharp):
    1. public static float GetPPI(string horizontal, string vertical)
    2.     {
    3.         float ppi = 0;
    4.  
    5.         if (float.TryParse(horizontal, out float h) && float.TryParse(vertical, out float v))
    6.         {
    7.             var standardInch = Mathf.Sqrt(Mathf.Pow(3.0f / CM_INCH, 2) + Mathf.Pow(3.0f / CM_INCH, 2));
    8.  
    9.             ppi = Mathf.CeilToInt(Mathf.Sqrt(Mathf.Pow(h, 2) + Mathf.Pow(v, 2)) / standardInch);
    10.         }
    11.  
    12.         if (ppi <= 0)
    13.         {
    14.             Debug.LogError($"ppi<=0 horizontal:{horizontal},vertical:{vertical}");
    15.             ppi = 287;
    16.         }
    17.  
    18.         return ppi;
    19.     }
     
  12. strikeric11

    strikeric11

    Joined:
    Sep 7, 2016
    Posts:
    13
    any solution for this?
     
  13. Thaina

    Thaina

    Joined:
    Jul 13, 2012
    Posts:
    1,158
    Do we have any more reliable way for this?

    Is it impossible for unity to have xdpi and ydpi property for every platform? In fact, is it impossible for unity to have a property `IsPhysicalSizeAvailable` and `PhysicalScreenSize` as Vector2 in DisplayInfo?

    We can check for availability and fallback to width|height / DPI. But in various OS and platform there are api to get physical monitor size and I wish this api should be implemented in unity directly. It would be crucial in MR and spatial computing