In my Android application (Wheather app), I have a main activity (displaying the wheater on the screen) and a class (getting the current location of the phone).
The "Position" class gets the latitude and longitude, which I would like to send in my main activity to use them. To do that, I tried to use getters but that does not seem to work. Here is the code for both classes :
Location class: (just pay attention to the getters at the end)
public class Position extends AppCompatActivity implements LocationListener {
private double longitude;
private double latitude;
private LocationManager locationManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED &&
ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
return;
}
Location location = locationManager.getLastKnownLocation(locationManager.NETWORK_PROVIDER);
onLocationChanged(location);
}
#Override
public void onLocationChanged(Location location) {
longitude=location.getLongitude();
latitude=location.getLatitude();
}
public double getLongitude1() {
return this.longitude;
}
public double getLatitude1() {
return this.latitude;
}
Main_Activity: (again just pay attention to the last four lines where I i'm trying to use latitude and longitude)
public class MainActivity extends AppCompatActivity {
TextView cityField, detailsField, currentTemperatureField, humidity_field, pressure_field, weatherIcon, updatedField;
Typeface weatherFont;
Position position = new Position();
private double latitude1;
private double longitude1;
private String latitude2;
private String longitude2;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
weatherFont = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/weathericons-regular-webfont.ttf");
cityField = (TextView)findViewById(R.id.city_field);
updatedField = (TextView)findViewById(R.id.updated_field);
detailsField = (TextView)findViewById(R.id.details_field);
currentTemperatureField = (TextView)findViewById(R.id.current_temperature_field);
humidity_field = (TextView)findViewById(R.id.humidity_field);
pressure_field = (TextView)findViewById(R.id.pressure_field);
weatherIcon = (TextView)findViewById(R.id.weather_icon);
weatherIcon.setTypeface(weatherFont);
Function.placeIdTask asyncTask =new Function.placeIdTask(new Function.AsyncResponse() {
public void processFinish(String weather_city, String weather_description, String weather_temperature, String weather_humidity, String weather_pressure, String weather_updatedOn, String weather_iconText, String sun_rise) {
cityField.setText(weather_city);
updatedField.setText(weather_updatedOn);
detailsField.setText(weather_description);
currentTemperatureField.setText(weather_temperature);
humidity_field.setText("Humidity: "+weather_humidity);
pressure_field.setText("Pressure: "+weather_pressure);
weatherIcon.setText(Html.fromHtml(weather_iconText));
}
});
latitude1 = position.getLatitude1();
longitude1 = position.getLongitude1();
latitude2 = String.valueOf(latitude1);
longitude2 = String.valueOf(longitude1);
asyncTask.execute(latitude2, longitude2); // asyncTask.execute("Latitude", "Longitude")
}
Why do I always get latitude2 = 0.0 and longitude2 = 0.0 in my android monitor ?
You have two different activities. Not an activity and a background service. There is only a single UI thread that runs the Activities. So when MainActivity is running, the Position activity is in the background and not running. And you can't create an object of an Activity using Position position = new Position();.
Why is your Position class an Activity? The onCreate method will never be called there unless you start the class as an Activity. Remove the AppCompatActivity from it and move the onCreate method in a separate method e.g. getLocation.
You also want to pass the Context to the Position class. Create a constructor for that
public Position(Context context) {
this.context = context;
}
and use that for the system calls.
Private variables can't be shared. Change it to.
public double longitude1;
public double latitude1;
You don't really need Position extend from an Activity. I can understand what you are trying to do, you just want to get the location from LocationManager, and send the result to the MainActivity. It should be fine if you just make a LocationManager instance in your MainActivity and pass the result of the location to whatever you want inside MainActivity.
public class MainActivity extends AppCompatActivity {
TextView cityField, detailsField, currentTemperatureField, humidity_field, pressure_field, weatherIcon, updatedField;
Typeface weatherFont;
Position position = new Position();
private double latitude1;
private double longitude1;
private String latitude2;
private String longitude2;
private LocationManager mLocationManager;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getSupportActionBar().hide();
setContentView(R.layout.activity_main);
weatherFont = Typeface.createFromAsset(getApplicationContext().getAssets(), "fonts/weathericons-regular-webfont.ttf");
cityField = (TextView)findViewById(R.id.city_field);
updatedField = (TextView)findViewById(R.id.updated_field);
detailsField = (TextView)findViewById(R.id.details_field);
currentTemperatureField = (TextView)findViewById(R.id.current_temperature_field);
humidity_field = (TextView)findViewById(R.id.humidity_field);
pressure_field = (TextView)findViewById(R.id.pressure_field);
weatherIcon = (TextView)findViewById(R.id.weather_icon);
weatherIcon.setTypeface(weatherFont);
mLocationManager = (LocationManager) getSystemService(LOCATION_SERVICE);
// do check permission staff as you post before
Location location = locationManager.getLastKnownLocation(locationManager.NETWORK_PROVIDER);
// do what you want with the location now.
Basically I think you don't have to make a Position class. You can get location directly and just use it then.
I suggest you to add following reforms to your code.
You need to create object of Position class inside onCreate() method of MainActivity. As onCreate() runs before everything else, it's necessary to have the definition of Position class inside this method.
Make your variables for longitude and latitude public to make them accessible in other class.
Position class need not to extend AppCompatActivity. Instead of using this and OnCreate() method, you can use Constructor and define all your stuff there.
Related
i am doing project on ecg monitoring android app so i need to get real time data from ubidots, i manage to get latest variable value when i run app but not the all new values which will be updated continuously.So, i need help to get real time data in my app as a result my app should get data when it is updated in ubidots variable .
here is my code for getting variable:
public class MainActivity extends Activity {
private TextView ecgLevel;
String variableValue;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ecgLevel = (TextView) findViewById(R.id.ecg);
ApiUbidots getApi = new ApiUbidots();
getApi.execute();
}
class ApiUbidots extends AsyncTask<Integer, Void, Value[]> {
private final String API_KEY = “";
private final String VARIABLE_ID = "”;
#Override
protected Value[] doInBackground(Integer... params) {
ApiClient apiClient = new ApiClient(API_KEY);
Variable ecgLevel = apiClient.getVariable(VARIABLE_ID);
Value[] variableValues = ecgLevel.getValues();
return variableValues;
}
#Override
protected void onPostExecute(Value[] variableValues) {
double varValue = variableValues[0].getValue();
variableValue = (String.valueOf(varValue));
ecgLevel.setText(variableValue);
}
}
}```
Use Retrofit for hit the API after you get latest variable
public class Page3 extends Activity {
double latitude;
double longitude;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.page3);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
/* Use the LocationManager class to obtain GPS locations */
LocationManager mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener mlocListener = new MyLocationListener();
try {
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
} catch (SecurityException e) {
e.printStackTrace();
}
}
/* Class My Location Listener */
public class MyLocationListener implements LocationListener {
#Override
public void onLocationChanged(Location loc) {
double a = loc.getLatitude();
latitude=a;
double b = loc.getLongitude();
longitude=b;
String Text = "My current location is: " +
"Latitud = " + loc.getLatitude() +
"Longitud = " + loc.getLongitude();
String x = getCompleteAddressString(a, b);
TextView text = (TextView) findViewById(R.id.tv_address);
text.setText(x);
}
Now,I want to access the variables latitude and longitude in another class.Here is the class,where I need to access these variables.Please note:The values of latitiude and longitude are set properly in this function since I get my current location(I dint paste the entire code here,since it is meaningless to do so)
Here is the code I wrote in the class where I want to access these variables
public class Page2 extends Activity {
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.page2);
Button btn = (Button) findViewById(R.id.help);
Page3 a=new Page3();
final double lati=a.latitude;
double longi=a.longitude;
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendSMS("9740641023", "Help"+lati+"");
}
});
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
Again I haven't copy pasted the entire code.This code was working fine on its own,but now on modification it sends the message "Help0.0" although according to me the latitude value should have changed to my current location.Please do help me out.
Your problem is basically that the one instance is created within a method:
LocationListener mLocListener = new MyLocationListener();
Instead, you should make it a field of that class.
And, if you make that a public static field, then other classes can directly access it using
LocationListener theListner = Classname.mLocListener;
But that is just a very "brute force way" of doing things. So, you can use that to see if you can make progress from there; but thing is: directly accessing static fields from other classes is bad practice; and you should avoid it.
As the real lesson is: this is very basic "java knowledge". You should step back from "android" for now; and study those basic Java things (like: "what are reasonable ways to access information in other objects"). Otherwise, you will hit one wall after the other!
And then, when you understand those basics; than you look into good books/tutorials about Android that explain to you how the "Android world" works. Because Android is sometimes using very special ways to get things done.
Declare that variavle as public static double lattitiue in First.java class
and now you can get value of this variable in any class by using First.lattitude
Good Data Abstraction and Encapsulation allows clients of a class to only see what the class allows the client(s) to see. Your data members like your variables latitude and longitude in the class Page3 should not be accessed directly by the other class. You should have public getter (accessor) and setter (mutator) methods that restrict "access" to your data members that should be declared as private.
You can only inherit one class in Java but you can implement as many interfaces as you like. Thus you do not need the inner public class MyLocationListener in the Page3 class. Just use the implement keyword and override the methods of the interface.
public class Page3 extends Activity implements LocationListener { // implement the interface instead of creating an inner class
private double latitude; // hide your data members from the client
private double longitude;
/**
* Called when the activity is first created.
*/
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.page3);
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder()
.permitAll().build();
StrictMode.setThreadPolicy(policy);
/* Use the LocationManager class to obtain GPS locations */
LocationManager mlocManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
try {
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this); // pass in this referring to the current class since implementing the interface LocationListener
} catch (SecurityException e) {
e.printStackTrace();
}
#Override
public void onLocationChanged(Location loc) {
setMyLatitude(loc.getLatitude()); // use mutator method to change value of your private data member
setMyLongitude(loc.getLongitude()); // use mutator method to change value of your private data member
String Text = "My current location is: " +
"Latitud = " + loc.getLatitude() +
"Longitud = " + loc.getLongitude();
String x = getCompleteAddressString(a, b);
TextView text = (TextView) findViewById(R.id.tv_address);
text.setText(x);
}
public void setMyLatitude(double a) {
this.latitude = a;
}
public void setMyLongitude(double b) {
this.longitude = b;
}
public double getMyLatitude() {
return latitude;
}
public double getMyLongitude() {
return longitude;
}
}
Now use your public methods to access your data members in the second activity.
public class Page2 extends Activity {
/**
* ATTENTION: This was auto-generated to implement the App Indexing API.
* See https://g.co/AppIndexing/AndroidStudio for more information.
*/
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.page2);
Button btn = (Button) findViewById(R.id.help);
Page3 a=new Page3();
final double lati=a.getMyLatitude();
double longi=a.getMyLongitude();
btn.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
sendSMS("9740641023", "Help"+lati+"");
}
});
// ATTENTION: This was auto-generated to implement the App Indexing API.
// See https://g.co/AppIndexing/AndroidStudio for more information.
client = new GoogleApiClient.Builder(this).addApi(AppIndex.API).build();
}
That is for good programming practice. A listener to communicate between to the two activities is probably what you will need to not get the initialized double value of 0.0. The listener should be implemented in class Page2 with a data member that is set to the listener in Page2 in class Page3. The listener will have some method(s) to either pass the data you want or tell the class Page2 that information has been modified in some way.
public class Page2 extends Activity implements DataListener {
.......
#Override
public void someMethod() {
// do something with the data longitude and latitude as their values have changed
}
private GoogleApiClient client;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.page2);
Button btn = (Button) findViewById(R.id.help);
Page3 a=new Page3();
a.setDataListener(this); // pass listener to the other class
/* code in Page2 */
}
public class Page3 extends Activity implements LocationListener {
private DataListener myListener;
/* code in Page3 */
#Override
public void onLocationChanged(Location loc) {
setMyLatitude(loc.getLatitude()); // use mutator method to change value of your private data member
setMyLongitude(loc.getLongitude()); // use mutator method to change value of your private data member
myListener.someMethod(); // call this method to inform the other class that information has changed
String Text = "My current location is: " +
"Latitud = " + loc.getLatitude() +
"Longitud = " + loc.getLongitude();
String x = getCompleteAddressString(a, b);
TextView text = (TextView) findViewById(R.id.tv_address);
text.setText(x);
}
public void setDataListener(DataListener listener) {
this.myListener = listener;
}
You can also pass in the the longitude and latitude directly into the "DataListener" method "someMethod" in the Page3 and not even need the getters and setters and private data members of the Page3 class.
Hi,
I'm a newbie in developing ArcGIS maps. Currently, I am able to display the map. But how can I create a default location using the longitude and latitude and implement this in my code?
For example, I want to set these coordinates: (1.3002, 103.8641). When you open the map, it will automatically zoom in to those coordinates.
Thank you in advance.
This is my code:
public class HelloWorld extends Activity {
MapView mMapView = null;
ArcGISTiledMapServiceLayer tileLayer;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Retrieve the map and initial extent from XML layout
mMapView = (MapView)findViewById(R.id.map);
/* create a #ArcGISTiledMapServiceLayer */
tileLayer = new ArcGISTiledMapServiceLayer(
"http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer");
// Add tiled layer to MapView
mMapView.addLayer(tileLayer);
}
#Override
protected void onPause() {
super.onPause();
mMapView.pause();
}
#Override
protected void onResume() {
super.onResume();
mMapView.unpause();
}
}
Before adding any layers to the MapView, set its OnStatusChangedListener. Add code to the listener that projects the longitude/latitude coordinates to map coordinates and centers the map at the map coordinates.
You could do it like this:
mMapView = (MapView)findViewById(R.id.map);
final double longitude = 103.8641;
final double latitude = 1.3002;
mMapView.setOnStatusChangedListener(new OnStatusChangedListener() {
#Override
public void onStatusChanged(Object source, STATUS status) {
if (STATUS.INITIALIZED.equals(status)) {
Point mapPoint = GeometryEngine.project(longitude, latitude, mMapView.getSpatialReference());
mMapView.centerAt(mapPoint, false);
}
}
});
/* create a #ArcGISTiledMapServiceLayer */
tileLayer = new ArcGISTiledMapServiceLayer(
"http://services.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer");
// Add tiled layer to MapView
mMapView.addLayer(tileLayer);
If you want to both center and zoom to a certain scale, you can call zoomToScale instead of centerAt.
Is there any code that lets you show your active coordinates in a self-made app? I am having troubles with my google maps and want to see what my active coordinates are. I prefer to show it as I am looking at the google maps in my app ie like a second layer of information. Thanks all !
You can set up a LocationListener.
In the onLocationChanged callback, you will receive a Location. You can then .getLatitude() and .getLongitude() from the location, and apply it to your layout.
public class MyActivity extends MapActivity implements LocationListener {
private LocationManager locationManager;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
requestFineAccuracyLocationUpdates();
}
private void requestFineAccuracyLocationUpdates() {
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
List<String> providers = locationManager.getProviders(true);
for (String provider : providers) {
locationManager.requestLocationUpdates(provider, 5000, 1000, this);
}
}
#Override
public void onLocationChanged(Location location) {
/* You can get your latitude and longitude here, and do whatever. */
}
}
I'm trying to set a textview text when the user location changes. All the code for the GPS portion works. I have been testing using Log();
Now instead of using Log, I wish to display the same information on the main layout, but the LocationChanged event is in a different class so I don't have access to the layout.
public class mylocationlistener implements LocationListener
{
#Override
public void onLocationChanged(Location location)
{
if (location != null)
{
Log.v("kjdv", location.getLatitude() + ", " + location.getLongitude());
//I would like to set a textview here, but don't have access to the object
}
}
This class gets created here:
public class gps extends ListActivity implements View.OnClickListener
{
#Override
public void onCreate(Bundle icicle)
{
super.onCreate(icicle);
setContentView(R.layout.main);
SetupLocationListener();
}
public void SetupLocationListener()
{
LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
LocationListener ll = new mylocationlistener(this);
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
}
So how, from the myLocationListener class can I set text in the onLocationChanged event?
Thanks!
We have 2 options.
one is just like as MisterSquonk said. keeping the Location listener as the inner class and the other one is to pass the object of the textView to the constructor of the mylocationlistener. Dont forget to handle null clause in second step.