i am working on an application where i have to get a value of string resource to a constant. how can i do that? any ideas please.
The String is placed in
Application/res/values/strings.xml
and the name of the resource is let say app_version. now i want to get this app version to a constant string in another file. Any help is appreciated.
Try context.getResources().getString(R.string.app_version) where 'context' is your Activity or Application instance.
If your question is really about getting the version name of your application there is a better way:
String versionName = getPackageManager().getPackageInfo(getPackageName(), 0).versionName;
This way you retrieve the info directly from the AndroidManifest and you don't have to maintain it twice.
In Java: R.string.string_name
In XML:#string/string_name
R.string.app_version or #string/app_version taken from strings.xml is your constant and will always represent the value you entered into that XML file.
http://developer.android.com/guide/topics/resources/string-resource.html
All responses here aren't up to date. This is the right way to do it.
Better to use
#StringRes
public class AndroidClass{
...
#StringRes
private static final int[] TAB_TITLES = new int[]{R.string.tab1, R.string.tab2, R.string.tab_2};
private final Context mContext;
...
public CharSequence getString(int position) {
return mContext.getResources().getString(TAB_TITLES[position]);
}
}
I wanted to do this as well, but upon reflection, I'm not sure this is possible. We are trying to set a value at compile time that is not available until run time.
Constants are set at compile time. Now, the resource ID is available then, but the value, which Android can change by locale, is not. Therefore, the string value is not available until runtime.
My workaround was to make a public static value, and assign it if it is null, to the string value at create time. I probably should've just used a plain old instance variable, but this works.
Although, you can overwrite the value.
public class MyFragment
...
public static String SHOW_FOO;
...
public View onCreateView(...
if (SHOW_FOO == null) {
SHOW_FOO = getResources().getString(R.string.settings_foo_key);
}
....
Related
I am trying to use getString() to get an String from resources to assign it to an String array before my activity is created:
private static final String[] MenuNames = {
Resources.getSystem().getString(R.string.LCMeterMenu),
Resources.getSystem().getString(R.string.FrecMenu),
Resources.getSystem().getString(R.string.LogicAnalyzerMenu),
"Prueba con achartengine",
Resources.getSystem().getString(R.string.BrazoMenu)
};
When I use Resources.getSystem().getString(R.string.LCMeterMenu), Eclipse doesn't complain but I get an error at runtime:
Caused by: android.content.res.Resources$NotFoundException: String Resource ID #0x7f0a000a
But if I put inside onCreate():
Log.i("StringR", "String: " + getString(R.string.LCMeterMenu));
I get the String but I can't assign it to the final String I defined before. If I use only getString() before onCreate() I get and static error message. How can I use resources before onCreate() for global variables?
You cannot initialize a static final field from resources; the field needs to be initialized at the time the class is initialized and that happens before the application resources have been bound at run time. (By the way, the reason you cannot use Resources.getSystem() is that the Resources object you obtain that way contains only system resources, not any application resources.)
If you need those strings available before the application resources are bound, the only practical thing to do is to put the strings into the code directly. However, the "Android way" would be to organize your code so initialization only needs to happen during (or after) onCreate(). Just initialize the string array in onCreate() and don't worry about making the fields static or final.
If you don't want the string array to be associated with a particular activity, then you can subclass Application and read the array from resources inside the application class's onCreate() method. (You also need to declare your custom application class in the manifest.) However, the docs recommend against such an approach. (Since the array is private, I suspect that it is closely tied to a single activity anyway, so the use of an Application subclass doesn't seem warranted.)
An alternative is to declare a singleton class for your array. The singleton accessor function then needs a Context so it can retrieve the resources if necessary:
public class StringArray {
private static String[] theArray;
public static String[] getArray(Context context) {
if (theArray == null) {
theArray = context.getResources().getStringArray(R.array.my_strings);
}
return theArray;
}
}
(This assumes the string data are defined in a <string-array> resource like #JaiSoni suggested in his answer.) Once again, the member field cannot be declared final.
No, you can't use Resources before onCreate(). You can get the instance of Resources in onCreate() by using getResources() where you can get all the Strings. Also the strings are already declared as static by defining them in the strings.xml.
Pseudo code for accessing the Resources,
Resources res = getResources();
String app_name = res.getString(R.string.app_name);
Another approach could be to initialize the static array with resource identifiers (which are already available as opposed to the resources themselves).
private static final int[] MenuNames = {
R.string.LCMeterMenu,
R.string.FrecMenu,
...
};
This way, you can defer the loading of resources to when they are actually available:
String s = getResources().getString(MenuNames[i]);
The following is a working approach to initialize static final variables in android from XML, such as strings.xml.
Subclass application and provide a "static context"
Register the application class in manifest
Use the static context to initialize your constants
1. MyApplication.java
public abstract class MyApplication extends Application {
private static Context context;
#Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
}
/**
* Returns a "static" application context. Don't try to create dialogs on
* this, it's not gonna work!
*
* #return
*/
public static Context getContext() {
return context;
}
}
2. AndroidManifest.xml
<application
android:name=".android.application.MyApplication"
<!-- ... -->
</application>
3. Your application code, e.g. Activity
private static final String[] MenuNames = {
getContext().getString(R.string.LCMeterMenu),
getContext().getString(R.string.FrecMenu),
getContext().getString(R.string.LogicAnalyzerMenu),
"Prueba con achartengine",
getContext().getString(R.string.BrazoMenu)
};
protected static Context getContext() {
return MyApplication.getContext();
}
For working examples refer to AbstractApplication and PreferencesServiceSharedPreferences.
Note that this approach also has its downsides:
Apart from being opposed to the "Android way" (as #Ted Hopp suggested in his answer),
it makes testing a bit difficult. That is why the call to MyApplication.getContext() is wrapped in another method. As it is a static method, overriding it in testing code is not simple. But you could use a framework such as Powermock for this purpose.
In addition it is a bit prone to NullPointerExceptions. As soon as the context is null (e.g. in your testing code) the application code crashes. One option to overcome this, is to do the initialization in a constructor, where you could react to getContext()returning null (see example).
Whatever you get by the getString(int resId) will already be a constant for your application. Why do you have to keep it in another final static variable. You can read it like that whenever you want, right?
I'm trying to store a create database script (a rather lengthy one) in the strings.xml file (noobie here, haven't figured out a better place to put it yet) it does show up in the generated R class:
public static final class string {
public static final int app_name=0x7f040001;
public static final int create_database=0x7f040002; //this one here
public static final int hello=0x7f040000;
}
but when I try this in the code:
DATABASE_CREATE = R.string.create_database;
'create_database' is not available. Ti's simply not there, I get an error if I try to use it. Any ideas why this is so? Do those strings have length limitations? Can they only consist of a single line?
If that's the case, what's the right place to put my SQL create script?
Thanks for your answers.
R.string.create_database in the generated R is an integer (see your line with the comment). In order to get the string value, you need to call getString(R.string.create_database). See getString(int)
Is there a way to use the getString method from a seperate class?
I have a string stored in my strings xml, I'd like to use that string in an object... but the method isn't even available in the object...
any tips?
getString() is a method of the Context class¹. If you need it inside a seperate class (that does not extend Context), it's usually best to provide it as a seperate argument to the method that needs it.
Example:
public void logString(Context c, int stringId) {
Log.d("TAG", c.getString(stringId));
}
One thing is important: Never store the context inside the separate class.
Provide an argument. Otherwise you will leak memory and disrupt the whole android lifecycle if the object that stores the context lives longer than the object where the context originally belongs to (e.g. an activity).
¹ getString() can also be used from the Resources class - which you can get via Context.getResources()
the solution here is to make sure your object has a reference to the application context
Class Swag{
private Context ctx;
public Swag(Context ctx){
this.ctx = ctx;
}
public void doSomething(){
String something = ctx.getResources().getString(R.string.somestring);
...
}
// or like this
public void makeUpperCase(Context appContext){
appContext.getResources().getString(R.string.super_string_swag_yolo);
}
}
obviously you'd have to supply the context when creating an object or when caling the method
resouce file: values/strings.xml
<resources>
<string name="app_name">App name</string>
<resources>
java
import android.content.res.Resources;
Resources.getSystem().getString(R.string.app_name);//result : App name
edit:
The below will NOT work. I read this on another site and assumed it worked, but I just tried it in my app and kept getting an error. Problem is, it will compile but you will get a runtime exception.
This will work from any java class:
import android.content.res.Resources
Resources.getSystem().getString(R.string.blah);
if you cannot pass a context as parameter, create another class, where you put all your static data.
example :
public class StaticData {
public static String BASE_URL = "https://stackoverflowrocks.com";
}
and get that string from your other class by calling directly
StaticData.BASE_URL
nice and clean.
This works, but for SYSTEM resources only:
import android.content.res.Resources
Resources.getSystem().getString(R.string.blah);
Reference: https://stackoverflow.com/a/40917607/8994882
Try this in your java file:
String myString = getResources().getString(R.string.MY_STRING)
Now use this string object.
I would like to have 2 languages for the UI and separate string values for them in my resource file res\values\strings.xml:
<string name="tab_Books_en">Books</string>
<string name="tab_Quotes_en">Quotes</string>
<string name="tab_Questions_en">Questions</string>
<string name="tab_Notes_en">Notes</string>
<string name="tab_Bookmarks_en">Bookmarks</string>
<string name="tab_Books_ru">Книги</string>
<string name="tab_Quotes_ru">Цитаты</string>
<string name="tab_Questions_ru">Вопросы</string>
<string name="tab_Notes_ru">Заметки</string>
<string name="tab_Bookmarks_ru">Закладки</string>
Now I need to retrieve these values dynamically in my app:
spec.setContent(R.id.tabPage1);
String pack = getPackageName();
String id = "tab_Books_" + Central.lang;
int i = Central.Res.getIdentifier(id, "string", pack);
String str = Central.Res.getString(i);
My problem is that i = 0.
Why does not it work in my case?
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.
Verify if your packageName is correct. You have to refer for the root package of your Android application.
private String getStringResourceByName(String aString) {
String packageName = getPackageName();
int resId = getResources().getIdentifier(aString, "string", packageName);
return getString(resId);
}
Not from activities only:
public static String getStringByIdName(Context context, String idName) {
Resources res = context.getResources();
return res.getString(res.getIdentifier(idName, "string", context.getPackageName()));
}
getResources().getString(getResources().getIdentifier("propertyName", "string", getPackageName()))
I would add something to the solution of leonvian, so if by any chance the string is not found among the resources (return value 0, that is not a valid resource code), the function might return something :
private String getStringResourceByName(String aString) {
String packageName = getPackageName();
int resId = getResources()
.getIdentifier(aString, "string", packageName);
if (resId == 0) {
return aString;
} else {
return getString(resId);
}
}
Best Approach
App.getRes().getString(R.string.some_id)
Will work Everywhere (Utils, Models also).
I have read all the answers, all answers can make your work done.
You can use getString(R.string.some_string_id) in both Activity or Fragment.
You can use Context.getString(R.string.some_string_id) where you don't have direct access to getString() method. Like Dialog.
Problem
When you don't have Context access, like a method in your Util class.
Assume below method without Context.
public void someMethod(){
...
// can't use getResource() or getString() without Context.
}
Now you will pass Context as a parameter in this method and use getString().
public void someMethod(Context context){
...
context.getString(R.string.some_id);
}
What i do is
public void someMethod(){
...
App.getAppResources().getString(R.string.some_id)
}
What? It is very simple to use anywhere in your app!
So here is a solution by which you can access resources from anywhere like Util class .
import android.app.Application;
import android.content.res.Resources;
public class App extends Application {
private static Resources resources;
#Override
public void onCreate() {
super.onCreate();
resources = getResources();
}
public static Resources getAppResources() {
return resources;
}
}
Add name field to your manifest.xml <application tag.
<application
android:name=".App"
...
>
...
</application>
Now you are good to go. Use App.getAppResources().getString(R.string.some_id) anywhere in app.
Easier way is to use the getString() function within the activity.
String myString = getString(R.string.mystring);
Reference: http://developer.android.com/guide/topics/resources/string-resource.html
I think this feature is added in a recent Android version, anyone who knows the history can comment on this.
getResources() works only when you're in Activity or Fragment class.
to get access to strings resource everywhere,
use:
Resources.getSystem().getString(android.R.string.somecommonstuff)
In case you are using Kotlin, you can define an extension function as follows:
fun Context.getStringResourceByName(stringName: String): String? {
val resId = resources.getIdentifier(stringName, "string", packageName)
return getString(resId)
}
And then simply use it. For example, in a Puzzles app I set the Activity title according to the image file name:
val stringName = "${folderName}_${assetName.substringBefore(".")}"
title = getStringResourceByName(stringName)
In this example I am reading string resources based on dynamic names.
If you don't have an Activity reference, you can use your context in this way:
getContext().getString(R.string.your_string_name);
In Kotlin, Leverage Extension functions 😎
fun Context.getStringByName(name: String): String {
return getString(resources.getIdentifier(name, "string", packageName))
}
There is also a set of predefined Android strings such as "Ok", "Cancel" and many others - so you don't have to declare all. They're available simply by:
getString(android.R.string.ok)
(In this case, "Ok" string). BTW there are also other Android resources available like for example icons images etc.
If you wannt get it inside an activity or fragmnet, then:
getContext().getResources().getString(R.string.string_name);
If you want to get it from a class outside of activity or fragment where you don't have the activity context then use application context:
getApplicationContext().getResources().getString(R.string.string_name);
String myString = getString(R.string.mystring);
easy way
You can try this in an Activity:
getResources().getString(R.string.your string name);
In other situations like fragments,... use
getContext().getResources().getString(R.string.your string name);
To safe, you should add:
mContext.getResources().getString(R.string.your_string);
mContext can be: context in onAttach() of Fragment or this of Activity.
R.string.<string_name>
Use that line directly in your java file. Keep it simple.
whats the deal with
CharSequence contentTitle = R.string.value;
Error cannot convert from int to CharSequence. Is there a way around this or am i missing something?
i tried
String s = R.string.value + "";
CharSequence contentTitle = s;
it returns integers values.
Any help?
R.string.value is a call to the static field in the class R, which is auto generated by Eclipse and which does a kind of summary of all your resources. To retrieve the string, you need to use :
CharSequence contentTitle = getString(R.string.value);
If you open the R class you will see that it contains only numbers that are references to the compiled resources of your project.
To retrieve the string, you need to use getString(),
but getString() is a method from Context class.
If you want to use this method outside your Activity class, you should get link to your context first and then call:
String s = mContext.getString(R.string.somestring)
R.string.value returns the reference ID number of the resource 'value'. If you look at your R class it will appear as something like this:
public static final class string {
public static final int value=0x7f040007;
}
I've been experiencing issues with referencing the getString() method. The exact error that Eclipse spits at me is:
The method getString(int) is undefined for the type DatabaseHelper.MainDatabaseHelper
After reading for awhile I've figured out that you must reference your application's context to get access to the getString() method. I was trying to create a private SQLDatabase helper class in a content provider, however, that was not allowing me to reference the getString() method. My solution so far is to do something like this:
private class MainDatabaseHelper extends SQLiteOpenHelper {
MainDatabaseHelper(Context context) {
super(context, context.getString(R.string.createRoutesTable), null, 1);
}
public void onCreate(SQLiteDatabase db) {
db.execSQL((getContext()).getString(R.string.createRoutesTable));
}
}
Notice these two context references:
context.getString()
(getContext()).getString()
I don't know if this is the optimal long-term solution but it seems to work for the moment. Hope this helps.
You could use String s = getResources().getString(R.string.value); also.