Android, Getting Resource Id from String

Android, getting resource ID from string?

@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.

Android, get resource id by string?

As someone mentioned in the comments, you can use the

getIdentifier(String name, String defType, String defPackage)

For you case, like this

int resId = getResources().getIdentifier("signal_" + mSignalStrength, "drawable", getPackageName());

How to get a resource id with a known resource name?

It will be something like:

R.drawable.resourcename

Make sure you don't have the Android.R namespace imported as it can confuse Eclipse (if that's what you're using).

If that doesn't work, you can always use a context's getResources method ...

Drawable resImg = this.context.getResources().getDrawable(R.drawable.resource);

Where this.context is intialised as an Activity, Service or any other Context subclass.

Update:

If it's the name you want, the Resources class (returned by getResources()) has a getResourceName(int) method, and a getResourceTypeName(int)?

Update 2:

The Resources class has this method:

public int getIdentifier (String name, String defType, String defPackage) 

Which returns the integer of the specified resource name, type & package.

How to convert String to its resource ID (Android Studio)

You can not get identifier by value, but you can make your identifier name look like a value and get it by string name,

So what I suggest,

use your String resource name something like, resource_150

<string name="resource_150">150</string>

Now here resource_ is common for your string entries in string.xml file, so
in your code,

String value = "150";
int resourceId = this.getResources().
getIdentifier("resource_"+value, "string", this.getPackageName());

Now resourceId value is as equivalent to R.string.resource_150

Just make sure here this represent your application context. In your case MainActivity.this will work.

How to get the id of a string resource associated with a TextView?

The only workaround I could was to match the +id of the TextView instances in the layout xml with the name of the string, then use Resources to get pair the two:

/**
* finds a string id matching a text view id name and returns the value
* @param textView - text view
* @param context - the context
* @param locale - the locale string
* @return String - resource string if found, empty string otherwise
*/
public static String getTextViewStringFromResources(TextView textView,Context context,String locale){
String result = "";
final int textViewID = textView.getId();

if(textViewID <= 0){
Log.e(TAG,"invalid id for textView " + textView + " text = " + textView.getText());
result = textView.getText().toString();
return result;
}
//get resources (re-usable)
final Resources resources = getLocalizedResources(context,locale);
// get textViews id
final String entryName = resources.getResourceEntryName(textView.getId());
// get the string id !! must match the textview id !!
final int stringID = resources.getIdentifier(entryName,"string",context.getPackageName());
//return string value for string id found by textview id
try{
result = resources.getString(stringID);
}catch (Resources.NotFoundException e){
Log.e(TAG,"couldn't find a string id for " + entryName);
Log.e(TAG,e.getMessage());
}
return result;
}

//!! requires minSDK 17
@NonNull
public static Resources getLocalizedResources(Context context, String locale) {
Locale desiredLocale = new Locale(locale);
Configuration conf = context.getResources().getConfiguration();
conf.setLocale(desiredLocale);
Context localizedContext = context.createConfigurationContext(conf);
return localizedContext.getResources();
}

The swapping is partially based on Gunhan Sancar's method of swapping text field.

This works but it pretty much a hack.

Eventually I needed to also change the Google Handwriting Input language programmatically and for that Juuso's ADB Change Language app came in super handy.

For reference, here's a function using Juuso's approach:

final String TAG = "ChangeLanguage"
//change language utils "kindly borrowed" from net.sanapeli.adbchangelanguage: brilliant little app!

/**
* updates a Configuration with a list of Locales
* @param configuration - a configuration to updated
* @param arrayList - an ArrayList of Locale instances
* @return the updated configuration
*/
@TargetApi(24)
public static Configuration addLocalesToConfiguration(Configuration configuration, ArrayList<Locale> arrayList) {
configuration.setLocales(new LocaleList((Locale[]) arrayList.toArray(new Locale[arrayList.size()])));
return configuration;
}

/**
* Change the system language
* @param lanaguageList - a list of Locale instances to change to
*/
public static void changeLanguages(ArrayList<Locale> lanaguageList){
try {
Class cls = Class.forName("android.app.ActivityManagerNative");
Method method = cls.getMethod("getDefault", new Class[0]);
method.setAccessible(true);
Object invoke = method.invoke(cls, new Object[0]);
method = cls.getMethod("getConfiguration", new Class[0]);
method.setAccessible(true);
Configuration configuration = (Configuration) method.invoke(invoke, new Object[0]);
configuration.getClass().getField("userSetLocale").setBoolean(configuration, true);
if (VERSION.SDK_INT >= 24) {
configuration = addLocalesToConfiguration(configuration, lanaguageList);
} else {
configuration.locale = (Locale) lanaguageList.get(0);
}
Method method2 = cls.getMethod("updateConfiguration", new Class[]{Configuration.class});
method2.setAccessible(true);
method2.invoke(invoke, new Object[]{configuration});
Log.d(TAG,"locale updated to" + lanaguageList.get(0).toString());
} catch (Exception e) {
Log.e(TAG,"error changing locale (double check you're granted permissions to the app first: pm grant your.app.package.here android.permission.CHANGE_CONFIGURATION )");
e.printStackTrace();
}
}

Remember to grant CHANGE_CONFIGURATION to your app.

This is tested with Android 7.1.1 but bare in mind that it will fail on Android 8.0 (and potentially upwards) as getConfiguration is not found (the API is different) under certain build conditions.

The method expects an ArrayList of Locale objects with the language you want to change to on top:
e.g.

ArrayList<Locale> fr = new ArrayList<Locale>();
fr.add(new Locale("fr"));
fr.add(new Locale("en"));

ArrayList<Locale> en = new ArrayList<Locale>();
en.add(new Locale("en"));
en.add(new Locale("fr"));

Make sure the Languages are installed on the devices as well.

If you have other improvement suggestions I'd be more than happy to update the answer

Android: How do I get string from resources using its name?

The link you are referring to seems to work with strings generated at runtime. The strings from strings.xml are not created at runtime.
You can get them via

String mystring = getResources().getString(R.string.mystring);

getResources() is a method of the Context class. If you are inside a Activity or a Service (which extend Context) you can use it like in this snippet.

Also note that the whole language dependency can be taken care of by the android framework.
Simply create different folders for each language. If english is your default language, just put the english strings into res/values/strings.xml. Then create a new folder values-ru and put the russian strings with identical names into res/values-ru/strings.xml. From this point on android selects the correct one depending on the device locale for you, either when you call getString() or when referencing strings in XML via @string/mystring.
The ones from res/values/strings.xml are the fallback ones, if you don't have a folder covering the users locale, this one will be used as default values.

See Localization and Providing Resources for more information.

Android get String Resource Id from value

I think what you're looking for is the following function that uses reflection:

fun getStringResourceName(stringToSearch: String): String? {
val fields: Array<Field> = R.string::class.java.fields
for (field in fields) {
val id = field.getInt(field)
val str = resources.getString(id)
if (str == stringToSearch) {
return field.name
}
}
return null
}

so by invoking getStringResourceName("Dummy Text") the function should return "text1".

The function can be even changed a bit to return the resource id corresponding to "Dummy Text":

fun getStringResourceId(stringToSearch: String): Int {
val fields: Array<Field> = R.string::class.java.fields
for (field in fields) {
val id = field.getInt(field)
val str = resources.getString(id)
if (str == stringToSearch) {
return id
}
}
return -1
}

so in this case by calling getStringResourceId("Dummy Text") you can get something like 2131886277 (the latter number is just an example).

How to get drawable resource id from string name base on current app theme in android (dark/light theme)

Short answer: Don´t use setImageResource(Int id). Get the themed drawable with getResources().getDrawable(Int id, Resources.Theme theme) and use setImageDrawable(Drawable drawable) instead.

Explanation: Themed resources don´t have a particular id suffix/preffix; is the same ID across all themes, to avoid breaking the app. The theme is supposed to be applied beforehand, allowing all the theme-sensitive values to be replaced by the theme´s version. Usually, a visual context (activity) contains the reference, but depending on how/when you are trying to get the resource, you may get one with a different theming (application context for example will not have theme references), and because that, we have getDrawable(Int id, Resources.Theme theme) since api 22. That´s the root of your problem. When you call setImageDrawable(Int res), the imageView executes this block:

private void resolveUri() {
if (mDrawable != null) {
return;
}
if (getResources() == null) {
return;
}
Drawable d = null;
if (mResource != 0) {
try {
d = mContext.getDrawable(mResource);
} catch (Exception e) {
Log.w(LOG_TAG, "Unable to find resource: " + mResource, e);
// Don't try again.
mResource = 0;
}
} else if (mUri != null) {
d = getDrawableFromUri(mUri);
if (d == null) {
Log.w(LOG_TAG, "resolveUri failed on bad bitmap uri: " + mUri);
// Don't try again.
mUri = null;
}
} else {
return;
}
updateDrawable(d);
}

as you can see, it uses the deprecated Context.getDrawable(Int id) method. So the drawable will, at best, match the theme reference in the context, if any. In your widget, the call likely happens before the rest of the change happens. So, specify the desired theme instead and you´ll be okay.

How can I get resource Id from String value(not name)

There's no method to lookup by value as it is not guaranteed to be unique. You need to iterate over all i.e. strings and compare values yourself.



Related Topics



Leave a reply



Submit