Where to store global constants in an Android application? - java

I would know what is the best practice for storing global constants which can change with the environnement (debug, preprod, prod, release, etc) at compile time.
In iOS, I used to keep all global constants in a header file and change it with pre-processor macro see this answer:
Where to store global constants in an iOS application?
What solution should I use for Android ?

Create a class constants in your base package folder. (or create an interface instead of a class so there is no need to reference the class everytime, however this is bad practice due to code readability, but it will work)
Fill it with public static final values.
Moreover, both the class as well as the interface can also be declared as abstract.

If values for your constants depend on environment (density, locale etc.) then you should use resources for storing them (integer, string, dimen etc.).
In another case you can put your global constants in one file (best practices - use prefixes for every set of constants) or put local constants in related classes (for instance, Intent holds flags. extras, categories and so on).

Use public static final values. and keep them in separate java file as follows:
static String QC = "http:/************";
static String DEV = "http:/************";
static String CLOUD = "http:/************";
static String SERVICEURL = CLOUD ; //Use this SERVICEURL in your code at run time

Another solution might be to use the resource file (if you are content with storing only string values).
This could be used to store constants such as the account that this application manages:
Ex. WelcomeActivity.java
AccountManager am = AccountManager.get(WelcomeActivity.this);
Account account = am.getAccountsByType(getResources().getString(R.string.ACCOUNT_TYPE))[0];
Ex. res/values/strings.xml
<resources>
<string name="ACCOUNT_NAME">com.acme.MyAccountSignature</string>
</resources>
This would also allow you to modify this without the need to recompile (similarly to how you would normally decouple translations, which the strings.xml file is best used for).

Pretty simple solutions is here
public class Constants {
/**
* Object key prams when pass the json object from server.
*/
public static final String KEY_EMAIL = "email";
public static final String KEY_PASSWORD = "password";
public static final String KEY_DEVICE_TOKEN = "device_token";
public static final String KEY_DEVICE_TYPE = "device_type";
public static final String KEY_NAME = "name";
public static final String KEY_COUNTRY_CODE = "country_code";
public static final String KEY_PHONE_CODE = "phone-code";
public static final String KEY_GENDER = "gender";
public static final String KEY_DATE_OF_BIRTH = "date_of_birth";
public static final String KEY_USER_ID = "user_id";
public static final String KEY_LIMIT = "limit";
public static final String KEY_DRIVER_ID = "driver_id";
public static final String KEY_LONGTITUDE = "logitude";
public static final String KEY_LATTITUDE = "lattitude";
public static final String KEY_RATING = "rating";
public static final String KEY_DETAILS = "details";
public static final String KEY_ACCESS_TOKEN= "access_token";
/**
* Fragments name
*/
public static final String FRAG_ETA = "ETA";
public static final String FRAG_ACCOUNT_FRAGMENT = "ACCOUNT_FRAGMENT";
public static final String FRAG_SETTING_FRAGMENT = "SETTING_FRAGMENT";
public static final String FRAG_MAP_FRAGMENT = "MAP_FRAGMENT";
public static final String FRAG_FEEDBACK = "FEEDBACK";
public static final String FRAG_RATE_FRAGMENT = "RATE_FRAGMENT";
public static final String USA_CODE = "+1";
public static final String DISTANCE_SEARCH = "DISTANCE_SEARCH";
}
happy coding

Property File
We store a property file under <project>/<package>/src/main/assets/config.properties
Loading properties
private static final String PROPS_NAME = "config.properties";
private static Properties configuration;
...
public static void init(Context ctx) {
configuration = new Properties();
InputStream rawResource = resources.getAssets().open(PROPS_NAME);
configuration.load(rawResource);

Related

Using Custom String.xml value in config.java file

I'm Working in A new Project and I already coded config.java for my project
My config.java code
package com.egf.myapp;
public class Config {
public static final String APP_API_URL = "http://www.egypt-freelancers.me/en/index.php";
public static final String APP_IMAGES_URL = "http://www.egypt-freelancers.me/uploads/";
public static final String APP_IMAGES_THUMB_URL = "http://www.egypt-freelancers.me/uploads/thumbnail/";
public static final String LANGUAGE_EN = "en";
public static final String LANGUAGE_AR = "fr";
public static final String DEFAULT_LANGUAGE = LANGUAGE_EN;
how to replace APP_API_URL with
custom language string.xml value
For English
http://www.egypt-freelancers.me/en/index.php
For French
http://www.egypt-freelancers.me/fr/index.php
Thanks
As per my understandings on the question you gave,
To get those variable values you can use this.
Config.STRING_VARIABLE_NAME; // this will return you the value from that class and object creation for that class is not needed as the variable is static.
Example :
String myvalue = Config.APP_API_URL;

Android static variables are lost

I am using a class with only static variables to store all constants and run-time properties. But, recently I have seen instances when I'm referencing these variables, I get null.
Following is my class definition:
public class PlayerProperties {
// Runtime but constant properties
public static int screenHeight;
public static int screenWidth;
public static String androidId;
// Static properties
// Urls
public static final String baseUrl = "http://www.blynq.in/api/player/";
public static final String registerUrlAppender = "activationKeyValid";
public static final String schedulesUrlAppender = "getScreenData";
public static final String updateUrlAppender = "updateAvailable";
public static final String tokenRegisterUrl = "fcmRegister";
public static final String mediaStatsUrl = "mediaStats";
public static final String logsUrl = "logs";
public static final String pingUrl = "ping";
public static final String screenInfoUrl = "screenInfo";
// Developer Keys
public static final String youtubeDeveloperKey = "ABCDEFGH...";
// Folder structure
public static final String mediaFolder = "player/media";
public static final String imagesFolder = "player/media/images";
public static final String videosFolder = "player/media/videos";
public static final String pdfFolder = "player/media/pdf";
public static final String gifFolder = "player/media/gif";
public static final String webFolder = "player/media/web";
public static final String othersFolder = "player/media/others";
public static final String logsFolder = "player/logs";
public static final String defaultFolder = "player/default/";
public static final String serFolder = "player/ser/";
public static final String tempFolder = "player/temp/";
// Shared Prefs Keys
public static final String ANDROID_ID_KEY = "ANDROID_ID";
public static final String MY_PREFERENCES_KEY = "MyPrefs";
// General properties
public static final String dateTimeFormatString = "ddMMyyyyHHmmss";
public static final String dateFormatString = "yyyy-MM-dd";
// Timeouts
public static final int httpPollTimeout = 20000; // in millis
public static final int pingPeriodicity = 30; // in secs
public static final int updateCheckPeriodicity = 24; // in hrs
public static final int pushEnabledPollPeriodicity = 30; // in secs
public static final int pushDisabledPollPeriodicity = 30; // in secs
public static final int statsUploadPeriodicity = 60; // in mins
public static final int logsUploadPeriodicity = 24; // in hours
public static final int cleanupPeriodicity = 24; // in hours
public static final int registrationStatusRecheckPeriod = 20000; // in millis
public static final int tokenResendToServerPeriod = 20000; // in millis
// Others
public static final int maxTextHeight = 50; // in dp
...
}
I have not stored any reference instantiatin PlayerProperties class, as all variables contained within are static.
When I am referencing the variable androidId using PlayerProperties.androidId , I SOMETIMES get null.
I have initialized the variable in one of the activities:
PlayerProperties.androidId = sharedpreferences.getString(PlayerProperties.ANDROID_ID_KEY, String.valueOf(UUID.randomUUID()));
My suspicion is that garbage collector was kicked by android in between. If gc does kick in, would it knock off all my runtime-initialized static variables ?
Which memory segment are the static variables stored ?
If not, what else could be the issue ?
Extra details: My app is configured to automatically launches on boot. I am facing the above described issue only with low end processors and when app is automatically triggered on boot.
Please note the following in reference to above question:
Garbage collector removes only unreferenced objects. Static variables will lose their values only when they are unloaded from JVM during run-time.
Initialization happens when app is launched via activities. If there are any services/broadcast receivers that are accessing methods within other classes and use these ids, and the app is not yet running by that time, the uninitialized values are referenced as default value. In case of string - it is null.
Nothing to do with low-end processors, easy to blame them often but JVM is powerful enough.
Only public static String androidId; can be null, when you want to use it you should init it in this class or in some other class in onResume()
androidId is a reference to an string, string is a class that will get by default a null reference as intial value if you dont do it....
look at this taken from oracle's doc
So basically androidId is null because is not initialized....the fact that the variable is static or not is not relevant in this case...
see here for more details
...I SOMETIMES get null.
yes, you will get always null unless its value change at run time...

Autocomplete for upper-case constants with underscores in Eclipse?

is there a possibility to activate autocomplete for constants with underscores _?
I have a class with many constants, where many of them begin same. Example:
// Component details
public static final String PROPERTY_NAME_COMPONENT_MATERIAL_NUMBER = "name";
public static final String PROPERTY_NAME_COMPONENT_OVERALL_WORK_STATUS = "componentOverallWorkStatus";
public static final String PROPERTY_NAME_COMPONENT_RELEASE_STATUS = "freigabestatus";
public static final String PROPERTY_NAME_COMPONENT_DESCRIPTION = "label";
public static final String PROPERTY_NAME_COMPONENT_AMOUNT = "newAmount";
public static final String PROPERTY_NAME_COMPONENT_BASE_QUANTITY_UNIT = "basismengeneinheit";
public static final String PROPERTY_NAME_COMPONENT_PRODUCER = "hersteller";
public static final String PROPERTY_NAME_COMPONENT_PRODUCER_FRAGMENT_NUMBER = "herstellerteilenummer";
public static final String PROPERTY_NAME_COMPONENT_EXCLUDE_ALTERNATIVE_ARTICLE = "componentExcludeAlternativeArticle";
public static final String PROPERTY_NAME_COMPONENT_GENERAL_INFO = "componentGeneralInfo";
They all start with PROPERTY_NAME_COMPONENT and if I now begin to type this
System.out.println(ClassWithThoseConstants.P
and press Ctrl + Space. Now I got all constansts starting with P, which is fine. But now I'd like to go further with camelcase style, i.e. PNCP which shall lead to the options:
PROPERTY_NAME_COMPONENT_PRODUCER and PROPERTY_NAME_COMPONENT_PRODUCER_FRAGMENT_NUMBER.
Typing P_N_C_P doesn't help either. Is there a possibility? I couldn't find any.

How to prevent the removal of leading whitespace from declarations in IntelliJ Jetbrains editor?

So when I have a lot of constants in Java I like to line up the initializers like this:
public static final String XML_QUESTION_ID_ELEMENT_NAME = "questionID";
public static final String XML_QUESTION_NAME_ELEMENT_NAME = "questionName";
public static final String XML_QUESTION_TEST_ELEMENT_NAME = "question";
public static final String XML_QUESTION_SCRAMBLE_ANSWERS_ELEMENT_NAME = "scramAns";
public static final String XML_QUESTION_REATIAN_ANSWER_ORDER_ELEMENT_NAME = "retOrder";
public static final String XML_QUESTION_ENCRYPTED_ANSWER_HASH = "encAnsHash";
public static final String XML_ANSWER_CHOICE_ELEMENT_NAME = "answerChoice";
I think it is easier to read. However, when I reload the project or reopen intellij it strips the leading white space so it goes back to looking like this:
public static final String XML_TEST_NAME_ELEMENT_NAME = "testName";
public static final String XML_AUTHOR_NAME_ELEMENT_NAME = "author";
public static final String XML_SCHOOL_NAME_ELEMENT_NAME = "school";
public static final String XML_PERIOD_NAME_ELEMENT_NAME = "class";
public static final String XML_DATE_ELEMENT_NAME = "date";
I already looked through indentation and editor settings but did not see anything that corresponded to this problem. Any help is appreciated! and as always, a big thanks to the community.
Go to settings->Code Style->Java->Wrapping And Braces->Field Groups-> select the check box for Align in Columns.
This should give you the desired indentation.

Java XML Serializing, Missing fields in file

this is the issue at hand, when trying to serialize the class below with the code below i'm getting is the below xml file without all the strings in the class.
The Class (some static values have changed but basically it), I left out all the generated get\set but they are all there with public access modifiers.
public class NotificationConfiguration implements Serializable
{
public static final String PORT_KEY = "mail.smtp.port";
public static final String DEFAULT_PORT_VALUE = "587";
public static final String TTL_KEY = "mail.smtp.starttls.enable";
public static final String DEFAULT_TTL_VALUE = "true";
public static final String AUTH_KEY = "mail.smtp.auth";
public static final String DEFAULT_AUTH_VALUE = "true";
public static final String MAIL_SERVER_KEY = "mail.smtp.host";
public static final String DEFAULT_MAIL_CLIENT_HOST = "smtp.gmail.com";
public static final String DEFAULT_MAIL_CLIENT_USERNAME = "*********";
public static final String DEFAULT_MAIL_CLIENT_PASSWORD = "*********";
public static final String DEFAULT_MAIL_CLIENT_ADDRESS = "*********";
public static final String DEFAULT_ADMIN_EMAIL = "*********";
public static final long DEFAULT_MAIL_INTERVAL = 24*60*60*1000; //One time a day default
public static final String SAVED_FOLDER_NAME = "C:\\Library";
public static final String SAVED_FILE_NAME = "C:\\Library\\NotificationCfg.xml";
private String portValue = DEFAULT_PORT_VALUE;
private String ttlValue = DEFAULT_TTL_VALUE;
private String authValue = DEFAULT_AUTH_VALUE;
private String mailClientHost = DEFAULT_MAIL_CLIENT_HOST;
private String mailClientUserName = DEFAULT_MAIL_CLIENT_USERNAME;
private String mailClientPassword = DEFAULT_MAIL_CLIENT_PASSWORD;
private String mailClientAddress = DEFAULT_MAIL_CLIENT_ADDRESS;
private String adminEMail = DEFAULT_ADMIN_EMAIL;
private boolean overdueSubsNotificationEnabled = false;
private boolean adminReportNotificationEnabled = false;
private long mailInterval =
}
The code used to serialize, which also creates the folder if missing.
public void storeChanges()
{
try
{
try
{
File f = new File(NotificationConfiguration.SAVED_FOLDER_NAME);
f.mkdir();
}
catch (Exception e){}
XMLEncoder encoder = new XMLEncoder( new BufferedOutputStream(new FileOutputStream(NotificationConfiguration.SAVED_FILE_NAME)));
encoder.writeObject(notificationConfig);
encoder.close();
System.out.println(LOG_CONFIGURATION_STORED);
}
catch (Exception ex)
{
System.out.println(LOG_CONFIGURATION_NOT_STORED + ex.getMessage());
}
}
The XML file received, with no exceptions thrown while serializing.
It basically just has the long value.
XMLEncoder encodes information about how to restore your object. If field values haven't changed from their defaults, XMLEncoder doesn't store anything.
This can cause confusion.
Hence, my rules of thumb when using XMLEncoder are:
1. don't initialize fields. don't do private String foo = DEFAULT_FOO;
2. don't do anything in the default constructor.
3. have some other method, or factory that will give you a "default" setup if needed.
I highly recommend to read again the XMLEncoder Javadoc
I will point out the main differences with the binary serialization we all know.
to restore the instance it need the class definition available to the JVM
It serializes only the data. And only the modified from default data.
As result of the 2 points above - is that there is no reason to serialize Static final values - they are part of the class definition.
The binary serialization on the other hand does serialize the class definition and can load from byte stream a class that was not available to the JVM before.
That is why you got results that you see. It Ok this is behavior by design and you use it right. It seems just not to be what you need.
By the way see what Xstream has to offer.
What is SAVED_FOLDER_NAME ? Is that like a factory object and did you by any chance call setMailInterval on that object?
Could that be that only mailInterval has a getter?
Just looked again the question apparently there is getter for all fields so ...

Categories