开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜