Android: Get screen physical size, density and resolution

Keywords: Android Mobile Java

Resolution

It should be noted that getHeight() and getWidth() are not recommended and getSize() is recommended to replace them.
The prototype of this method is as follows:
  1. public void getSize(Point outSize) {  
  2.     synchronized (this) {  
  3.         updateDisplayInfoLocked();  
  4.         mDisplayInfo.getAppMetrics(mTempMetrics, mDisplayAdjustments);  
  5.         outSize.x = mTempMetrics.widthPixels;  
  6.         outSize.y = mTempMetrics.heightPixels;  
  7.     }  
  8. }  
A parameter is a return parameter that returns a Point of resolution. This Point is also relatively simple. We just need to focus on the two members x and y.
The usage is as follows:
  1. private void getDisplayInfomation() {  
  2.     Point point = new Point();  
  3.     getWindowManager().getDefaultDisplay().getSize(point);  
  4.     Log.d(TAG,"the screen size is "+point.toString());  
  5. }  
The results are as follows:
  1. D/MainActivity﹕ the screen size is Point(800, 1280)  

In addition, Display provides a getRealSize method, which is prototyped as follows:
  1. public void getRealSize(Point outSize) {  
  2.     synchronized (this) {  
  3.         updateDisplayInfoLocked();  
  4.         outSize.x = mDisplayInfo.logicalWidth;  
  5.         outSize.y = mDisplayInfo.logicalHeight;  
  6.     }  
  7. }  

The implementation of the two methods is different, but the return values of the two methods are the same in general. So what is the difference? Here are some experiments to verify it.
First, I set Acitvity to different theme s, such as:
  1. android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"  
  2. android:theme="@android:style/Theme.NoTitleBar.Fullscreen"  
The results are the same.

Next, turn my ActionBarActivity parent into ActionBarActivity, as follows:
public class MainActivity extends ActionBarActivity
It is expected that ActionBar will occupy some screens and dynamically set the image size in the Item of Listview in the program. By chance,
The results verify that in this case, getSize returns a different result.
The code is as follows:
  1. private void getDisplayInfomation() {  
  2.     Point point = new Point();  
  3.     getWindowManager().getDefaultDisplay().getSize(point);  
  4.     Log.d(TAG,"the screen size is "+point.toString());  
  5.     getWindowManager().getDefaultDisplay().getRealSize(point);  
  6.     Log.d(TAG,"the screen real size is "+point.toString());  
  7. }  

Log is as follows:
  1. D/MainActivity﹕ the screen size is Point(800, 1202)  
  2. D/MainActivity﹕ the screen real size is Point(800, 1280)  

If you can't easily reproduce it and don't rush it, be sure to use getRealSize() in order to get the relatively correct information.

II. Screen Size

The physical screen size of the device. Unlike a few years ago, the mobile screen is now too big to hold in one hand. Standard matching has already reached the age of 5 inch screen.
The so-called screen size refers to the length of the screen diagonal line in inches.
However, different screen sizes can use the same resolution, and the difference between them is different from density.
Next, we introduce the concept of density, DPI and PPI. Finally, we explain how to calculate the screen size according to the obtained Display information. This is a problem that has troubled me for a long time.

3. Screen Density

Screen density is closely related to the concept of DPI. DPI is dots-per-inch, the number of dots per inch. That is to say, the greater the density, the more points per inch of content.
There is a DisplayMetrics class under the android.util package to get density-related information.
Most importantly, the member densityDpi has the following common values:
  1. DENSITY_LOW = 120  
  2. DENSITY_MEDIUM = 160  //Default value  
  3. DENSITY_TV = 213      //TV dedicated  
  4. DENSITY_HIGH = 240  
  5. DENSITY_XHIGH = 320  
  6. DENSITY_400 = 400  
  7. DENSITY_XXHIGH = 480  
  8. DENSITY_XXXHIGH = 640  

Examples are as follows:
  1. private void getDensity() {  
  2.     DisplayMetrics displayMetrics = getResources().getDisplayMetrics();  
  3.     Log.d(TAG,"Density is "+displayMetrics.density+" densityDpi is "+displayMetrics.densityDpi+" height: "+displayMetrics.heightPixels+  
  4.         " width: "+displayMetrics.widthPixels);  
  5. }  

Log is as follows:
  1. the screen size is Point(1600, 2438)  
  2. the screen real size is Point(1600, 2560)  
  3. Density is 2.0 densityDpi is 320 height: 2438 width: 1600  

With this information, can we calculate the screen size?
Firstly, the diagonal length in pixels is obtained.
Then divide it by density (Dpi) to get the length of the diagonal line.
The code is as follows:
  1. private void getScreenSizeOfDevice() {  
  2.     DisplayMetrics dm = getResources().getDisplayMetrics();  
  3.     int width=dm.widthPixels;  
  4.     int height=dm.heightPixels;  
  5.     double x = Math.pow(width,2);  
  6.     double y = Math.pow(height,2);  
  7.     double diagonal = Math.sqrt(x+y);  
  8.   
  9.     int dens=dm.densityDpi;  
  10.     double screenInches = diagonal/(double)dens;  
  11.     Log.d(TAG,"The screenInches "+screenInches);  
  12. }  

Log is as follows:

  1. 01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ the screen size is Point(1600, 2438)  
  2. 01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ the screen real size is Point(1600, 2560)  
  3. 01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ Density is 2.0 densityDpi is 320 height: 2438 width: 1600 xdpi 338.666 ydpi 338.666  
  4. 01-13 16:35:03.026  16601-16601/com.linc.listviewanimation D/MainActivity﹕ The screenInches 9.112922229586951  

As Log can see, using heightPixels gives a value of 2483 instead of the correct 2560. This brings the result of 9.11 closer to the real screen size. Let's do it again with the right height.
  1. 01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ the screen size is Point(1600, 2560)  
  2. 01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ the screen real size is Point(1600, 2560)  
  3. 01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ Density is 2.0 densityDpi is 320 height: 2560 width: 1600 xdpi 338.666 ydpi 338.666  
  4. 01-13 16:39:05.476  17249-17249/com.linc.listviewanimation D/MainActivity﹕ The screenInches 9.433981132056605  
The result is 9.43 inches, and the real value is 8.91. If you change another device, the difference is more. It shows that the above calculation is wrong.
So what's wrong? densityDpi is the dots-per-inch unit commonly used by printers (hence also known as print resolution), rather than the number of pixels per inch. The concept of PPI is introduced below.

Four, PPI

Pixels per inch, that's the number of pixels per inch I want (also known as image sampling rate). With this value, the physical size of the screen can be derived from the above formula.
Fortunately, DisplayMetrics has two members, xdpi and ydpi, which are described as:
  1. //The exact physical pixels per inch of the screen in the X/Y dimension.  
Real physical PPI on the X/Y axis of the screen.
Yes!Got it!
To ensure the correct resolution, I still use getRealSize to get the screen width and high pixels. So, after modification, the code is as follows:
  1. private void getScreenSizeOfDevice2() {  
  2.     Point point = new Point();  
  3.     getWindowManager().getDefaultDisplay().getRealSize(point);  
  4.     DisplayMetrics dm = getResources().getDisplayMetrics();  
  5.     double x = Math.pow(point.x/ dm.xdpi, 2);  
  6.     double y = Math.pow(point.y / dm.ydpi, 2);  
  7.     double screenInches = Math.sqrt(x + y);  
  8.     Log.d(TAG, "Screen inches : " + screenInches);  
  9. }  
Log is as follows:
  1. 01-13 16:58:50.142  17249-17249/com.linc.listviewanimation D/MainActivity﹕ Screen inches : 8.914015757534717  

Five, DIP

Be careful not to be confused with the above DPI, which is Density Independent Pixel, literally translated into density-independent pixels.
The dp/dip we use in the layout file is it. dp is officially recommended because it calculates the corresponding pixels according to the density of your device.
The formula is: pixel = dip*density

It's important to note that we can't set the width and height of the control in Java code, but the unit that comes with it is the pixel. So if you dynamically change the size of the control,
Our task is to convert pixels to dp.
The example code is as follows:
  1. //pixel = dip*density;  
  2. private int convertDpToPixel(int dp) {  
  3.     DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();  
  4.     return (int)(dp*displayMetrics.density);  
  5. }  
  6.   
  7. private int convertPixelToDp(int pixel) {  
  8.     DisplayMetrics displayMetrics = mContext.getResources().getDisplayMetrics();  
  9.     return (int)(pixel/displayMetrics.density);  
  10. }   

Reference resources:

http://stackoverflow.com/questions/19155559/how-to-get-android-device-screen-size

Posted by OMorchoe on Sun, 07 Apr 2019 23:24:32 -0700