128

If you use the Vector Asset wizard in Android Studio 1.5.0, any vector drawable XML you import using that wizard goes into res/drawable/.

However, the build/ directory, and the resulting APK show that those XML files get moved into a res/drawable-anydpi-v21/ resource directory. The -v21 part makes sense, as VectorDrawable is only supported on API Level 21+. However, -anydpi seems to be undocumented. I would have expected -nodpi, both for the original import destination and for where the build system elects to move it.

Has anyone seen official statements for what -anydpi means, and what its relationship is with -nodpi? I am looking for practical effects, not merely what some code comments hint at.

Muhammad Babar
  • 8,084
  • 5
  • 39
  • 56
CommonsWare
  • 986,068
  • 189
  • 2,389
  • 2,491
  • 5
    [Read the OP's own summary here.](https://commonsware.com/blog/2015/12/21/nodpi-anydpi-wtf.html) – Suragch Sep 16 '17 at 04:43
  • It is now 2023 and for the last 6 years I've been coming back to this question because I can't for the life of me remember which is which. I just know one of them is a fallback and the other is an override. Does anybody have a mnemonic to help remember this? – Subaru Tashiro Apr 27 '23 at 09:26

4 Answers4

133

nodpi

These are density-independent resources. The system does not scale resources tagged with this qualifier, regardless of the current screen's density.

For instance:

  • drawable-nodpi/dot.png

The dot will appear small on xxhdpi, big on ldpi.

However, the resource resolver will match a specific qualifier if it exists.

For instance

  • drawable-hdpi/eg.png
  • drawable-nodpi-v21/eg.xml

On a Lollipop (API 21) hdpi device, the bitmap is used.

On a Lollipop (API 21) xhdpi device, the vector is used.

anydpi

These resources take precedence in any dpi.

For instance

  • drawable-hdpi/eg.png
  • drawable-anydpi-v21/eg.xml

On a Lollipop (API 21) hdpi device, the vector is used.

On a Lollipop (API 21) xhdpi device, the vector is used.

Reference

Note: anydpi was added in change Ic3288d0236fe0bff20bb1599aba2582c25b0db32.

rds
  • 26,253
  • 19
  • 107
  • 134
  • 1
    That's not what I am seeing. Quoting my bounty: "Given two editions of the same resource in res/drawable-nodpi/ and res-drawable-mdpi/, I get the res/drawable-nodpi/ edition on a Nexus 5 running Android 6.0, which is an -xxhdpi device". Do you have a sample project that demonstrates the behavior that you are citing? – CommonsWare Dec 19 '15 at 12:30
  • That's because you used `drawable`. The bahaviour of the SDK can have changed. See [VectorDrawable: Android loads xhdpi PNG's instead of the vector resource](http://stackoverflow.com/questions/29001230/vectordrawable-android-loads-xhdpi-pngs-instead-of-the-vector-resource/32271246#32271246) – rds Dec 19 '15 at 12:49
  • "That's because you used drawable" -- so did you in your answer. Every single resource directory you cite in your answer is a `drawable` resource directory, just as both directories that I cited in my bounty are `drawable` resource directories. – CommonsWare Dec 19 '15 at 12:50
  • 1
    "On a xxxdpi, the framework will take the hdpi bitmap." -- that is specifically what is not happening, though my testing is on an `-xxhdpi` device. I have `res/drawable-mdpi/nodpi_and_m.png` and `res/drawable-nodpi/nodpi_and_m.xml`. On a Nexus 5, `-xxhdpi` device, the resource that is used is `res/drawable-nodpi/nodpi_and_m.xml`. According to your algorithm, and my expectations, `res/drawable-mdpi/nodpi_and_m.png` should be used. That is not what is happening. – CommonsWare Dec 19 '15 at 12:57
  • Also, note that the bug only applies if your project support pre-L devices. – rds Dec 19 '15 at 13:03
  • To be honest, I'm trying to reproduce the initial bug, and I have a hard time too. – rds Dec 19 '15 at 13:03
  • OK, I now grasp the difference, but the change description doesn't correspond to the actual behaviour observed today. – rds Dec 19 '15 at 14:13
  • I agree with your analysis. I have a sample app that demonstrates part of this behavior, and I'll write up a blog post about that Monday, linking to your answer. Many thanks! – CommonsWare Dec 19 '15 at 18:10
  • Seeing that now VectorDrawable is supported using the new supoprt library, where exactly should vectorDrawable files be put into, as they are now supported even on pre-Lollipop. – android developer Mar 05 '16 at 15:13
  • 3
    Bottom line: you should place vectors in `drawable-anydpi-v21`. If you have the support-vector-drawable library, you can place them in `drawable-anydpi` or simply `drawable`. – rds Mar 12 '16 at 18:38
  • Pls, check out this culprit (and the 1st comment): http://stackoverflow.com/questions/37999199/resourcesnotfoundexception-for-imageview-with-vector-drawable – WindRider Jun 23 '16 at 19:12
  • 2
    One big advantage to a drawable-nodpi folder is that scaling increases app memory use exponentially on the user end for high res screens (4x,16x,etc) with the default drawable folder. I found this out by checking the memory use of my game app while running with drawable vs drawable-nodpi graphic assets. I'm surprised this isn't documented anywhere. – Androidcoder Mar 17 '18 at 20:24
  • @rds What about `` or any non-Vector-Drawable xmls? – ericn Jun 15 '21 at 14:21
23

I use drawable-nodpi for everything, including plenty of large graphics for my game. An undocumented consequence of scaling up your graphics with -anydpi is that it increases memory use exponentially. So if you have a 1MB graphic in drawable, it will get scaled to 4MB, 16MB, 64MB, or more depending on the resolution of the user device. And device resolutions keep going up. That scaling up doesn't actually increase the sharpness of the graphic, of course. Normally drawing actions are available to direct how large each graphic should be in relation to screen size anyway, no need to bloat the app. I don't use multiple resolution specific draw folders either to save on memory and housekeeping.

Androidcoder
  • 4,389
  • 5
  • 35
  • 50
  • 5
    underrated answer. I encountered the same issue: had an image 100KB big, but frequently had OOM errors when loading it. The app crashed stating it could not allocate 18MB!!! Could not understand how these 100KB could be turned into 18MB, but it was actually the result of that scaling. Switching the image to no-dpi solved the issue. – Simon Ninon Jul 21 '18 at 00:19
  • 3
    The memory aspect is actually the most important when using drawable-nodpi (or mipmap-nodpi). – Uwe Post Feb 11 '21 at 09:07
18

The source code contains the following comments (line 639):

/**
 * Value for {@link #densityDpi} for resources that scale to any density (vector drawables).
 * {@hide}
 */
public static final int DENSITY_DPI_ANY = 0xfffe;

/**
 * Value for {@link #densityDpi} for resources that are not meant to be scaled.
 * {@hide}
 */
public static final int DENSITY_DPI_NONE = 0xffff;

Hope this clears out the confusion.

stkent
  • 19,772
  • 14
  • 85
  • 111
Vishavjeet Singh
  • 1,385
  • 11
  • 13
  • 12
    "Hope this clears out the confusion" -- not really. It is unclear what the difference is between "scale to any density" and "not meant to be scaled" mean in practice. Drawables in `-nodpi` directories most certainly get scaled based on size, according to whatever rules are in place for how the drawable is used. – CommonsWare Dec 08 '15 at 14:05
  • "Not meant to scaled" means they will not be scaled no matter what programmer does or what density is. – Vishavjeet Singh Dec 08 '15 at 14:15
  • I think they mean by the phrase "scale to any density" that they are referring to vector drawables which will **scale to fit** any density no matter how large the density is. – Vishavjeet Singh Dec 08 '15 at 14:21
  • ""Not meant to scaled" means they will not be scaled no matter what programmer does" -- they most certainly are scaled. If I put a 24 x 24 pixel image in `-nodpi`, and I apply that drawable to a 240x240 `ImageView`, depending upon the `ImageView` `scaleType`, the drawable will be scaled. They are not *additionally* scaled based upon density. `-anydpi` would appear to be the same thing. – CommonsWare Dec 08 '15 at 14:24
  • ""`-anydpi` would appear to be the same thing."" if `-anydpi` does the same thing then why was it introduced? – Vishavjeet Singh Dec 08 '15 at 14:36
  • There must be some reason behind `-anydpi` inclusion. – Vishavjeet Singh Dec 08 '15 at 14:40
  • 3
    it was added in https://android.googlesource.com/platform/frameworks/base/+/31245b4%5E!/, and from it you can learn it probably fixed some bug 17007265 – marcinj Dec 08 '15 at 16:02
  • 2
    @MarcinJędrzejewski: Actually, the "are chosen as the best match unless there is a configuration that matches the density requested exactly" comment on that commit gives me a clue. Thanks! – CommonsWare Dec 10 '15 at 13:25
16

nodpi: Resources for all densities. These are density-independent resources. The system does not scale resources tagged with this qualifier, regardless of the current screen's density.

anydpi: This qualifier matches all screen densities and takes precedence over other qualifiers. This is useful for vector drawables. Added in API Level 21.

dzikovskyy
  • 5,027
  • 3
  • 32
  • 43