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.
Related
I'm intercepting the click from the mylocation button like so:
map.setMyLocationEnabled(true);
map.setOnMyLocationButtonClickListener(new GoogleMap.OnMyLocationButtonClickListener() {
#Override
public boolean onMyLocationButtonClick() {
bMyLocationClicked = true;
return false;
}
});
and then making it zoom in like so:
// Acquire a reference to the system Location Manager
LocationManager locationManager = (LocationManager) parentActivity.getSystemService(Context.LOCATION_SERVICE);
LocationListener myLocationListener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
if (bMyLocationClicked) {
bMyLocationClicked = false;
map.moveCamera(CameraUpdateFactory.zoomTo(18f));
}
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
// Register the listener with the Location Manager to receive location updates
locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, myLocationListener);
Everything works fine, except that there's an extremely long delay between pressing the mylocation button and the zoom in actually happening. The centering of the map finishes and about 2 seconds later the map actually zooms in. How can I speed this up?
I'm looking for an answer where I stay using the mylocation button rather than implementing my own.. although, if there's absolutely no alternative, I'll build a custom center/zoom button.
I am making an app that will draw a user's path on a map. This is all working fine. However, I also want to continue to collect the path (when requested by the user) when the app is in the background. This also is working pretty good, but occasionally I get "glitches". See this map for an example:
GoogleMap
I believe what is happening is that when I start the service, I am getting the "last known location" instead of the current location. I have tried several techniques without much luck so far. Some other ideas that I have have had:
Passing the GoogleApiClient from the Activity to the Service, already connected (is this possible?)
Ignoring the first "X" location updates in the service (how big does "X" need to be?)
Cleansing the path, to remove "bad" locations (what kind of algorithm would I need to figure out what a "bad" location is...it is easy to see in the attached map, but I am not sure how to do it in code).
Any other suggestions on the best way to handle this scenario?
Here is some code to give you an idea of the current functionality:
Activity.java:
#Override
protected void onCreate(Bundle savedInstanceState) {
...
setUpMapIfNeeded();
buildGoogleApiClient();
createLocationRequest();
...
}
private void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
}
private void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setInterval(Utils.LOCATION_UPDATE_MS);
locationRequest.setFastestInterval(Utils.FASTEST_LOCATION_UPDATE_MS);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
Log.v("Connected", String.format("Location: %f, %f, %f", location.getLatitude(), location.getLongitude(), location.getAccuracy()));
if (location != null) {
updateMap();
}
}
#Override
protected void onPause() {
super.onPause();
LocalBroadcastManager.getInstance(this).unregisterReceiver(pathReceiver);
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
if (isNavigatingTo()) {
Preferences.save(Preferences.PREFERENCE_NAVIGATE_TO, navigateToWaypoint.getId());
} else {
Preferences.remove(Preferences.PREFERENCE_NAVIGATE_TO);
}
if(isRecordingTrack()){
// Start the PathSevice to continue recording the track.
Intent pathServiceIntent = new Intent(this, PathService.class);
pathServiceIntent.putExtra(Utils.PATH_EXTRA, path);
startService(pathServiceIntent);
}
}
...
PathService.java:
#Override
public void onCreate() {
buildGoogleApiClient();
createLocationRequest();
googleApiClient.connect();
super.onCreate();
}
private void buildGoogleApiClient() {
googleApiClient = new GoogleApiClient.Builder(this).addConnectionCallbacks(this).addOnConnectionFailedListener(this).addApi(LocationServices.API).build();
}
private void createLocationRequest() {
locationRequest = new LocationRequest();
locationRequest.setInterval(Utils.LOCATION_UPDATE_MS);
locationRequest.setFastestInterval(Utils.FASTEST_LOCATION_UPDATE_MS);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
#Override
public void onConnected(Bundle bundle) {
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
#Override
public void onLocationChanged(Location location) {
path.addPoint(location.getLatitude(), location.getLongitude());
}
So the solution was in my question...as it seemed I was adding the "last known location" when returning back to the activity from the service (see onConnected in the Activity class above).
I now only start the location requests in the onConnected.
So I have implemented the new Fused Location Provider API to get a location of the user but for some reason, I cannot get any location unless the GPS is on. Not always, will users have their GPS on and I would like to not have to ask them to turn their GPS on every time the load the app.
How can I tell the API to give me a location with whatever provider it has available?
Here is my code:
public class FusedLocationService implements
LocationListener,
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
public interface OnLocationChangedListener {
public void OnLocationChanged(Location location);
}
private final String TAG = "SE8611";
private boolean mRequestingLocationUpdates = true;
private OnLocationChangedListener mCallBack;
Service locationService;
private LocationRequest locationRequest;
private GoogleApiClient googleApiClient;
private Location mCurrentLocation;
private FusedLocationProviderApi fusedLocationProviderApi = LocationServices.FusedLocationApi;
public FusedLocationService(Service locationService, final long INTERVAL, final long FASTEST_INTERVAL) {
Logger.log(TAG, "FusedLocationService called");
this.mCallBack = (OnLocationChangedListener)locationService;
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
this.locationService = locationService;
googleApiClient = new GoogleApiClient.Builder(locationService)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
if (googleApiClient != null) {
googleApiClient.connect();
}
}
#Override
public void onConnected(Bundle connectionHint) {
if(mRequestingLocationUpdates) {
startLocationUpdates();
}else{
Logger.log(TAG, "Location updates are already running.");
}
}
protected void startLocationUpdates() {
this.fusedLocationProviderApi.requestLocationUpdates(
googleApiClient, locationRequest, this);
this.mRequestingLocationUpdates = false;
}
#Override
public void onLocationChanged(Location mCurrentLocation) {
Logger.log(TAG, "onLocationChanged called");
this.mCurrentLocation = mCurrentLocation;
this.mCallBack.OnLocationChanged(this.mCurrentLocation);
}
public void startLocationUpdatesAfterResume(){
if (googleApiClient.isConnected() && !mRequestingLocationUpdates) {
Logger.log(TAG, "startLocationUpdatesAfterResume called");
this.startLocationUpdates();
}
}
public void stopLocationUpdates() {
Logger.log(TAG, "stopping Location Updates");
LocationServices.FusedLocationApi.removeLocationUpdates(
googleApiClient, this);
}
public Location getLocation() {
return this.mCurrentLocation;
}
#Override
public void onConnectionSuspended(int i) {
this.mRequestingLocationUpdates = true;
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
this.mRequestingLocationUpdates = true;
}
}
I had the same issue like you, which is not an issue at all.
Android used to have a GPS button that let you control it directly, but they replaced it with a Location button which works different.
In order to get any type of location, you must turn it on.
Like you, I thought the Location button turns on and off the GPS only, but that's not the case.
You can control the GPS by changing the location mode:
1. High accuracy (GPS, Wi-Fi and mobile networks)
2. Power Saving (Wi-Fi and mobile networks)
3. GPS only
I think I have found the solution of the problem.
If you go to Settings -> Privacy and Safety -> Location, you would notice that Location is not only GPS, but it actually lets user decide which providers can be used. For example, you can set that only WiFi and Cellular should be used to obtain any locations
Disabling Location option will disable all providers at once, not only GPS.
To test that app for users with only WiFi can get a location – change setting to "Wifi+Cellular".
you seem to be using LocationRequest.PRIORITY_HIGH_ACCURACY, which prefers using GPS above and over other methods. You might want to use PRIORITY_BALANCED_POWER_ACCURACY, which will use WiFi and cell towers before using GPS.
Also, since PRIORITY_BALANCED_POWER_ACCURACY is a "coarse" level of accuracy, you might want to change the location permission in your manifest appropriately.
The training documentation details more information about the priority flags, you might also want to go through it.
I want to get Mobile Current Location ,When I install Application ,than first time get correct lat long but than after every time display first time get location.please give me correct code for get every time correct lat long.
_ In Sort My Location is Not Update,or Location cach not clear.
->my code
public class MyLocationListener implements LocationListener {
private LocationManager mLocationManager;
private Location currentLocation;
public MyLocationListener(Context context) {
mLocationManager = (LocationManager) context
.getSystemService(Context.LOCATION_SERVICE);
currentLocation = mLocationManager
.getLastKnownLocation(LocationManager.GPS_PROVIDER);
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER, 0, 0, this);
}
public Location getBestLocationAvailable() {
return currentLocation;
}
#Override
public void onLocationChanged(Location newBestLocation) {
mLocationManager.removeUpdates(this);
currentLocation = newBestLocation;
}
#Override
public void nProviderDisabled(String arg0) {
}
#Override
public void onProviderEnabled(String arg0) {
}
#Override
public void onStatusChanged(String arg0, int arg1, Bundle arg2) {
}
}
MyLocationListener loc = new MyLocationListener(MainActivity.this);
Location location = loc.getBestLocationAvailable();
system.out.println(location.getLatitude()+" "+location.getLongitude);
give me write answer,why i get ever time old lat Long?
Try to get latitude and longitude inside the onLocationChnage()
public void onLocationChanged(Location loc) {
//sets and displays the lat/long when a location is provided
String lat = loc.getLatitude();
String longt= loc.getLongitude();
Toast.makeText(getApplicationContext(),"Lat"+ lat+ "Long"+longt, Toast.LENGTH_LONG).show();
}
Add the permission in menifest
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_MOCK_LOCATION" />
You code looks right, but why did you add this string?
mLocationManager.removeUpdates(this);
So, you will receive only one location update and after it your listener will be disabled. Try to remove this string and check again.
Also, please note that different devices take different time for GPS "cold" start. Before testing your app, check GPS status in another app (for example maps, or GPS monitor). If your device on "cold" state, you will not receive any updates long time (10-20 minutes or more).
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.