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 ...
}
Related
this seems to be a very silly problem but I really have no idea how to deal with it. I'm using IntelliJ IDEA to write java code. Let's say my class have a variable name:
public class city {
private String name;
}
And I want to generate a Getter() method for name, the most convenient way is to use the auto generate:
However here is the result:
public class city {
public String getName() {
return name;
}
private String name;
}
As you can see, the getName() is always generated above the variable, but I want it to be below the variable. What should I do to achieve that? Thanks.
It depends on the position of the cursor. so where you click to generate the getter, it will create the code. to solve this. Just move the cursor under the attribute and click Alt + Insert
Then the result is:
I'm developing an android library (.aar) and I was wondering if it was possible to, as the title suggest, force a user to implement an interface or extend an abstract class of my library.
I already know that I could just go with a class like this in my library :
public class MyLibrary
{
public interface VariablesInterface
{
void createVariables();
}
private static VariablesInterface vi = null;
public void setVariablesInterface(VariablesInterface v)
{
vi = v;
}
private static void SomeWork()
{
if (vi == null)
{
throw new RuntimeException("You noob.");
}
else
{
// do work
}
}
}
The library will work "alone" at some point, and when it will come to SomeWork(), if the interface isn't implemented it will crash, but this could only be seen at runtime.
Is there a way to have this behaviour when compiling the user's application ?
The goal is to avoid the user forgetting that he have to implement this without having to write it in the documentation and hope the user will probably read it.
Thanks for reading !
EDIT
I think that this question need some enhancement and background.
The purpose of the library is to provide classes that create variables which manages preferences, e.g. :
public class VarPreferenceBoolean extends VarPreference
{
private boolean defaultValue;
public VarPreferenceBoolean(String key, boolean defaultValue)
{
super(key, true);
this.defaultValue = defaultValue;
}
public void setValue(Context context, boolean value)
{
SharedPreferences.Editor e = context.getSharedPreferences(PropertiesManager.preferenceFileName, Context.MODE_PRIVATE).edit();
e.putBoolean(key, value);
e.commit();
}
public boolean getValue(Context context)
{
readPropFile(context);
SharedPreferences sp = context.getSharedPreferences(PropertiesManager.preferenceFileName, Context.MODE_PRIVATE);
return sp.getBoolean(key, defaultValue);
}
}
The same goes for int, string and so on.
In the super class, I add each VarPreference to a List to keep the library acknowledged of all the variables availables.
Note the readPropFile inside the getter.
Then, the user use the library in his project like this :
public class Constants
{
public static final VarPreferenceInt FILETYPE;
public static final VarPreferenceInt DATAMODE;
public static final VarPreferenceString URL_ONLINE;
public static final VarPreferenceBoolean UPDATING;
public static final VarPreferenceLong LAST_UPDATE;
static
{
FILETYPE = new VarPreferenceInt("FileType", MyFile.FileType.LOCAL.getValue());
DATAMODE = new VarPreferenceInt("DataMode", DataProvider.DataMode.OFFLINE.getValue());
URL_ONLINE = new VarPreferenceString("UrlOnline", "http://pouetpouet.fr");
UPDATING = new VarPreferenceBoolean("Updating", false);
LAST_UPDATE = new VarPreferenceLong("LastUpdate", 0L);
}
}
Now, when the user call an accessor, readPropFile will first search if a .properties file exist and modify accordingly the preferences if it found matches between the list of VarPreference and the properties of the file. Then it will delete the file and the accessor will return the value.
This is what exists today.
Now we want another application (let's say Pilot) to be able to get the VarPreferences of the user's application (let's say Client). Both implements the library.
Pilot send an Intent asking for the VarPreference list of Client, putting in extra the package name of Client.
The library receive the intent, verify the packagename, if it's Client it send back the list.
Problem is, if Client hasn't started, no VarPreference exists, and the list is empty.
I need to force the user to create his VarPreference in an method that my library know, to be able to call it whenever I want, and create the VarPreferences of the user when it's necessary.
Hope this is clearer !
EDIT
I rethought about all of this with a colleague and it just hit us that all this stack is biaised.
I didn't explain well and even if I said it, I didn't take account enough of this : everything needs to be done from the library.
So, even if I give an interface to the library, the application will have to run and call this affectation first in order to let the library work alone.
We are heading towards introspection now.
(This is the goal, it may not be possible...)
There will be an abstract class inside the library, with an abstract method where the user will place all of the VarPreferences creations. The user will have to extends this class and call the method in order to create his VarPreferences.
In the library, a method will search by introspection a child of the abstract class, create an instance of this child and call the method that will create the VarPreferences.
I would leave the abstract classes and interfaces in the main library and load the rest of your code via classloader from another. JDBC works like this.
Is there a way to have this behaviour when compiling the user's application ?
I see no way to force a compilation failure. However, if you force them to supply a VariablesInterface in the constructor then it will fail immediately. Make the VariablesInterface be final and only initialize it in the constructor:
public class MyLibrary {
private final VariablesInterface vi;
public MyLibrary(VariablesInterface vi) {
if (vi == null) {
throw new IllegalArgumentException("vi can't be null");
}
this.vi = vi;
}
...
If you can't change the constructor then you can also add to any SomeWork public methods some sort of configuration check method to make sure the the vi wiring has properly been done but this requires careful programming to make sure all public methods are covered.
public void somePublicMethod() {
checkWiring();
...
}
private void checkWiring() {
if (vi == null) {
throw new IllegalStateException("vi needs to be specified");
}
}
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?
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;
}
When I run the following code to save a JSON:
String regionObject = this.gson.toJson(parentRegion);
JsonFileInputOutput.saveObjectToTextFile(regionObject,
"./tests/model/util/test_saveRegionObject.txt");
and after that I reopen the created .txt file:
public void test_openRegionObject() throws IOException {
String regionAsString = JsonFileInputOutput
.openObjectInTextFile("./tests/model/util/test_saveRegionObject.txt");
Gson gson = new Gson();
Region LGNRegion = gson.fromJson(regionAsString, Region.class);
System.out.println(LGNRegion.toString());
}
it works perfectly fine.
However, when I try the second snippet of code into a different class that does not contain the first one I get the following error:
java.lang.RuntimeException Failed to invoke public model.MARK_II.Cell() with no args
Cell is a custom class that is used inside Region class. Here is the implementation of the Cell class:
public abstract class Cell {
protected boolean isActive;
public Cell() {
this.isActive = false;
}
public boolean getActiveState() {
return this.isActive;
}
public void setActiveState(boolean isActive) {
this.isActive = isActive;
}
}
My question is how can I fix this exception so that I can read a proper serialized JSON as the one I create with first snippet of code.
Two questions here.
Why I get the exception? This is simple to answer: your Cell class (or better your subclass of Cell class since Cell is abstract) has no a constructor without parameters. Maybe it has a constructor with one or more parameters.
Why I can't open a generic file? Difficult to say without showing us the file. It's sure that if you save a Json serialization into a file and just open it you have no error. My best guess is this: when you serialize and save you have not Cell subclasses inside (maybe member variables are nulls), whenever you open another file, maybe Cell subclasses are defined and so answer to 1. applies.