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...
Related
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.
I trying to understand the difference between the two lines below. Why is it returning a zero when I add static to the field.
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
From this I get: this_year = 0;
private final int this_year = Calendar.getInstance().get(Calendar.YEAR);
And from this I get: this_year = 2013;
Someone who can explain why the first returns a zero?
Here's the code I use it in:
public class TheKing {
public static final TheKing theKing = new TheKing();
private final int beltSize;
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
private TheKing() {
beltSize = this_year - 1930;
}
public int beltSize() {
return beltSize;
}
public static void main(String[] args) {
System.out.println("TheKing wears a size " +
theKing.beltSize() + " belt.");
}
}
When fields are declared static, they are initialized in the static initialization method, meaning that your code looks like the following when compiled:
static {
theKing = new TheKing();
this_year = Calendar.getInstance().get(Calendar.YEAR);
}
Notice that the constructor is called before this_year is initialized, and before an int is initialized, it has its default value of 0. In other words, this_year is used before it is set to 2013.
One way to fix this is to simply reverse the order of the declarations:
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
public static final TheKing theKing = new TheKing();
Static methods are initialized in the order they are given in code.
public static final TheKing theKing = new TheKing();
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
So the above would initialize theKing first, which calls the constructor, which uses the uninitialized value of 0 of this_year. If you were to change it to:
private static final int this_year = Calendar.getInstance().get(Calendar.YEAR);
public static final TheKing theKing = new TheKing();
it would work fine.
Or if you remove the static, this_year would get initialized as the object theKing is created.
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);
I am new to Android and from what I read here most of the question goes to Imageview setting image. Here is my problem same as ImageView errors
Ive created a arraylist of Integer because of some function needed Int List rather than String List. Basically like most of function I created it like this one
private ArrayList<Integer> myArrayList = new ArrayList<Integer>();
public void setPicture(Integer datanumber)
{
if (datanumber>=10)
{
myArrayList.add(R.drawable.picture);
}
else{
myArrayList.add(R.drawable.picture_gray);
}
///and so on
}
Everything works fine until I found out that I cannot get this string ex "R.drawable.picture" using this code
myArrayList.get(0).toString();
Instead it gives me random number that I cannot understand.
My question is how can I return it to default value(or the one that I add on my list)
Thank you for spending time reading my question
Use String.valueOf(myArrayList.get(0));
instead of myArrayList.get(0).toString();
It isn't giving you a Random number. It is giving you the value of R.drawable.picture. All resources in R.*.*are referenced through numbers. This is evident if you take a look inside R.java, which shows something like:
public final class R {
public static final class attr {
}
public static final class drawable {
public static final int help=0x7f020000;
public static final int ic_action_search=0x7f020001;
public static final int ic_launcher=0x7f020002;
public static final int splash1=0x7f020003;
}
public static final class id {
public static final int userName=0x7f070002;
}
public static final class layout {
public static final int splash=0x7f030003;
}
public static final class menu {
public static final int action=0x7f060000;
public static final int menu=0x7f060001;
}
public static final class string {
public static final int app_name=0x7f040000;
public static final int create_user=0x7f040004;
public static final int help=0x7f040001;
public static final int image=0x7f040002;
public static final int primarymodtext=0x7f040003;
}
}
What you are getting is the int value R.drawable.picture. This is because when you're adding a value to the array list, you're passing in the int value stored in R.drawable.picture.
You can still use this integer value you get like you would use R.drawable.picture. Just pass it in normally.
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 ...