get value from other static class to json object - java

Hi My android project is
A GPSTracker.java class which gives Latitude and longitude
A RemoteFetch.java class which get the JSON from an adress API is in static state
A MainActivity.java
but the url to get the json is like that :
private static final String OPEN_WEATHER_MAP_API =
"http://api.openweathermap.org/data/2.5/weather?" + "q=%s&" +"lat="+"&lon=" + "&units=metric";
My latitude and longitude are in the GPSTracker, but when I'm getting them, the it don't let me get these values as they're not in static format...
So as soon as I'm adding them in my openweatherapi url I have the error :
"Non static field cannot be referenced from a static context" .
Is there a way to "cast" a string/int format to a static format ??
If you need more info just say it to me please.
here some code
private void updateWeatherData(final String city){
new Thread(){
public void run(){
final JSONObject json = RemoteFetch.getJSON(MainActivity.this,city);
if(json == null){
handler.post(new Runnable(){
public void run(){
Toast.makeText(MainActivity.this.getApplicationContext(),R.string.place_not_found,Toast.LENGTH_LONG).show();
}
});
} else {
handler.post(new Runnable(){
public void run(){
renderWeather(json);
}
});
}
}
}.start();
}
in RemoteFetch.java
private static final String OPEN_WEATHER_MAP_API =
"http://api.openweathermap.org/data/2.5/weather?" + "q=%s&" +"lat="+"&lon=" + "&units=metric";
public static JSONObject getJSON(Context context, String city){
try {
// gps.getLatitude();
URL url = new URL(String.format(OPEN_WEATHER_MAP_API, city));
HttpURLConnection connection =
(HttpURLConnection)url.openConnection();
connection.addRequestProperty("x-api-key",
context.getString(R.string.open_weather_maps_app_id));
BufferedReader reader = new BufferedReader(
new InputStreamReader(connection.getInputStream()));
StringBuffer json = new StringBuffer(1024);
String tmp="";
while((tmp=reader.readLine())!=null)
json.append(tmp).append("\n");
reader.close();
JSONObject data = new JSONObject(json.toString());

You must understand the difference between a class and an instance of that class. Static fields and methods are connected to the class itself and not to it's instances.
Since as per your code, latitude and longitude are in the GPSTracker are not static,(those are instance variables) you are getting the error.
To solve your problem, you need to instantiate an instance (create an object) of your class so the runtime can reserve memory for the instance and allow you an access to instance variables (in your case,latitude and longitude are in the GPSTracker ).
Try below code where you want to access latitude and longitude in the GPSTracker (in onCreate() of MainActivity for example)
GPSTracker obj = new GPSTracker();
To access the instance variable latitude and longitude use obj as below
obj.latitude or obj.longitude.
2 other points to consider for above to work:
1. Make sure you import GPSTracker class in your file where you want to use it (MainActicity.java for example), if it is outside your file's package.
2. If GPSTracker class has some other constructor defined, that you want to use, you need to call that constructor while creating an object.

You are trying to access something that is not on your scope (aka context, but in terms of language, do not confuse it with the class Context). So you either need to pass your variable as a parameter to the static method, or making the method and instance method (removing the static).
Editing for further explanation:
On some part of your code (which I suppose is not on the part you pasted), you are using an attribute. Inside your static method you cannot see that attribute.
'static' means whatever it is, it lives on the Class, while non-static things belong to instances of that class. While the code seems to be on the same place when you write it, it won't be in the same place on runtime. That's why you cannot see attributes from the instance when you are doing something on a static context (that is, inside the static method).
So you either:
pass it as a parameter, like you did with the other two (context and city),
or you remove the 'static' keyword from your toJSON method. Beware if it was being use on other places on static context, since it might throw a compilation error saying that now those other context cannot see the method!
Also, you might want to check out Gson https://sites.google.com/site/gson/gson-user-guide
A SO response on your error, read it and try to understand how it works: "Non-static method cannot be referenced from a static context" error
And some docs on class members http://docs.oracle.com/javase/tutorial/java/javaOO/classvars.html
I would advice you to review basic OOP concepts, since this error you are having is a very basic one.

Related

How can I prevent invoking a static method on an instance of my class? [duplicate]

This question already has answers here:
Can we call a static method with a null object in Java? If so, how?
(4 answers)
Closed 4 years ago.
I have the following class, which is used for controlling some debugging and beta testing options in various places in my Android app. It just contains some flags and some logic to (de)serialize it to/from JSON.
public class DevConfiguration {
public boolean dontSendSMS;
public static String toJsonString(DevConfiguration devConfiguration) {
JSONObject json = new JSONObject();
if( devConfiguration != null ) {
try {
json.put("dontSendSMS", devConfiguration.dontSendSMS);
} catch (JSONException e) {
e.printStackTrace();
}
}
return json.toString();
}
public static DevConfiguration fromJsonString(String jsonString) {
if( jsonString.isEmpty() )
return null;
DevConfiguration result = new DevConfiguration();
try {
JSONObject jsonObj = new JSONObject(jsonString);
result.dontSendSMS = jsonObj.optBoolean("dontSendSMS", false);
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
Now, in one of my services I receive a serialized DevConfiguration object in an Intent, and might later pass it on to another service:
serviceIntent.putExtra("dev_conf", DevConfiguration.toJsonString(mDevConfiguration));
I choose to make the toJsonString() method static, so that I don't risk invoking it on a null instance. However, it's still possible to make a mistake somewhere and invoking the static method on an instance - potentially a null instance!
mDevConfiguration.toJsonString(mDevConfiguration);
There is a Lint warning in Android Studio, but still it's a potential NullPointerException bug waiting to happen. I thought it might be possible to hide it by defining a similar private method but with a different signature
/** Hide instance implementation **/
private String toJsonString(Object o){ return ""; }
but of course calling it with a DevConfiguration parameter will invoke the static method anyway, and the IDE doesn't give any more warnings than before either.
Is there any way to "hide" the static method from instance variables?
EDIT
Comments make it clear that invoking a static method on a null instance is perfectly legal. However, the question is not "How do I prevent a NullPointerException when invoking a static method on a null instance?", but the more general "How can I prevent invoking a static method on an instance of my class?".
In other words - is there any way to prevent the compiler from compiling if one accidentally tries to invoke a static method on an instance?
Calling a static method on a variable with null value will not raise NullPointerException. Following code will print 42 even though variable i is null.
public class Test {
public static void main(String... args) {
Integer i = null;
System.out.println(i.parseInt("42"));
}
}
When calling static methods by variable, what really matters is the declared type of the variable and not the referenced type of its value. This is related to the fact that static methods in java are not polymorphic.
„How can I prevent invoking a static method on an instance of my class?"
Calling static methods by variable is just a regular language feature defined in the Java spec. I’d be surprised if there were any method to suppress it in general.
If I had to do it for a selected class, I would probably migrate static methods to a separate „companion” utility (as described in another answer).
But having such static (factory) methods in your class is a perfectly fine idiom (see for example: Joshua Bloch, „Effective Java”, Item 1: Consider static factory methods instead of constructors). I wouldn’t easily give up on it.
I see a few ways you could do this:
Use a Utils class:
public class Utils {
public static String toJsonString(DevConfiguration devConfiguration) {
JSONObject json = new JSONObject();
if( devConfiguration != null ) {
try {
json.put("dontSendSMS", devConfiguration.dontSendSMS);
} catch (JSONException e) {
e.printStackTrace();
}
}
return json.toString();
}
public static DevConfiguration fromJsonString(String jsonString) {
if( jsonString.isEmpty() )
return null;
DevConfiguration result = new DevConfiguration();
try {
JSONObject jsonObj = new JSONObject(jsonString);
result.dontSendSMS = jsonObj.optBoolean("dontSendSMS", false);
} catch (JSONException e) {
e.printStackTrace();
}
return result;
}
}
Now you can just makes calls to Utils.method() and avoid confusion.
Use Kotlin
Kotlin actually makes it really hard (if not impossible) to call a static method on a dynamic receiver. It won't show in the method suggestions, and will underline in red if you type it manually. It might not even compile, although I haven't gotten that far.
Kotlin also has built-in null protection: instance?.method(). The ? means method() just won't execute if instance is null.
Just don't call a static method on a dynamic receiver. If you do it by accident, go back and fix it. You shouldn't be relying on Java to work around your syntax errors for you.
Finally, why even do this? I highly doubt mDevConfiguration is ever null, unless you initialize it in a really weird spot. If it is, you may want to look at reorganizing your code. Because, again, you shouldn't be relying on Java to work around your syntax errors for you. Also, if it is null, it won't throw an NPE, at least in Java, since it doesn't need a dynamic receiver to run (this is probably different in Kotlin).
It's up to you to make code that works as it should, and implement the proper null checks, error handling, etc. If you miss something, it's no big deal; that's why you test your code and fix the crashes and bugs you catch before you release it. Anything you don't catch will be reported by the Google Play Console (if you publish there) or Firebase (if you implement that) or your users.
Sorry if the above sounds harsh, but I'm really having trouble seeing why you'd want to do this instead of just checking your code.
If you really want to keep this structure, at least make the constructor for DevConfiguration private:
public class DevConfiguration {
//...
private DevConfiguration() {}
//...
}
That way, only the static methods inside it can create an instance.

Static method in java, can I access in a non-static way to a static method?

I think that there's something wrong in my code, is it the same to call (in setIstance) the method isSameMonth() in the static way or in a non static way?
The compiler suggest me to change: timesheet.isSameMonth() to Timesheet.isSameMonth()
I think no, because I want to pass the local variable timesheet, is it the same thing or should I modify my code?
Timesheet class:
static private Timesheet timesheet;
static public Timesheet getIstance()
{
if (timesheet == null || !Timesheet.isSameMonth())
{
timesheet = null;
timesheet = new Timesheet();
}
return timesheet;
}
static public void setIstance(Timesheet timesheet)
{
if (timesheet != null && timesheet.isSameMonth())
{
Timesheet.timesheet = timesheet;
}
}
public static boolean isSameMonth()
{
Date now = new Date();
Calendar calendarNow = Calendar.getInstance();
calendarNow.setTime( now );
Date firstDay = timesheet.days[0];
Calendar calendarFirstDay = Calendar.getInstance();
calendarFirstDay.setTime( firstDay );
if (calendarNow.get(Calendar.MONTH) == calendarFirstDay.get(Calendar.MONTH))
{
return true;
}
return false;
}
From outside I make this call:
Gson gson = new Gson();
String json = sharedPrefs.getString("timesheet", "");
if (!json.isEmpty())
{
try
{
Timesheet timesheet = Timesheet.getIstance();
if (timesheet.getDay(0)==null)
{
Timesheet.setIstance( gson.fromJson(json, Timesheet.class) );
}
refreshWidget(timesheet, context, allWidgetIds, intent.getAction());
}
catch (Exception e)
{
Log.e(TAG_LOG, e.toString());
}
}
It works either way, but the convention is to refer to static methods via the class name :
Timesheet.isSameMonth()
This makes it clear to someone who reads your code that you are calling a static method.
The fact that you ask that question should make you think about the design. I see no reason why isSameMonth should be a static method if every usage is connected with the preserved instance.
Not strictly an answer to the question in the topic, but apparently it helped
No. There is no need change your code other than the method calling style Timesheet.isSameMonth().
Since that is a static method, the style of invoking the method by convenience is with Class name, rather than the instance variable.
Otherwise, the people reading your code might thinks that it is a instance method. That is why it is a suggestion by IDE to make everyone life easy.
timesheet is not a local variable, it is a static field of the class. And your IDE suggests you to change timesheet.isSameMonth() to Timesheet.isSameMonth() because that method is static and it's better to access it in that (static) way.
If timesheet would not be static, you would have already get another compile error saying that the static isSameMonth() cannot access the non-static variable.
Accessing a static method works both way: via the Class name and via an instance reference but the same code will be generated. You can even access the static method even if the reference is null:
Runtime r = null;
r.getRuntime(); // This works even though r is null

Get a variable from an anonymous class

I have the following situation :
final String value = null;
AsyncHttpClient client = new AsyncHttpClient();
client.get("http://www.google.com", new AsyncHttpResponseHandler() {
#Override
public void onSuccess(String response) {
value = response;
}
});
System.out.println(value);
I am running this code from my main class.
Now I need to be able to use the variable (String Response) from the over ridden class in my main class.
How am i meant to go about getting this variable, as clearly what i have doesnt work.
ps, suggest an edit for the name, I didnt know what to call it.
Your problem doesn't have to do with classes; it's that you're using asynchronous code synchronously. Anything you want to do with the string response must be within the onSuccess handler (or a function called by it).

How to get a preference value into a static String variable?

I am getting the following error message:
"Cannot make a static reference to the non-static method
getPreferences(int) from the type Activity" is the error in my case.
'TimeCardLogin' must be a static variable."
How do I get a preference into a static String variable?
public class MyBaseURLContainer extends Activity {
public static String urlPref = "";
static String BASE_URL =
getPreferences(MODE_PRIVATE).getString("Name of variable",urlPref);
public static final String TimeCardLogin = BASE_URL + "/timecard";
}
I'd recommend making a static getter that takes an Context as an argument. That way a) it will actually compile, and b) if your base-url changes at some point, it will load the most recent value, instead of loading once in the beginning like your program is:
private final static String PREFS = "myUrlPrefs";
public static String getBaseUrl(Context context) {
return context.getSharedPreferences(PREFS, MODE_PRIVATE).getString(
"Name of variable",urlPref);
}
You'd call it from another activity like this:
String baseUrl = MyBaseUrlContainer.getBaseUrl(this);
Or from anywhere you have access to a Context like this (an Activity is a Context):
String baseUrl = MyBaseUrlContainer.getBaseUrl(myContext);
If you absolutely have to use this code from somewhere that doesn't have access to a Context (which really should almost never be the case in an Android app), you could store the value after it's retrieved, but the first time you get the value it has to be from a Context.

Getter and Setter return null in Android

so I've been working on a project that receives data from server, for example sessionKey. I created getter and setter method like this :
public class sEngine
{
private static String sessionKey;
public static String getSessionKey() {
return sessionKey;
}
public static void setSessionKey(
String sessionKey) {
sEngine.sessionKey = sessionKey;
}
}
Then I have activity A. In this activity A, I insert a value into the setter method.
public class A extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
sEngine.setSessionKey("Hello world")
}
}
I also have activity B. In this activity B, I call the getter method
public class B extends Activity
{
#Override
protected void onCreate(Bundle savedInstanceState) {
String sessionKey = sEngine.getSessionKey();
}
}
It occurs to me, that Android sometimes wipes all the data in order to free some memory, for example when I let the program idle for too long, or I used Advanced Task Killer. The problem is if those happen, I will get null in activity B when I call the getter method although I've set the value in activity A. Is there any way for me to maintain the value stored via the setter method (other than using SharedPreference) so the value will still be there although Android wipes the memories/data?
Is there any way for me to maintain the value stored via the setter
method (other than using SharedPreference) so the value will still be
there although Android wipes the memories/data?
Not sure why you wouldn't want to use SharedPreferences, despite it being the perfect candidate in your requirement. When somethings as simple as this can store it:
SharedPreferences sharedPrefs = getApplicationContext().getSharedPreferences(SOME_KEY, Context.MODE_PRIVATE);
Editor editor = sharedPrefs.edit();
editor.putString("session_key", sessionKey );
This will ensure your sessionkey always remains stored for easy retrieval. Unless the user clears your app data that is.
Your only alternatives as opposed to SharedPreferences are saving the sessionkey to a Database which in my opinion, considering the task it will perform, is absolutely unnecessary.
You could also consider writing the sessionkey to a text file and then read it to retrive the data.
Both the alternatives to SharedPreferences are truly unfit for the purpose you need it for. And I would really urge you to re-consider using SharedPreferences .
Try this, Declare you non activity class in A Activity. and then set your session value.
sEngine mengine = new sEngine();
mengine.setSessionKey("Hello world");
And also get session value in B activity.
sEngine mengine = new sEngine();
String str = mengine.getSessionKey();
change
sEngine.sessionKey = sessionKey;
in your code to
this.sessionKey = sessionKey;
or simply
sessionKey = sessionKey;
using sEngine. makes one believe that your class is static.Which it isnt!
or if you want to use this sEngine. everywhere in your code you need to declare this class as static.In that case you just need to make the class declaration to static:
public static class sEngine {

Categories