I'm working on a simple Android app, with a GPS listener and a webview.
I can get the latitude and longitude with no issue. The problem is, I want to put the latitude and longitude into a URL (like myurl.com/mypage.php?lat=57&lon=21)... but the variable the data is stored in is confined to its class. I can't figure out how to declare or create a variable that I can use throughout the entire main class. Here's my code:
public class WTest2Activity extends Activity {
public String txt;
public class MyLocationListener implements LocationListener {
public void onLocationChanged(Location loc) {
loc.getLatitude();
loc.getLongitude();
txt = "Latitude: " + loc.getLatitude() + "Longitude: " + loc.getLongitude();
Toast.makeText( getApplicationContext(),txt,Toast.LENGTH_SHORT).show();
}
public void onProviderDisabled(String provider) {
Toast.makeText( getApplicationContext(),"Gps Disabled",Toast.LENGTH_SHORT ).show();
}
public void onProviderEnabled(String provider) {
Toast.makeText( getApplicationContext(),"Gps Enabled",Toast.LENGTH_SHORT).show();
}
public void onStatusChanged(String provider, int status, Bundle extras) {} /* do nothing */
}
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
/* Use the LocationManager class to obtain GPS locations */
LocationManager mlocManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
LocationListener mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates( LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
WebView webview;
webview = (WebView) findViewById(R.id.webview);
webview.getSettings().setJavaScriptEnabled(true);
webview.loadUrl("http://www.myurl.com/page.php?this=" + txt);
}
}
Your OnCreate method is the method called at start of Activity. At that time, txt is null. That's why it doens't show in your url. Then, onLocationChanged sets the value of txt but where are you using this afterwards? nowhere!.
you should move what you do in onCreate to onLocationChanged:
public void onLocationChanged(Location loc) {
loc.getLatitude();
loc.getLongitude();
txt = "Latitude: " + loc.getLatitude() + "Longitude: " + loc.getLongitude();
Toast.makeText( getApplicationContext(),txt,Toast.LENGTH_SHORT).show();
webview.loadUrl("http://www.myurl.com/page.php?this=" + txt);
}
add a new line here:
public class WTest2Activity extends Activity {
public String txt;
public Location location;
then, in your public void onLocationChanged(Location loc), try setting location.setLatitude(loc.getLatitide); and location.setLongitude(loc.getLongitude);
then, you can access your location anywhere with your global variable location
Buddy its just small logical mistake in your code. Let me explain. You are requesting location updates then right after that you are loading URL. Now location listening is different thread which is updating value of txt variable. And updating location takes time. And taken time can be different every time. That is why you need to move your loadUrl code to onLocationChanged method.
Related
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.
I have a class which extends from AsyncTask and gets data in JSON format from a web service. My android app has to retrieve data asynchronously whenever the location is changed. My android activity implements LocationListener and I am invoking the asynchronous execution in onLocationChanged() method. I have tried setting zero for both minTime and minDistance parameters of requestLocationUpdates() method but the data which is to be retrieved asynchronously is never retrieved.
The code for my onCreate() and onLocationChanged() methods is given below
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_nearby);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
// Hashmap for ListView
albumsList = new ArrayList<HashMap<String, String>>();
}
#Override
public void onLocationChanged(Location location) {
latitude = String.valueOf(location.getLatitude());
longitude = String.valueOf(location.getLatitude());
new MyAsyncTask().execute();
}
The latitude and longitude variables are used in the MyAsyncTask class for getting data with respect to user's current location.
Please tell me what's wrong with my code. I have been looking for the solution since last week but haven't found any.
oke, a little bit confused but let me understand it. You retrieve the data in onLocationChanged() ? example long=111 lat=222 and with your Asyntask you make a GET request to a WS with a json parameter probably long and lat and some other stuff in it ? and if you try to debugg it there are some values in logcat ? or some error ? or did you put the permision in the manifest file ? or in the phones settings ?
did tried debugging??
or
Log??
are you getting any error???
sometimes the location.getLatitute() and location.getLatitute() returns null which may cause null pointer Exception..
that may stopped reaching the MyAsyncTask()
check this may help you..
#Override
public void onLocationChanged(Location location) {
double latit =null;
double longi =null;
do
{
latit=location.getlatitude();
longi=location.getlongitude();
}while(latit!=null && longi!=null);
latitude = String.valueOf(location.getLatitude());
longitude = String.valueOf(location.getLatitude());
new MyAsyncTask().execute();
}
The getlatitude() and getlongitude() function will return double value check this documentation
http://developer.android.com/reference/android/location/Location.html#getLatitude()
Oops My Bad!
The correct code is
#Override
public void onLocationChanged(Location location) {
latitude = String.valueOf(location.getLatitude());
longitude = String.valueOf(location.getLongitude());
new MyAsyncTask().execute();
}
We have a strong GPS signal I have an app for testing how fast a GPS lock can be established I even tested the navigation app on my phone they all get pretty much insta lock bellow 10 if I just turned on the GPS.
But with this app I just never get a lock, the wile loop just keeps going on and on and the Log never shows I let it run for 10min and nothing. Am I missing something here I know there is a possible > 10min delay but other apps have no problem that are not using lastKnownLocation but pulling an actual location.
Also the gpsLocation() method is in a static Locator class.
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
Location location = Locator.gpsLocation(this);
while(location == null)
{
location = Locator.gpsLocation(this);
}
Log.w("GPS LOCATION", "LOCATION FOUND");
}
/**
* Finds users location using gps
* satelite network.
*
* #param FragmentActivity
* #return Location
*/
public static Location gpsLocation(FragmentActivity context)
{
// Fetch LocationManager service & instance of UserLocator
LocationManager provider = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
UserLocator locator = new UserLocator();
// Attempt to get a fix on users location
provider.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locator);
// Return users location using GPS Service
return locator.location;
}
/**
* Use to listen for user location updates
* TODO: Reimplement as a anonymous class
*/
class UserLocator implements LocationListener
{
// Public accessor
public Location location;
public void onLocationChanged(Location location)
{
if(location != null)
{
// We have a fix on users location
this.location = location;
}
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
I think your problem is that your location updates listener is updating the location variable inside your UserLocation class, however the variable you are checking is the one you get back from the method gpsLocation, which is null.
What you are doing is you are signing up for location updates and immediately returning the value of null and checking it over and over again, while your real location is being updated in another place.
All this is also assuming that you have declares the proper permission in your manifest file.
Try this:
Location location;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
gpsLocation(this);
while(location == null)
continue;
Log.w("GPS LOCATION", "LOCATION FOUND");
}
public static void gpsLocation(FragmentActivity context)
{
LocationManager provider = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
UserLocator locator = new UserLocator();
provider.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locator);
}
class UserLocator implements LocationListener
{
public void onLocationChanged(Location loc)
{
if(loc != null)
location = loc;
}
public void onProviderDisabled(String provider) {}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
}
With this implementation, both the listener and the while loop address the same instance of Location, so once this changes from null you will get the log message.
I would however strongly discourage putting such a while(true) loop in your onCreate method, you will be blocking the main thread, and this is generally a bad thing to do.
I have a separate class GPSTracker.java which returns the current latitude and longitude.
public class Live extends Activity implements LocationListener
{
GPSTracker gps;
Location newLocation = new Location(LocationManager.GPS_PROVIDER);
Location oldLocation = new Location(LocationManager.GPS_PROVIDER);
float distanceTravelled=0;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_live);
startactivity();
}
startactivity:
public void startactivity()
{
gps = new GPSTracker(Live.this);
if(gps.canGetLocation())
{
double latitude = gps.getLatitude();
double longitude = gps.getLongitude();
Toast.makeText(getApplicationContext(), "Your Location is: \nLat: " + latitude + "\nLong: " + longitude, Toast.LENGTH_LONG).show();
newLocation.setLatitude(latitude);
newLocation.setLongitude(longitude);
}
else
{
gps.showSettingsAlert();
}
}
Whenever I do that commented out part, it gives an exception even if I declare the location outside the startactivity() in the Live class. Otherwise it displays the correct latitude and longitude.
I want to use it to calculate distance travelled, like this:
#Override
public void onLocationChanged(Location location)
{
oldLocation.set(newLocation);
startactivity();
distanceTravelled+=newLocation.distanceTo(oldLocation);
String stringdistance= Float.toString(distanceTravelled);
TextView distance = (TextView) findViewById(R.id.textDistance);
distance.setText(stringdistance);
}
Is that logic correct?
And the onLocationChanged() does not finds the newLocation in the startactivity(). How can I do that?
But first thing is I get an exception when I use location in startactivity().
But first thing is I get an exception when I use location in startactivity().
Location newLocation;
newLocation.setLatitude(latitude);
newLocation.setLongitude(longitude);
You are trying to execute above code, but see newLocation is null (by default value) and you are trying to use null instead of Object and it results in NullPointerException.
In order to create a new object in Java, you have to use:
Location newLocation = new Location("test");
You are trying to set the longitude and latitude to a non-object. This creates a NullPointerException. You have to create the ojbect location before you use it.
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.