Android Emulator Reports 600x1024 MDPI as XLarge?

2019-02-05 01:55发布

问题:

I am currently trying to test an existing application for compatibility with the soon to be released Amazon Kindle Fire tablet. They say to set the emulator at 600x1024 and LCD Density to 169 (https://developer.amazon.com/help/faq.html?ref_=pe_132830_21362890#KindleFire although in email they said 160 instead of 169) and that it should report out as being "large" and not "xlarge" (this I have from a back and forth email exchange with their support team where I'm complaining it does not work).

Google seems to support this as being true in their section on testing for multiple screen sizes when they list this resolution and MDPI as being "large" (http://developer.android.com/guide/practices/screens_support.html#testing). However, anytime I include a "layout-xlarge" folder along with the "layout-large", the emulator is always loading the "xlarge". If I change the LCD Density to something like 240, it loads "large" instead of "xlarge", but that is not supposed to be correct and I'm worried that means it won't work on the final device. To test this, I took the API-10 sample of "Multi-Res" and created a series of layout folders described above and every time it loaded "xlarge" if it was there and would load "large" if there was not an "xlarge".

So, my question is if I'm reading the documentation correctly or if my emulator is somehow messed up as the folks at Amazon are insisting it should be reporting as "large", which if that were true it would never load "xlarge" right?

Here is what I have in the manifest in the example Multi-Res that I modified to test this:

<?xml version="1.0" encoding="utf-8"?>
<manifest
  xmlns:android="http://schemas.android.com/apk/res/android"
  package="com.example.android.multires"
  android:versionCode="1"
  android:versionName="1.0">

  <uses-permission
    android:name="android.permission.INTERNET"/>

  <application
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name">

    <activity
      android:name=".MultiRes"
      android:label="@string/app_name">
      <intent-filter>
        <action
          android:name="android.intent.action.MAIN"/>
        <category
          android:name="android.intent.category.LAUNCHER"/>
      </intent-filter>
    </activity>
  </application>

  <uses-sdk android:minSdkVersion="4" />

  <supports-screens android:anyDensity="true"
                    android:xlargeScreens="true"
                    android:largeScreens="true"
                    android:normalScreens="true"
                    android:smallScreens="true" />

</manifest>

回答1:

This seems to be a bug in the documentation. If we look at the actual code that is used to calculate screen size, we can see that a 600x1024 screen at 160 dpi will indeed be considered as xlarge.

Don't take my word for it. The implementation is in WindowManagerService.computeNewConfigurationLocked() (warning for slow JavaScript). The interesting bits are as follows. The screen size in pixels is scaled based on density:

    longSize = (int)(longSize/dm.density);
    shortSize = (int)(shortSize/dm.density);

For a an mdpi (160 dpi) screen, dm.density will be 1.0. For hdpi (240 dpi) it will be 1.5. In our case we have an mdpi screen. So after this code has run, longSize == 1024 and shortSize == 600. Shortly after, we reach this code:

    // What size is this screen screen?
    if (longSize >= 800 && shortSize >= 600) {
        // SVGA or larger screens at medium density are the point
        // at which we consider it to be an extra large screen.
        mScreenLayout = Configuration.SCREENLAYOUT_SIZE_XLARGE;
    } else if ( // ...

which with our values of longSize and shortSize means that mScreenLayout will be assigned Configuration.SCREENLAYOUT_SIZE_XLARGE, in other words that the screen will be considered 'xlarge'. It is interesting to note that if the screen was one pixel smaller on the short side, it would only be considered as 'large'.

So, you are reading the documentation correctly, but as far as I can see, the documentation is wrong and your emulator is just fine.