So, I have an Android application that is asking for the GPS from the LocationManager class.
I have an Activity that wants to use that data, and a custom class that implements LocationListener.
I have written some custom methods to return the GPS values to my other class.
Currently, I am asking for and releasing the location updates from my Activity class, not my implementation of the LocationListener class... I think this is the right way to go about it, but I just wanted to get any feedback on the life cycle, etc. (the class that implements LocationListener is not an Activity, so I don't think I even could call onPause() etc, ?)
This is the Activity:
package com.jessescott.sonicity;
import android.app.Activity;
import android.content.Context;
import android.view.View;
import android.widget.TextView;
import android.location.Location;
import android.location.LocationManager;
import android.location.LocationListener;
public class PlayActivity extends Activity {
// GLOBALS
private static final String TAG = "SoniCity";
LocationManager locationManager;
MyLocationListener locationListener;
TextView latitude, longitude;
TextView ActualLatitude, ActualLongitude;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.play_layout);
// GPS
locationListener = new MyLocationListener(this);
// TextViews
latitude = (TextView) findViewById(R.id.Latitude);
longitude = (TextView) findViewById(R.id.Longitude);
ActualLatitude = (TextView) findViewById(R.id.ActualLat);
ActualLatitude.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.v(TAG, "Asking For New Latitude");
ActualLatitude.setText(locationListener.getCurrentLatitude());
}
});
ActualLongitude = (TextView) findViewById(R.id.ActualLon);
ActualLongitude.setOnClickListener(new View.OnClickListener() {
#Override
public void onClick(View v) {
Log.v(TAG, "Asking For New Latitude");
ActualLongitude.setText(locationListener.getCurrentLongitude());
}
});
}
#Override
protected void onPause() {
super.onPause();
// Stop GPS
locationManager.removeUpdates(locationListener);
locationManager = null;
}
#Override
protected void onResume() {
super.onResume();
locationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 2000, 5, locationListener);
}
#Override
public void onDestroy() {
super.onDestroy();
}
} /* */
... and this is the LocationListener implementation :
package com.jessescott.sonicity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.os.Bundle;
import android.util.Log;
class MyLocationListener implements LocationListener {
private static final String TAG = "SoniCity";
float currentLatitude = 0;
float currentLongitude = 0;
public MyLocationListener(Context context) {
super();
}
// Define all LocationListener methods
public void onLocationChanged(Location location) {
currentLatitude = (float)location.getLatitude();
currentLongitude = (float)location.getLongitude();
}
public void onProviderDisabled (String provider) {
Log.v(TAG, "Provider is " + provider);
}
public void onProviderEnabled (String provider) {
Log.v(TAG, "Provider is " + provider);
}
public void onStatusChanged (String provider, int status, Bundle extras) {
Log.v(TAG, "Status is " + status);
}
// Custom Methods
public String getCurrentLatitude() {
String lat = Float.toString(currentLatitude);
return lat;
}
public String getCurrentLongitude() {
String lon = Float.toString(currentLongitude);
return lon;
}
} /* */
I guess since I've moved it to a separate class (they used to be the same one), I just want to make sure I'm calling th request/remove in the right place.
I haven't looked at your code in detail, but from what I've seen it looks fine to me. onResume() is the right place to register your listener, and onPause() is the right place to unregister it, so that e.g. battery life is optimised.
A couple of things to consider going forward:For a robust app, make sure you pay attention to the information that you get from onStatusChanged, onProviderEnabled and onProviderDisabled. I've seen various questions on stackoverflow.com to which the answer was to pay attention to status changes etc.Also for a better estimate of location, you might consider using the Location.accuracy value, because the accuracy of GPS location estimates can change. One minute they might be very accurate, but then the visible satellites change and the accuracy can suddenly be much lower. In my apps I use a simple Kalman filter for this, and I posted the code for it in my answer to the question Smooth GPS data.
Related
My app has two activities that need GPS, so I tried to offload it to a separate class that either activity could use. I found an answer here that looked easy enough
Android - Best way to implement LocationListener across multiple activities
But of course, it's not working for me. I was wondering if anyone can see the issue. I used pretty much exactly the same code, but I got rid of the gps settings dialog.
Here's my GPS class
package fieldlayout.skipmorrow.com.fieldlayout;
import android.app.Activity;
import android.content.Context;
import android.location.LocationManager;
import android.os.Bundle;
import android.location.LocationListener;
import android.location.Location;
import android.util.Log;
/**
* Created by skip on 4/20/2015.
*/
public class GPS {
private IGPSActivity main;
// Helper for GPS-Position
private LocationListener mlocListener;
private LocationManager mlocManager;
private boolean isRunning;
public GPS(IGPSActivity main) {
this.main = main;
// GPS Position
mlocManager = (LocationManager) ((Activity) this.main).getSystemService(Context.LOCATION_SERVICE);
mlocListener = new MyLocationListener();
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
// GPS Position END
this.isRunning = true;
Log.i("FieldLayout_GPS", "GPS Object created");
}
public void stopGPS() {
if(isRunning) {
mlocManager.removeUpdates(mlocListener);
this.isRunning = false;
}
Log.i("FieldLayout_GPS", "stopGPS");
}
public void resumeGPS() {
mlocManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, mlocListener);
this.isRunning = true;
Log.i("FieldLayout_GPS", "resumeGPS");
}
public boolean isRunning() {
return this.isRunning;
}
public class MyLocationListener implements LocationListener {
private final String TAG = MyLocationListener.class.getSimpleName();
#Override
public void onLocationChanged(Location loc) {
GPS.this.main.locationChanged(loc.getLongitude(), loc.getLatitude());
Log.i("FieldLayout_GPS", "onLocationChanged");
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.i("FieldLayout_GPS", "onStatusChanged");
}
#Override
public void onProviderEnabled(String provider) {
Log.i("FieldLayout_GPS", "onProviderEnabled");
}
#Override
public void onProviderDisabled(String provider) {
Log.i("FieldLayout_GPS", "onProviderDisabled");
}
}
}
The interface file
package fieldlayout.skipmorrow.com.fieldlayout;
/**
* Created by skip on 4/20/2015.
*/
public interface IGPSActivity {
public void locationChanged(double longitude, double latitude);
}
And my implementation from my activity
package fieldlayout.skipmorrow.com.fieldlayout;
import android.content.Context;
import android.content.Intent;
public class StartActivity extends ActionBarActivity implements IGPSActivity{
private Location currentLocation;
private GPS gps;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_start);
gps = new GPS(this);
}
#Override
protected void onResume() {
if (!gps.isRunning()) gps.resumeGPS();
super.onResume();
}
#Override
protected void onStop() {
// Disconnecting the client invalidates it.
Log.i("FieldLayout_StartAct", "onStop called. Disconnecting GPS client");
gps.stopGPS();
super.onStop();
}
#Override
public void locationChanged(double longitude, double latitude) {
Log.i("FieldLayout_StartAct", "locationChanged");
currentLocation.setLatitude(latitude);
currentLocation.setLongitude(longitude);
}
}
The only log I am seeing is the creation of the GPS object. None of the other methods in the listener are being executed.
GPS class constructor contains this row:
public GPS(IGPSActivity main) {
this.main = main;
// GPS Position
mlocManager = (LocationManager) ((Activity) this.main).getSystemService(Context.LOCATION_SERVICE);
...
}
And your interface looks like this:
public interface IGPSActivity {
public void locationChanged(double longitude, double latitude);
}
So, the GPS class get an interface, and you want to cast it into an Activity to get a system service from it. That is not going to work.
Change your GPS class a little bit. For example:
public GPS(IGPSActivity main, Activity activity){
mlocManager = (LocationManager) activity.getSystemService(Context.LOCATION_SERVICE);
...
}
Call this in your activity:
gps = new GPS(this, this);
my android application can detect longitude and latitude. but it take some time. my app has 9 activates and last activity should send location to data base. any one can give a solution for this. i want to detect location soon as possible, what did missed in my code?
package com.example.zlocation;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends Activity implements LocationListener{
protected LocationManager locationManager;
protected LocationListener locationListener;
protected Context context;
protected TextView txtLat;
String lat;
String provider;
protected String latitude,longitude;
protected boolean gps_enabled,network_enabled;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
txtLat = (TextView) findViewById(R.id.textView1);
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, this);
}
#Override
public void onLocationChanged(Location location) {
txtLat = (TextView) findViewById(R.id.textView1);
txtLat.setText("Latitude:" + location.getLatitude() + ", Longitude:" + location.getLongitude());
}
#Override
public void onProviderDisabled(String provider) {
Log.d("Latitude","disable");
}
#Override
public void onProviderEnabled(String provider) {
Log.d("Latitude","enable");
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
Log.d("Latitude","status");
}
}
You are trying to get the location from gps provider.The problem with gps is however vit is accurate but it takes time in starting the gps and providing a location it can take anything from 2-30 seconds to provide the location if you want location as soon as possible have a look at fused location provider by google and implement it in that you can define the time after you want the location updates or from my personal experience i would suggest you to have a look at littlefluffy location library it is easier to implement.
i recently asked a question for implementation of toast message when the GPS is not enabled.
of this i knew it was possible.
Is it possible to automatically activate the GPS function in the background.
When i remotely activate the application in the background. can i activate the GPS from the phone itself aswell without the other phone reporting anything to the user ?
the situation is like this.
we have a project named ParentalControl Application. So a parent has to be able to track its child remotely.
does anyone have suggestion or ideas ... ?
if it is of anyhelp
this is the code i'm using at the moment.
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity
{
TextView TxtLat;
TextView TxtLong;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TxtLat = (TextView) findViewById(R.id.TxtLat);
TxtLong = (TextView) findViewById(R.id.TxtLong);
LocationManager lm = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
// implementation of TOASTS
if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER))
{
Toast toast= Toast.makeText(MainActivity.this, " You can improve the accuracy by turning on the GPS", Toast.LENGTH_SHORT);
toast.show();
}
LocationListener ll = new myLocationListener();
lm.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, ll);
}
class myLocationListener implements LocationListener
{
#Override
public void onLocationChanged(Location location)
{
if (location != null)
{
double pLong = location.getLongitude();
double pLat = location.getLatitude();
TxtLat.setText(Double.toString(pLat));
TxtLong.setText(Double.toString(pLong));
}
}
#Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
#Override
public void onProviderEnabled(String s) {
}
#Override
public void onProviderDisabled(String s) {
}
}
}
I am working on geo-loaction applciation where I need to calculate user speed, to get user speed I used LocationManager for their current location after every 30second, for this I used following code.
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 1000*30, 0, myLocationListener); //from NETWORK_PROVIDER
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 1000*30, 0, myLocationListener); //from GPS_PROVIDER
But my problem is I want location based on fix time interval here is 30second. Right now I get location after every 45second also vary. So if any know how I can set 'maxTime' to location manager then please let me know.
Also if any one know the location listener calling business logic based on time / distance also please let me know.
Thanks in advanced.
Use the new introduced Fused Location Provider API
import android.app.IntentService;
import android.content.Intent;
import android.location.Location;
import android.os.Bundle;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesClient;
import com.google.android.gms.location.LocationClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
public class Locations extends IntentService implements
GooglePlayServicesClient.ConnectionCallbacks,
GooglePlayServicesClient.OnConnectionFailedListener, LocationListener {
public Locations() {
super("Locations");
Log.d("Locations", "Location service started... ");
}
private LocationRequest locationRequest;
private LocationClient locationClient;
private Location location;
private static final int INTERVAL = 1800000;
private static final int FASTEST_INTERVAL = 60000;
#Override
protected void onHandleIntent(Intent intent) {
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
locationClient = new LocationClient(this, this, this);
locationClient.connect();
}
#Override
public void onLocationChanged(Location l) {
// do something on Location change.
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
}
#Override
public void onConnected(Bundle arg0) {
Log.w("Locations", "Location client connected...");
// get last location
location = locationClient.getLastLocation();
Log.w("Locations", "Latitude : "+location.getLatitude() + "");
Log.w("Locations", "Longitude : "+location.getLongitude() + "");
}
#Override
public void onDestroy() {
if (locationClient.isConnected()) {
locationClient.removeLocationUpdates(this);
}
locationClient.disconnect();
}
#Override
public void onDisconnected() {
}
}
Source https://developer.android.com/training/location/index.html
So i am using the getLastKnownLocation method to get the Location loc of the device but it returns null unless there is a GPS fix. Is there a way to delay execution of getLastKnownLocation until the GPS has a valid location to provide?
package test.example;
import android.app.Activity;
import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;
public class testGPS extends Activity
{
private LocationManager lm;
private LocationListener locationListener;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView tv = new TextView(this);
//---use the LocationManager class to obtain GPS locations---
lm = (LocationManager)
getSystemService(Context.LOCATION_SERVICE);
locationListener = new MyLocationListener();
lm.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
0,
0,
locationListener);
Location loc = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (loc != null) {
tv.setText("Hello, lat is " + loc.getLatitude() + " lon is " + loc.getLongitude());
setContentView(tv);
} else {
tv.setText("Hello, loc is null :(");
setContentView(tv);
}
}
private class MyLocationListener implements LocationListener
{
#Override
public void onLocationChanged(Location loc) {
}
#Override
public void onProviderDisabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onProviderEnabled(String provider) {
// TODO Auto-generated method stub
}
#Override
public void onStatusChanged(String provider, int status,
Bundle extras) {
// TODO Auto-generated method stub
}
}
}
You're misunderstanding how location works in Android. getLastKnownLocation() doesn't provide null unless the GPS has a fix, it returns null if there's no previous known location - the location does not have to come from the GPS (it could come via wifi or mobile network) and calling that method does not instruct the location framework to return a new location.
You need to start again, after fully reading and understanding this page:
http://developer.android.com/guide/topics/location/obtaining-user-location.html
It includes everything you need to handle locations in Android, and you need a framework that suits the needs of your application. If you want the location to persist (to reduce the use of the GPS) then you can save the location to preferences, and/or enable network location sending (not as accurate, but usually faster). For some apps you may want to grab a rough location quickly (using last-known, or the network location provider) and then update it when an accurate GPS location arrives. But the approach you use will vary by app.