Other solutions here classify device screens into 4 buckets (small, normal, large, x-large).
For those looking to classify the device into the 6 drawable buckets instead, the following approach can be used.
The advantage of this approach is that it is not required to perform screen density calculations, which may differ from the way the OS does it. This solution instead relies purely on the OS to decide the density bucket. The disadvantage of this solution is that it requires creating redundant drawable resources, which is not elegant.
The are 6 screen density buckets:
- drawable-ldpi
- drawable-mdpi
- drawable-hdpi
- drawable-xhdpi
- drawable-xxhdpi
- drawable-xxxhdpi
The solution requires creating 6 drawables, and placing a copy into the density folders, so that each density folder is missing the correspondingly named resource. For example, pixel_not_ldpi.png, should be placed into all folders, except the drawable-ldpi folder.
resources
- pixel_not_ldpi.png // copy to the 5 folders, except drawable-ldpi
- pixel_not_mdpi.png // copy to the 5 folders, except drawable-mdpi
- pixel_not_hdpi.png // etc..
- pixel_not_xdpi.png // etc..
- pixel_not_xxdpi.png // etc..
- pixel_not_xxxdpi.png // etc..
Notes:
- Do not place any of these resources inside the general 'drawable' folder.
- It's best to create a 1x1 pixel png image, which is only 68kb, and is smaller than a 1x1 jpeg image. Also make sure to strip meta data from these images to save space.
Once the images are placed, write a helper method which attempts to load each of these resources using 6 try/catch blocks. Catch the Resources.NotFoundException. Whichever resource throws the exception, that is the screen density of the device. This works with Android App Bundles.
It's not an ideal solution, but it answers the question comprehensively, and unlike other solutions, which involve arithmetic, it relies purely on the OS to determine density.
Edge Case: incorrect side-loading of App Bundle
Some users side-load their apps, by downloading them from outside the play store, or otherwise, and can make the mistake of downloading only a part of the resources present in the whole app bundle. Such users are able to install and launch the app, but some resources might be missing, which would cause a resource not found exception to fire inside one of our try/catch blocks above, making it impossible to determine whether the resource was missing intentionally, or unintentionally (due to an incomplete app bundle).
To differentiate the two cases, simply use the same approach. Place another resource, pixel.png into all 6 density drawable folders, and try to load it using a try/catch. If it throws, then the app was downloaded incorrectly.
Enjoy