Why does my OnLocationChanged() never get called?
Asked Answered
R

3

15

What I am trying to do:

I am trying to develop an app that only requires the user's location at the start of one activity. So only when the user is within the activity, the location gets updated either by network or GPS. Accordingly, the user may choose an indoor map.

What is my problem:

However, I find that the app is always using the history location, and never updates the location. I suspect there must be something wrong with my

location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER)

But I am not sure where the problem is.

Related code snippet:

In my Activity, I have:

    locationDetector = new LocationDetector(MapSelectionActivity.this);
    // try to get the current location
    if (locationDetector.checkLocationServiceAvailability()) {
        location = locationDetector.getLocation();
        if (location != null) {
            latitude = location.getLatitude();
            longitude = location.getLongitude();
        }
        Log.d("MapSelectionActivity", latitude + " " + longitude);
        //locationDetector.stopLocalization(); // stop the localization to save the energy
    } else { // if no location service, requires the user to turn GPS on
        locationDetector.showSettingsAlert();
    }

My LocationDetector class is as follows:

public final class LocationDetector implements LocationListener {

    private final Context mContext;

    private boolean isNetworkEnabled = false;
    private boolean isGPSEnabled = false;
    private boolean canGetLocation = false;

    private Location location;
    private String providerUsed;

    // The minimum distance to change Updates in meters
    private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 0; // 0 meters
    // The minimum time between updates in milliseconds
    private static final long MIN_TIME_BW_UPDATES = (long) (1000 * 60 * 0.5); // 0.5 minute

    // Declaring a Location Manager
    protected LocationManager locationManager;

    // constructor
    public LocationDetector(Context context) {

        this.mContext = context;

        locationManager = (LocationManager) mContext.getSystemService(Context.LOCATION_SERVICE);
    }

    // NOTE call  checkLocationServiceAvailability(); first before calling this!
    public Location getLocation() {
// I SUSPECT SOMETHING IS WRONG HERE
        if (isNetworkEnabled) { // use network

            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
            Log.d("LocationDetector", "Using Network");
            if (locationManager != null) {
                location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
            }

            providerUsed = "Network";

        } else if (isGPSEnabled) { // use GPS

            if (location == null) {
                locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
                Log.d("LocationDetector", "Using GPS");
                if (locationManager != null) {
                    location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
                }
            }

            providerUsed = "GPS";

        } else { // neither the network nor the GPS is on

            providerUsed = null;

            Toast.makeText(mContext, "Location service is unavaliable", Toast.LENGTH_SHORT).show();
        }

        return location;
    }

    // call this to restart requesting the detecting
    public void startLocalization() {

        if (locationManager != null) {
            locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
            locationManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, MIN_TIME_BW_UPDATES, MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
        }
    }

    // call this to stop the detecting to save power
    public void stopLocalization() {

        if (locationManager != null) {
            locationManager.removeUpdates(LocationDetector.this);
        }
    }

    // check location service availability
    public boolean checkLocationServiceAvailability() {

        // check GPS on or off
        isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
        // check Internet access
        ConnectivityManager connectivityManager = (ConnectivityManager) mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
        NetworkInfo netInfo = connectivityManager.getActiveNetworkInfo();
        if (netInfo != null && netInfo.isConnected()) {
            isNetworkEnabled = true;
        } else {
            isNetworkEnabled = false;
        }

        if (isGPSEnabled || isNetworkEnabled) {
            canGetLocation = true;
        } else {
            canGetLocation = false;
        }

        return canGetLocation;
    }

    public String getLocationProvider() {

        return providerUsed;
    }

    // show alert dialog to direct the users to the settings
    public void showSettingsAlert() {

        AlertDialog.Builder alertDialog = new AlertDialog.Builder(mContext);

        // make it uncancellable
        alertDialog.setCancelable(false);

        // Setting Dialog Title
        alertDialog.setTitle("Forgot to turn GPS on?");

        // Setting Dialog Message
        alertDialog.setMessage("Currently there is no Internet access.\n\nLocalization requires GPS when Internet is unavailiable.\n\nDo you want to enable GPS so as to proceed?");

        // On pressing Settings button
        alertDialog.setPositiveButton("Yes", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
                mContext.startActivity(intent);

                Toast.makeText(mContext, "After enabling GPS, press the physical 'Back' button to return", Toast.LENGTH_LONG).show();
            }
        });

        // on pressing cancel button
        alertDialog.setNegativeButton("No", new DialogInterface.OnClickListener() {
            public void onClick(DialogInterface dialog, int which) {
                dialog.cancel();

                Toast.makeText(mContext, "No location service, please choose map manually", Toast.LENGTH_LONG).show();
            }
        });

        // Showing Alert Message
        alertDialog.show();
    }

    @Override
    public void onLocationChanged(Location _location) {
// IT NEVER GETS CALLED
        location = _location;

        // update the text view
        MapSelectionActivity.coordinatesTextView.setText("(" + Math.round(location.getLatitude() * 1000) / 1000.0 + ", " + Math.round(location.getLongitude() * 1000) / 1000.0 + ")");

        // update the marker on Google Maps
        MapSelectionActivity.googleMap.clear();
        MapSelectionActivity.googleMap.addMarker(new MarkerOptions().position(new LatLng(location.getLatitude(), location.getLongitude())).title("I am here!"));
        MapSelectionActivity.googleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 15)); // 15 is the approporiate zooming level

        // re-suggest the map
        int recommendedMapSequenceNumber = MapSelectionActivity.mapDatabase.getMapSequenceNumber(location.getLatitude(), location.getLongitude());
        MapSelectionActivity.recommendedMapTextView.setTextColor(Color.parseColor("red"));
        if (recommendedMapSequenceNumber == -1) { // the so-called nearest is still too far

            Toast.makeText(mContext, "Please manually select one to proceed", Toast.LENGTH_LONG).show();
            MapSelectionActivity.recommendedMapTextView.setText("No recommended maps");
            MapSelectionActivity.autoSelectButton.setEnabled(false);
        } else { // suggest a map

            Toast.makeText(mContext, "One suitable map found", Toast.LENGTH_SHORT).show();
            MapSelectionActivity.recommendedMapTextView.setText(MapSelectionActivity.mapDatabase.getMapName(recommendedMapSequenceNumber));
        }

        Toast.makeText(mContext, "New location detected", Toast.LENGTH_SHORT).show();
    }

    @Override
    public void onProviderDisabled(String provider) {
    }

    @Override
    public void onProviderEnabled(String provider) {
    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

}

I never see the Toast in onLocationChanged(), which means that it never gets called! Also from the map, I can see the position is not updated.

Rehash answered 23/7, 2013 at 8:7 Comment(10)
(1000 * 60 * 0.5) this will be actually 30 seconds, you need change it to (1000 * 60 * 5) for 5 minutes interval, However this is not the actual problem.Duchess
Have you given enough permissions in Manifest ?Duchess
@Duchess - Those 5 minutes I guess are concerning the GPS_PROVIDER, because they are quite OK for the NETWORK_PROVIDER?Epileptic
ok good, now comment this code if (locationManager != null) { location = locationManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER); } and try executing your code once again.Duchess
@perfectionm1ng - You might be getting the location refreshed by the GPS_PROVIDER, but since you give it 30 seconds for the refresh - it's never enough, and that's why it just does not refresh it. On the other side, you are getLastKnownLocation(LocationManager.NETWORK_PROVIDER), which is never refreshed, since the prefered provider is GPS - right?Epileptic
@Duchess just tried. Commenting that off causes no location is found. The coordinates are (-1, -1), because that is the way I initialize them to be like that.Rehash
ur code is correct ...bt u need to do real testing ...i mean open place if u r using LocationManager.GPS_PROVIDER and i hve tested this code https://mcmap.net/q/826651/-localization-is-returning-null-what-is-wrong-with-the-code working correct for me... and to get more accurate locaiton plz check developer.android.com/about/versions/android-4.2.html#BehaviorsConstabulary
@Epileptic I am currently testing it indoors. And my phone is connected to the Internet. I print the provider out, and it is indeed the NETWORK_PROVIDER. These are all correct, I think. Regarding the 30s, I change it to 0. It still does not work.Rehash
@perfectionm1ng - changing it to zero is going to only worsen it. You need to extend it and give more time for the Provider to refresh the data - 0 is of no use.Epileptic
Just a suggestion but you might want to try using LocationServices.FusedLocationApi to make your requests. It should save you some time and effort.Trentontrepan
H
1

Since this seems to be a common issue with getting Android Locations, I'll put down a quick checklist of common fixes:


  1. Check your manifest!

    One of the most common issues is that the right permissions were never given. If you are using GPS (with or without Network), use <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>, else use <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>. Google's FusedLocationApi requires ACCESS_FINE_LOCATION.


  1. (For Android 6+) Check runtime permissions!

    Check for and request permissions! If you are never given permissions, you'll end up with crashes, or worse (if you are catching all exceptions), you'll end up with no indication of anything! It doesn't matter if the user grants you permission at the start of the app, always check to see if you have permissions for all calls. The user can easily go to their settings and revoke them.


  1. Double check your code!

    Are you sure you are passing in the right listener? Did you add that BroadcastReceiver or IntentService to your manifest? Are you using PendingIntent.getService() on a BroadcastReceiver class, or getBroadcast() on an IntentService class? Are you sure you are not unregistering your listener somewhere else in your code immediately after requesting?


  1. Check device settings!

    Obviously, make sure you have location services turned on.

    enter image description here

    If you are using Network services, did you turn on "Scanning Always Available"? Do you have your location mode set to "Best" ("High Accuracy") or "Battery Saving" ("Network Only")?

    enter image description here

    If you are using GPS, did you turn on "Best" ("High Accuracy") or "Device only" in location mode?

    enter image description here


  1. Double check your code!

    Yes, this is on here twice. Did you try using a LocationListener instead of a PendingIntent, or vice-versa, to ensure you actually implemented LocationManager properly? Are you sure that the location request isn't being removed in some part of the Activity or Service lifecycle that you didn't expect to happen?


  1. Check your surroundings!

    Are you testing GPS on the first floor of a building in the middle of San Francisco? Are you testing Network locations in the middle of nowhere? Do you work in a secret underground bunker void of all radio signals, wondering why your device isn't getting location? Always double check your surroundings when trying to troubleshoot location problems!


There could be many other less obvious reasons why location isn't working, but before searching out those esoteric fixes, just run through this quick checklist.

Hospitalization answered 20/2, 2017 at 18:36 Comment(0)
U
0

This is right, you might face a hardware issue. Please install on device the App :GPS STATUS in order to see if your GPS is workin fine!

Unspeakable answered 13/11, 2015 at 15:44 Comment(0)
S
0

locationManager.requestLocationUpdates (LocationManager.GPS_PROVIDER, MIN_TIME_BW_UPDATES,MIN_DISTANCE_CHANGE_FOR_UPDATES, this);

For this line

MIN_DISTANCE_CHANGE_FOR_UPDATES = 0 meter.

MIN_TIME_BW_UPDATES = 1000 seconds.

Coming to your question, onLocationChanged() will be called if the current location update is not matching with last known location.

The updated location will be changed for every minTime (in my case 1000 milli sec) and also if device moved minDistance (in my case 0 meters) distance.

I hope you will understand this.

Stapleton answered 17/11, 2016 at 12:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.