Is there any way to tell what folder a drawable resource was inflated from?
Does anyone know of a way to tell which folder Android system will resolve to when I request a particular drawable from the Resources (drawable-long
vs. drawable-notlong
, for example)? I want to make sure it's loading resources the way I would expect it to (for instance, to make sure the Tattoo is really ldpi
and not mdpi
since it's right on the borderline).
I could always print out the intrinsic size of t开发者_Python百科he drawable after I fetch it from Resources, and check that against the various image sizes I have, but that's kind of a pain. Plus, my company allows its clients to skin their app before it's released, so after it's been skinned I won't be able to rely on that method.
I tried using Resources.getName(resId)
but that doesn't give the folder name, and as far as I know you can get a AssetFileDescriptor
for the resource but you can't get an actual filename.
UPDATE:
Since asking this question I have discovered that you can access many of the resource qualifier names through the Configuration
and DisplayMetrics
classes (both accessible via getResources()
). DisplayMetrics
can give you the ldpi
/mdpi
/hdpi
designation, and Configuration
can give you small
/normal
/large
screen size, long
/notlong
aspect ratio, locale, mobile network codes, and other hardware information. However, this still does not positively confirm that you are getting the resources you expect if you have a complicated resource set. It also does not protect you from bugs that report the incorrect values, like the Motorola Droid bug where the DisplayMetrics
reports the wrong xdpi
and ydpi
(it reports 96dpi where the real value is more like 265dpi! Terrible bug.).
A different approach would be to use two different images, with the same name, red in one resource folder blue in the other. When it inflates, you'll be able to see which one it is coming from.
If you really want to go crazy, make an image saying "ldpi" or "xhdpi" etc for each folder and when you start your project, you can note which ones came up for each device you wanted explicit testing for.
From Mark Allison, same idea but the values directory with strings that contains the name of the bucket it's in - it's less effort than creating images!
I know, you write, that you can go through all resources and compare sizes with the bitmap size. But I don't know, if you thought it same way as I did, so this may help you or someone else.
So this is the way I did it. At first I load sizes (in bytes) for all drawable images.
String defType = "drawable";
String drawableDirPrefix = "res/drawable";
SparseArray<SparseArray<String>> resourceDirs = new SparseArray<SparseArray<String>>();
ZipInputStream apk = null;
try {
apk = new ZipInputStream(new FileInputStream(getPackageResourcePath()));
ZipEntry entry = null;
while ((entry = apk.getNextEntry()) != null) {
String resourcePath = entry.getName();
if (resourcePath.startsWith(drawableDirPrefix)) {
int firstSlashPos = resourcePath.indexOf('/');
int lastSlashPos = resourcePath.lastIndexOf('/');
int dotPos = resourcePath.lastIndexOf('.');
String resourceDir = resourcePath.substring(firstSlashPos + 1, lastSlashPos);
String resourceName = resourcePath.substring(lastSlashPos + 1, dotPos);
int resourceId = getResources().getIdentifier(resourceName, defType, getPackageName());
int resourceSize = (int) entry.getSize();
SparseArray<String> resourceInfo = resourceDirs.get(resourceId);
if (resourceInfo == null) {
resourceInfo = new SparseArray<String>();
resourceInfo.append(resourceSize, resourceDir);
resourceDirs.append(resourceId, resourceInfo);
} else {
resourceInfo.append(resourceSize, resourceDir);
}
}
}
} catch (IOException e) {
Log.e("tag", "Error", e);
} finally {
if (apk != null) {
try {
apk.close();
} catch (IOException e) {
Log.e("tag", "Error", e);
}
}
}
Then, when I want to know the folder, I can compare the bitmap size to loaded sizes.
InputStream bitmapStream = null;
try {
int bitmapId = R.drawable.icon;
bitmapStream = getResources().openRawResource(bitmapId);
int bitmapSize = bitmapStream.available();
String bitmapDir = resourceDirs.get(bitmapId).get(bitmapSize);
Log.i("tag", bitmapDir);
} catch (Exception e) {
Log.e("tag", "Error", e);
} finally {
if (bitmapStream != null) {
try {
bitmapStream.close();
} catch (IOException e) {
Log.e("tag", "Error", e);
}
}
}
Well, this will work only if the images have different sizes. Or you can compare other things, like width, height, etc.
May be it is not, what you are looking for, but at least it satisfied my needs.
精彩评论