Why does this method compile? - java

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;
}

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.

how to refer string resources 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.

Set resource ID of String in code

Is there a way to set the ID of a string in code, so I can call the string in other Activities by R.strings.codegenstring. I can't predefine them in the string.xml since there will be a variable amount of code generated strings.
No. But you can define a String as static
public class A {
public static String s;
public void yourStringGeneratingFunction() {
s = "blahblah";
}
}
And access it from another class by:
A.s
No, there no way. To call string by R.string.codegenstring you must define public static string variable in R class. But R class are built by Android during compiling and you shouldn't modify it.

Inner class in Android R file

Is there any way to create an inner class in the auto-generated R file?
Right now R file looks like this:
public static final class id {
public static final int button1=0x7f020000;
public static final int button2=0x7f020001;
public static final int text1=0x7f020002;
}
And to access it, you should type
R.id.button1
What do I want to get it something like this:
public static final class id {
public static final class activity1 {
public static final int button1=0x7f020000;
}
public static final int button1=0x7f020001;
}
So I can access it with
R.id.activity1.button1
It is possible to manually edit the file, but that's not the way I'm looking for
Update: I need this because my current project consists of around 20 activities, with 5-30 widgets on each of them. I'm skipping a lot of ids(mostly for buttons and layout), but still it's not comfortable to type something like
AcEventListToolbarUserImageView
(AcEventList - name of activity, Toolbar - frame, UserImageView - user picture)
Update 2: partial solution is:
in activity layout xml
<TextView android:id="#+id_ActivityName/WidgetName" />
in the java code it will be:
R.id_ActivityName.WidgetName
Pros:
see all your activity list after typing "R.id_";
see all widget ids for the activity you need by typing "R.id_ActivityYouNeed."
The auto-generation of the R.java file is purely there as a mechanism to allow you to easily reference the contents of your res hierarchy from your code. As such, you cannot create sub-hierarchies.
The simple solution is to add context to your item names instead. For example, use #+id/Activity1_button1, and you can access this as R.id.Activity1_button1.
The R file is created automaticallly and it SHOULD NOT be edited...even if u try to do that manually when u run ur code a new R file will be created. can u give a reason why you need to do that ?
I dont know if this helps, but you could define your own hierarchical structure of Id containing classes that are defined in terms of your actual resources. You would still need to type the fully qualified name, but only once.
Like this:
public static final class MyResources {
public static final class activity1 {
public static final int button1=R.id.blahblah_button1;
}
public static final int button1=0x7f020001;
}
then refer to them as:
MyResources.activity1.button1;

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