38

I have declared a string in my strings.xml file , and using it in my activity as R.string.compose_title. (setting it as title i.e. setTitle(R.id.compose_title)). Now in some case I want to edit the string and then use it to set the title . How can I do this ?

P.S. I need to change value of a single string only , So declaring a new strings.xml for each case(which are variable depending upon the user) using localization seems to be a lil inefficient .

Cœur
  • 37,241
  • 25
  • 195
  • 267
atuljangra
  • 457
  • 1
  • 5
  • 9
  • What do you mean edit the string? Are you trying to change the value in strings.xml so that the next time you getString you get the new value? or just change/append to the string for a specific use? – ByteMe Mar 12 '12 at 21:17
  • 1
    Why not "setTitle("CHANGED STRING"); Instead of editing the generated resources... String my_new_value = "CHANGED STRING"; setTitle(my_new_value); – braden Mar 12 '12 at 21:17
  • @ByteMe Changing or appending will also do the work . – atuljangra Mar 12 '12 at 22:01
  • @bradenV2 My app is supporting many languages , so I wanted to take a string from my strings.xml that's currently in use and change that , and then use that one – atuljangra Mar 12 '12 at 22:04
  • @atuljangra create separate folder with values-CC where cc is lang code - the u can use configuration to create specific language Resource object – ceph3us Jul 26 '17 at 03:11
  • @atuljangra Have you find any solution for this? – Rahul May 17 '22 at 10:32

8 Answers8

65

One thing what you have to understand here is that, when you provide a data as a Resource, it can't be modified during run time. For example, the drawables what you have in your drawable folder can't be modified at run time. To be precise, the "res" folder can't be modified programatically.

This applies to Strings.xml also, i.e "Values" folder. If at all you want a String which has to be modified at runtime, create a separate class and have your strings placed in this Class and access during run time. This is the best solution what I have found.

Andro Selva
  • 53,910
  • 52
  • 193
  • 240
  • But it works for some people http://stackoverflow.com/questions/6297159/change-button-text-and-action-android-development For me, sometimes it will crash if I change the text after use 'setContentView(~)' – Alston May 16 '14 at 03:13
  • to disabuse users I have included my answer to this question – ceph3us Mar 21 '17 at 19:29
  • It is so important to have the possibility of changing the resource file like the style. For example, when we want to change launcher theme that applicable even in the preview window. – Mohammad Afrashteh Jun 06 '18 at 07:20
  • drawable folder can't be modified at run time that not always true check this to see that you can may be for bitmap only – Mostafa Anssary Feb 09 '20 at 21:41
8

example howto:

how? by changing one variable reference to other reference

usage:

setRColor(pl.mylib.R.class,"endColor",pl.myapp.R.color.startColor);
// override app_name in lib R class  
setRString(pl.mylib.R.class,"app_name",pl.myapp.R.string.app_name);

base methods:

public static void setRColor(Class rClass, String rFieldName, Object newValue) {
    setR(rClass, "color", rFieldName, newValue);
}

public static void setRString(Class rClass, String rFieldName, Object newValue) {
    setR(rClass, "string", rFieldName, newValue);
}

// AsciiStrings.STRING_DOLAR = "$";
public static void setR(Class rClass, String innerClassName, String rFieldName, Object newValue) {
    setStatic(rClass.getName() + AsciiStrings.STRING_DOLAR  + innerClassName, rFieldName, newValue);
}

helper methods :

public static boolean setStatic(String aClassName, String staticFieldName, Object toSet) {
    try {
        return setStatic(Class.forName(aClassName), staticFieldName, toSet);
    } catch (ClassNotFoundException e) {
        e.printStackTrace();
        return false;
    }
}

public static boolean setStatic(Class<?> aClass, String staticFieldName, Object toSet) {
    try {
        Field declaredField = aClass.getDeclaredField(staticFieldName);
        declaredField.setAccessible(true);
        declaredField.set(null, toSet);
        return true;
    } catch (Exception e) {
        e.printStackTrace();
        return false;
    }
}

@bradenV2 My app is supporting many languages , so I wanted to take a string from my strings.xml that's currently in use and change that , and then use that one – atuljangra Mar 12 '12 at 22:04

ps the above solution is good for example when u want to inject some data in already compiled lib/jar. But if u want localize strings just make folder under res per LANG CODE like values-CC where cc is lang code (values-de,values-cs) etc

then u have 2 choices:

  1. "build in" system dependent language selection - based on device selected lang
  2. via create resources for configuration - you decide which lang show

like this:

configuration = new Configuration(resources.getConfiguration());
configuration.setLocale(targetLocale);
String localized = Context.createConfigurationContext(configuration)
    .getResources()
    .getString(resourceId);

enter image description here

ceph3us
  • 7,326
  • 3
  • 36
  • 43
6

I don't think you can programmatically customize the R class as it is built by ADT automatically.

Michael Alan Huff
  • 3,462
  • 3
  • 28
  • 44
waqaslam
  • 67,549
  • 16
  • 165
  • 178
1

Use SharedPreferences instead of a Java class. It will give you more versatility if you decide to take values from the outside (web). Filling Java class in runtime can be useless offline. In case of SharedPreferences you have to ensure they are loaded only once, during app's first start, and then updated only by manual request, as previous import will be used.

myActivity.getSharedPreferences("com.example.imported",0)
.edit()
.putString("The news",getTheNews())
.apply();
Chirag Jain
  • 628
  • 11
  • 24
Zon
  • 18,610
  • 7
  • 91
  • 99
1

I had a situation like this, where one of my strings.xml values had some dynamic piece of it. I set up the strings.xml with a "replacement text" (something like %%REPLACEMENT_EMAIL%%), and when I wanted to use that string programatically, I retrieved the string value of the resource, and replaced instances of that replacement text with the dynamic value (e.g. input by the user).

To be honest, my app has not been localized yet, but I'm still attempting to follow best practices w.r.t. not hardcoding any strings.

Rob I
  • 5,627
  • 2
  • 21
  • 28
0

Maybe you want to "modify" the string.xml so when it is required by the activity again it uses the new value, for example to keep a new dynamic title after screen rotation.

First, you can't modify the resource. It's already compiled. You can't modify the R class (what for?) all it's atributes are "final".

So, for the example above you can use onSaveInstanceState() and onRestoreInstanceState() for those properties you wanna keep on display.

David Silva-Barrera
  • 1,006
  • 8
  • 12
0

According to my knowledge, you can't change resource value(R class value) while app running. why don't try to store on shared preference? I recommend you to use shared preference

Thinesh
  • 555
  • 1
  • 6
  • 7
0

I used below method to get the key-value pairs from the API and storing it in HashMap globally. If the key value is not found in HashMap then I will search that key in strings.xml file. It will achieve the purpose of dynamically changing the value of key.

public String getAppropriateLangText(String key) {
        String value = "";
        try {
            HashMap<String, String> HashMapLanguageData HashMapLanguageData = gv.getHashMapLanguageData();
            value = HashMapLanguageData.get(key);//Fetching the value of key from API
            if (value == null || value.length() == 0) { //If Key value not found, search in strings.xml file
                String packageName = getPackageName();
                int resId = getResources().getIdentifier(key, "string", packageName);
                value = getString(resId);
            }
        } catch (Exception e) {
            value = "";
        }

        return value;
    }