185

I need to pass a resource ID to a method in one of my classes. It needs to use both the id that the reference points to and also it needs the string. How should I best achieve this?

For example:

R.drawable.icon 

I need to get the integer ID of this, but I also need access to the string "icon".

It would be preferable if all I had to pass to the method is the "icon" string.

3
  • is it possible in similar way to getId of files saved to internal storage? I have problem cause I should supply array of ids instead of locations to my gallery (thought it's adapter).. thanks Commented Feb 24, 2012 at 10:16
  • @Ewoks: They don't have IDs on internal storage. They're just images, if anything you need to load them into a bunch of Image objects and pass those, you might want to start a new question though. Commented Feb 27, 2012 at 10:43
  • possible duplicate of How to get a resource id with a known resource name? Commented Jun 11, 2015 at 13:17

16 Answers 16

200

@EboMike: I didn't know that Resources.getIdentifier() existed.

In my projects I used the following code to do that:

public static int getResId(String resName, Class<?> c) { try { Field idField = c.getDeclaredField(resName); return idField.getInt(idField); } catch (Exception e) { e.printStackTrace(); return -1; } } 

It would be used like this for getting the value of R.drawable.icon resource integer value

int resID = getResId("icon", R.drawable.class); // or other resource class 

I just found a blog post saying that Resources.getIdentifier() is slower than using reflection like I did. Check it out.

WARNING: This solution will fail in the release build if code/resource shrinking is enabled as suggested by Google: https://developer.android.com/build/shrink-code
Also, it might fail for some other cases, e.g. when you have <string name="string.name">…</string> the actual field name will be string_name and not the string.name

Sign up to request clarification or add additional context in comments.

16 Comments

@Macarse: Presently, getIdentifier() has to do two reflection lookups. In your example above, getIdentifier() would use reflection to get Drawable.class, then another reflection lookup to get the resource ID. That would account for the speed difference. That being said, neither are especially quick and therefore really need to be cached (particularly if used in a loop, or for rows in a ListView). And the reflection approach's big problem is that it makes assumptions about the internals of Android that might change in some future release.
@CommonsWare: That's right. I was checking how android implemented and it ends ups being a native call. gitorious.org/android-eeepc/base/blobs/… => gitorious.org/android-eeepc/base/blobs/…
I would use an integer array with the IDs instead. Using strings for IDs doesn't sound like the right approach.
Why the context parameter?
Calling should be getId("icon", R.drawable.class); not getResId("icon", context, Drawable.class);
|
98

You can use this function to get resource ID.

public static int getResourceId(String pVariableName, String pResourcename, String pPackageName) { try { return getResources().getIdentifier(pVariableName, pResourcename, pPackageName); } catch (Exception e) { e.printStackTrace(); return -1; } } 

So if you want to get for drawable call function like this

getResourceId("myIcon", "drawable", getPackageName()); 

and for string you can call it like this

getResourceId("myAppName", "string", getPackageName()); 

Read this

4 Comments

What is the point of making a function that simply calls another one and "handles" a possible exception? Call getResources().getIdentifier() directly.
Upvoted for clarifying how to pass in the type to get different kinds or resources. The android dev documentation does not have details and "id" from a prior answer does not work for strings.
Is there also the opposite? Meaning from R.string.some_string to "some_string" ?
Use of getIdentifier is discouraged because resource reflection makes it harder to perform build optimizations and compile-time verification of code
42

This is based on @Macarse answer.

Use this to get the resources Id in a more faster and code friendly way.

public static int getId(String resourceName, Class<?> c) { try { Field idField = c.getDeclaredField(resourceName); return idField.getInt(idField); } catch (Exception e) { throw new RuntimeException("No resource ID found for: " + resourceName + " / " + c, e); } } 

Example:

getId("icon", R.drawable.class); 

Comments

29

How to get an application resource id from the resource name is quite a common and well answered question.

How to get a native Android resource id from the resource name is less well answered. Here's my solution to get an Android drawable resource by resource name:

public static Drawable getAndroidDrawable(String pDrawableName){ int resourceId=Resources.getSystem().getIdentifier(pDrawableName, "drawable", "android"); if(resourceId==0){ return null; } else { return Resources.getSystem().getDrawable(resourceId); } } 

The method can be modified to access other types of resources.

2 Comments

now .getResources().getDrawable is deprecated if(android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP){ return mContext.getDrawable(resourceId); } else { return mContext.getResources().getDrawable(resourceId); }
also use of getIdentifier is discouraged because resource reflection makes it harder to perform build optimizations and compile-time verification of code
14

If you need to pair a string and an int, then how about a Map?

static Map<String, Integer> icons = new HashMap<String, Integer>(); static { icons.add("icon1", R.drawable.icon); icons.add("icon2", R.drawable.othericon); icons.add("someicon", R.drawable.whatever); } 

Comments

10

Simple method to get resource ID:

public int getDrawableName(Context ctx, String str){ return ctx.getResources().getIdentifier(str,"drawable", ctx.getPackageName()); } 

2 Comments

Would be better if you just give some more information to your answer.
Use of getIdentifier is discouraged because resource reflection makes it harder to perform build optimizations and compile-time verification of code
9

I did like this, it is working for me:

 imageView.setImageResource(context.getResources(). getIdentifier("drawable/apple", null, context.getPackageName())); 

2 Comments

Thanks. Works as expected. I used the following: view.context.resources.getIdentifier("drawable/item_car_$position", null, context.packageName).
Use of getIdentifier is discouraged because resource reflection makes it harder to perform build optimizations and compile-time verification of code
8

You can use Resources.getIdentifier(), although you need to use the format for your string as you use it in your XML files, i.e. package:drawable/icon.

1 Comment

My answer below is the reverse of this. Pass in the resource id, and then use getResourceEntryName(id) to find the string name. No messing to find "icon" from the longer text.
8

The Kotlin approach

inline fun <reified T: Class<*>> T.getId(resourceName: String): Int { return try { val idField = getDeclaredField (resourceName) idField.getInt(idField) } catch (e:Exception) { e.printStackTrace() -1 } } 

Usage:

val resId = R.drawable::class.java.getId("icon") 

Or:

val resId = R.id::class.java.getId("viewId") 

2 Comments

This works but what exactly is this doing? It has a very weird syntax. How is it performance wise?
This doesn't work with proguard/minify enabled.
7

Since you said you only wanted to pass one parameter and it did not seem to matter which, you could pass the resource identifier in and then find out the string name for it, thus:

String name = getResources().getResourceEntryName(id); 

This might be the most efficient way of obtaining both values. You don't have to mess around finding just the "icon" part from a longer string.

Comments

7

A simple way to getting resource ID from string. Here resourceName is the name of resource ImageView in drawable folder which is included in XML file as well.

int resID = getResources().getIdentifier(resourceName, "id", getPackageName()); ImageView im = (ImageView) findViewById(resID); Context context = im.getContext(); int id = context.getResources().getIdentifier(resourceName, "drawable", context.getPackageName()); im.setImageResource(id); 

Comments

2

In your res/layout/my_image_layout.xml

<LinearLayout ...> <ImageView android:id="@+id/row_0_col_7" ...> </ImageView> </LinearLayout> 

To grab that ImageView by its @+id value, inside your java code do this:

String row = "0"; String column= "7"; String tileID = "row_" + (row) + "_col_" + (column); ImageView image = (ImageView) activity.findViewById(activity.getResources() .getIdentifier(tileID, "id", activity.getPackageName())); /*Bottom code changes that ImageView to a different image. "blank" (R.mipmap.blank) is the name of an image I have in my drawable folder. */ image.setImageResource(R.mipmap.blank); 

Comments

1

In MonoDroid / Xamarin.Android you can do:

 var resourceId = Resources.GetIdentifier("icon", "drawable", PackageName); 

But since GetIdentifier it's not recommended in Android - you can use Reflection like this:

 var resourceId = (int)typeof(Resource.Drawable).GetField("icon").GetValue(null); 

where I suggest to put a try/catch or verify the strings you are passing.

Comments

1

For getting Drawable id from String resource name I am using this code:

private int getResId(String resName) { int defId = -1; try { Field f = R.drawable.class.getDeclaredField(resName); Field def = R.drawable.class.getDeclaredField("transparent_flag"); defId = def.getInt(null); return f.getInt(null); } catch (NoSuchFieldException | IllegalAccessException e) { return defId; } } 

Comments

0
 ImageId.substring(0, ImageId.length()-1); imageMessage = (ImageView) findViewById(R.id.imageMessage); int resID = getResources().getIdentifier(ImageId , "drawable", getPackageName()); imageMessage.setImageResource(resID); 

Dont forget to add substring

Comments

0
 //Inside main class int resID = getId(buttonID); findViewById(resID); 

Use the method below

 private int getId (String resourceName) { try { Field idField = R.id.class.getDeclaredField(resourceName); return idField.getInt(idField); } catch (Exception e) { throw new RuntimeException("No resource ID found for: " + resourceName + " / ", e); } } 

For ID use R.id.class

For Drawable Use R.Drawable.class

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.