how to refer string resources programmatically [duplicate] - java

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.

Related

Is there a way to get R.Id.text1 's text1 programmatically? [duplicate]

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.

Meaning of R.layout.activity_main in android development (JAVA language)

What is the meaning of R.layout.activity_main ?
I understand that "." operator is used to define variables of a particular object but in this case its been used twice so I can't make anything out of it. Also what exactly is "R" and "layout"?
I mean obviously they are classes (right?) but what is their function ? Basically explain R.layout.activity_main !
Please comment if question too vague or too broad.
R.java is a class (with inner classes, like layout or string) generated during the build process with references to your app's resources. Every resource you create (or which is provided by Android) is referenced by an integer in R, called a resource id.
R.layout.* references any layout resource you have created, usually in /res/layout. So if you created an activity layout called activity_main.xml, you can then use the reference in R.layout.activity_main to access it. Many built-in functionality readily accepts such a resource id, for example setContentView(int layoutResid) which you use during the creation of your activity and where you probably encountered this particular example.
If you create a string resource (in strings.xml) like this:
<string name="app_name">Application name</string>
it will get a new reference in R.string.app_name. You can then use this everywhere where a string resource is accepted, for example the android:label for your application in AndroidManifest.xml, or on a TextView; either in the xml:
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="#string/app_name"
/>
or in code: textview.setText(R.string.app_name).
You can access resources programmatically using the Resources class, to which you can get a reference by calling getResources on any context (like your activity). So for example you can get your app name described above in your activity by calling this.getResources().getString(R.string.app_name).
You can also supply different resources for different device properties/settings (like screen size or language), which you can access using the same references in R. The easiest example here, imho, is strings: if you add a new values folder in /res with a language specifier (so /res/values-nl for Dutch) and you add strings with the same identifier but a different translation and the resource management system cleverly figures out which one to provide for you based on your user's device.
I hope this helps a bit. For more information on resources see the documentation.
R is an auto-generated class, and describe the resources of your project. It contains static inner classes. layout is one of them. R.layout refers to the inner class called layout. activity_main is a public static final member of the class layout
In Android R is an Java-class that is auto-generated from your resources by the build process.
The R.layout member is a auto-generated class that contains all IDs for layouts.
R.layout.activity_main is a static final int member that represents the ID of the layout-file in layout/activity_main.xml.
Okay, so R is a generated class. If you're lucky enough you'll never see it nor have to touch it, otherwise you did something very wrong.
When you make a layout, or any change to a layout, Android Studio generates quite a couple files for you. This includes a R.java file. Here's a piece of an R.java class:
public final class R {
public static final class anim {
public static final int abc_fade_in = 0x7f050000;
public static final int abc_fade_out = 0x7f050001;
public static final int abc_grow_fade_in_from_bottom = 0x7f050002;
public static final int abc_popup_enter = 0x7f050003;
public static final int abc_popup_exit = 0x7f050004;
public static final int abc_shrink_fade_out_from_bottom = 0x7f050005;
public static final int abc_slide_in_bottom = 0x7f050006;
public static final int abc_slide_in_top = 0x7f050007;
public static final int abc_slide_out_bottom = 0x7f050008;
public static final int abc_slide_out_top = 0x7f050009;
}
public static final class attr {
public static final int actionBarDivider = 0x7f010062;
public static final int actionBarItemBackground = 0x7f010063;
public static final int actionBarPopupTheme = 0x7f01005c;
public static final int actionBarSize = 0x7f010061;
public static final int actionBarSplitStyle = 0x7f01005e;
public static final int actionBarStyle = 0x7f01005d;
public static final int actionBarTabBarStyle = 0x7f010058;
public static final int actionBarTabStyle = 0x7f010057;
public static final int actionBarTabTextStyle = 0x7f010059;
As you can see, in this case if I'd type
R.anim.abc_fade_in
I'd be selecting the value 0x7f050000;.
Every layout file is mapped out in this R file, and gets an ID by which android recognizes it. The layouts are located in R.Layout. So, R.layout.activity_main gets you the value of variable activity_main of the class layout of the class R.
And again, don't try finding or changing your generated R file. Things can go very wrong if you do that.
From https://stackoverflow.com/a/4953282/1393766
R is a class containing the definitions for all resources of a particular application package. It is in the namespace of the application package.
If you want to inflate a layout inside your activity class,you can use R.layout.activity_main where layout specifies that your resource is a layout and it's name is activity_main.
If you want to use a drawable image in a layout inside your activity class,you can use R.drawable.image_name where drawable specifies that your resource is a drawable image.
Also,R.java class is an autogenerated class which is not supposed to alter manually.

Display String based on user system language in Android

I have an enum class, but I want to display string based on user system language. For example, If the system is English , it should display 1 , 2 ,3
. But if the System is Chinese, the display should totally be different like "一", “二”, “三”. (一 means 1 in Chinese, 二 means 2 in Chinese).
Here is my code
public enum OrderType {
ONE("1"), TWO("2"), THREE("3")
private String name;
private OrderType(String name) {
this.name = name;
}
public String toString() {
return name;
}
public static String getEnumByString(String code) {
for (OrderType e : OrderType.values()) {
if (code.equals(e.name)) {
return e.name();
}
}
return null;
}
}
The enum works fine in android, Can I define the String in the value folder,
Like values-iw, values-ru... And how can I use that?
UPDATE:
I also want to use constructor to initialize the enum string. Just like
private OrderType(String name) {
String temp = getResources().getString(R.string.name);
this.name = temp ;
}
But I do not know how to pass parameter of R.string.parameter..
Second, how Can I use getResources() function in enum class
Just provide the String resource ID as a parameter to your Enum:
public enum OrderType {
ONE(R.string.order_type_one),
TWO(R.string.order_type_two)
private final int mTextResourceId;
OrderType(int resourceId) {
mTextResourceId = resourceId;
}
public int getTextResourceId() {
return mTextResourceId;
}
}
Provide these strings in each desired resource folder, e.g.:
res/values/strings.xml
res/values-es/strings.xml
res/values-fr/string.xml
Then, when you want to consume this in a TextView somewhere:
myTextView.setText(myOrderType.getTextResourceId());
No Context passing required, and it is determined at runtime based on the current locale.
You must know that enums are initialized statically. Each of ONE, TWO, THREE is static.
In android to use resources, such as strings, you need a context.
Generally, you can not access Android context in static methods or initializes, therefore you can't use them with enums.
Even if you could use a hack to make android context statically available you would still have issues :
you'd need to ensure none of your OrderType enums accessed before Application#onCreate
strings in your enums won't reflect runtime language changes
Edit
I hope it is clear that you can not reliably initialize your enums with string resources.
You could, however, associate static id of a string (R.string.string_name) with your enum and obtain needed resource string later using a context, as proposed in kcoppock's answer.
You should keep the strings in your string xml resource. That way you can get it from there into your code. For example like this:
String one = getResources().getString(R.string.num_one);
Then you just put a strings.xml file with overloading values in the language folders you want (values-ru, values-sv etc.)
For tasks of that kind use localizations.
"google on i18n java"
and
"android app localization"
public enum OrderType {
One(mActivity.getString(R.string.One)), Two(mActivity.getString(R.string.Two));
private String name;
private OrderType(String name) {
this.name = name;
}
public String toString() {
return name;
}
public static String getEnumByString(String code) {
for (OrderType e : OrderType.values()) {
if (code.equals(e.name)) {
return e.name();
}
}
return null;
}
}
also Here is the link, which I think is best way solve the porblem. This developing for API level 11 currently, however this code should run on higher versions. After a quick review in API 16 I did not see an existing core Android solution to this problem, if you know of one please post below and share.

Why does this method compile?

Why does this method compile?
private int test(){
return R.string.test;
}
R.string.test is defined this way in my android strings.xml file:
<resources>
<string name="test">Test</string>
</resources>
Everything I know about logic, the universe and life itself currently makes no sense. Please help a confused soul.
When you define your resources, android code generator reads the resources file and generate a java file R.java with all the resources id and thats why the code is compiled correctly.
R.string.teste get id of string as integer. So i didn't see any problems...
To get string you should write context.getResources().getString(R.string.teste)
In Android, all the resources located in the res folder are compiled in a class called R.java, there, you have an identifier of the resource created. For example, inside of the R.java class there is a sub class called string for the Strings, id for the ids and so on. In your example you will have:
public final class R {
// Other stuff
public static final class string {
public static final int test=0x7f05001c;
// More String resources
}
// Other stuff
}
So when you are doing return R.string.test; you are returning the id for that resource, in my example 0x7f05001c
If what you want is retrieve the string itself, instead of its id, you need to do what #Suvitruf told you: context.getResources().getString(R.string.test)
Try this :
private String test(){
String mess = getResources().getString(R.string.test);
return mess;
}

Android Programming Question

Howdy, I am a programmer that has worked almost exclusively with c++/c#/vbs and am just now entering into the world of Android development. I am running into a few issues that I cant seem to find answers for/ dont want to watch lengthy tutorial videos to find out so I figured I would ask here and get a quick answer.
I dont know if this is the best way to do this, so I am open to any suggestions.
I need some custom data containers for my program, lets say I want an 'Achievement' class so I can have an array of them!
now in C# I would do something like
public class Achievment
{
bool locked;
string achName;
string achSubName;
public Achievement(string name, string subname)
{
//ctor code goes here
}
}
Thats not everything I would need but thats the idea of the data layout I would like. However when I try to make a custom class in Eclipse it is all up in my grill about 'Public type achievement must be defined in its own file?' I'm writing this in the application's .java file... Is there somewhere else this should go? I am so confused. Basically java may as well be swahili to me... I like my intuitive c# layouts!
Like essentially I want to store my data separate from my UI, and when I generate an 'Achievement List' it looks at the current user's achievement array and populates from there. Good, bad?
Any answers that are not in the form of a redirect to a tutorial are much appreciated!
You should define the Achievement class in a separate file, called Achievement.java. You also need to change the constructor to have the name name as the class:
...
public Achievement(String name, String subname)
{
//ctor code goes here
}
...
In Java, the type is String, not string.
You either have to remove public modifier from the class (thus its visibility will be default level -- visible only from the package your Application class is placed) OR you need to move your class to Achievment.java file.
In java, public classes are required to be in their own file with the name of the file being the same as the class name (in your example, it must be in Achievment.java).
Create a file called Achievement.java within the source folder in your Eclipse Java project. You would also likely want the class to exist in a package so your assuming your package name was "com.acme", then your Achievement.java file would exist within the following directory structure:
<project-folder>/src/com/acme/Achievement.java
Now, assuming you've done the steps above, you will also need to make the following corrections to the code you posted:
package com.acme // NOTE: This maps to the directory structure
public class Achievement {
private boolean locked;
private String achName;
private String achSubName;
public Achievement(String name, String subname) {
this.achName = name;
this.achSubName = subname;
}
public boolean isLocked() {
return this.locked;
}
public void setLocked(boolean locked) {
this.locked = locked;
}
public String getName() {
return this.achName;
}
public void setName(String name) {
this.achName = name;
}
// etc ...
}

Categories

Resources